Open
Description
Did you check the tree-sitter docs?
- I have read all the tree-sitter docs if it relates to using the parser
Is your feature request related to a problem? Please describe.
Currently, else if
blocks are parsed as nested if
statements. For example,
int main() {
if (0) {
;
} else if (0) {
;
} else if (0) {
;
}
}
(translation_unit ; [0, 0] - [9, 0]
(function_definition ; [0, 0] - [8, 1]
type: (primitive_type) ; [0, 0] - [0, 3]
declarator: (function_declarator ; [0, 4] - [0, 10]
declarator: (identifier) ; [0, 4] - [0, 8]
parameters: (parameter_list)) ; [0, 8] - [0, 10]
body: (compound_statement ; [0, 11] - [8, 1]
(if_statement ; [1, 2] - [7, 3]
condition: (parenthesized_expression ; [1, 5] - [1, 8]
(number_literal)) ; [1, 6] - [1, 7]
consequence: (compound_statement ; [1, 9] - [3, 3]
(expression_statement)) ; [2, 4] - [2, 5]
alternative: (else_clause ; [3, 4] - [7, 3]
(if_statement ; [3, 9] - [7, 3]
condition: (parenthesized_expression ; [3, 12] - [3, 15]
(number_literal)) ; [3, 13] - [3, 14]
consequence: (compound_statement ; [3, 16] - [5, 3]
(expression_statement)) ; [4, 4] - [4, 5]
alternative: (else_clause ; [5, 4] - [7, 3]
(if_statement ; [5, 9] - [7, 3]
condition: (parenthesized_expression ; [5, 12] - [5, 15]
(number_literal)) ; [5, 13] - [5, 14]
consequence: (compound_statement ; [5, 16] - [7, 3]
(expression_statement)))))))))) ; [6, 4] - [6, 5]
This structure is suboptimal for various reasons.
-
If the source contains very long
else if
chain, and a query pattern has a (editor-specific) predicate that climbs up the tree, processing the predicate can be very slow. For example, Neovim's#has-ancestor?
predicate can be slow: Poor performance with Treesitter highlighting on deep if-else in c neovim/neovim#24965. -
Naively folding each
(if_statement)
would create a nested fold for eachelse if
, resulting in deeply nested folds. What user would want is to have fold for each body ofelse if
.
Describe the solution you'd like
The entire if
-else if
-else
should be parsed as flat list. Something like this:
(if_statement
(alternative (condition) (consequence)) ; the first `if`
(alternative (condition) (consequence)) ; the first `else if`
(alternative (condition) (consequence)) ; the second `else if`
...
(else (consequence)) ; `else`
)
Describe alternatives you've considered
- For predicate performance, the predicate implementor can limit the traversal length. See perf(treesitter): bound
has-ancestor?
for highlighter neovim/neovim#27783. Other solutions: Poor performance with Treesitter highlighting on deep if-else in c neovim/neovim#24965 (comment) - For folds, one could fold each
consequence: (compound_statement)
instead ofif_statement
.
Additional context
No response