tree-sitter-heex
tree-sitter-heex copied to clipboard
Support for `case` statements
HEEx templates support the valid (if not somewhat esoteric) usage of case statements (as referenced in this Elixir Forum post). For example:
<%= case some_value do %>
<% something -> %>
Some stuff
<% something_else -> %>
Some other stuff
<% _ -> %>
Default stuff
<% end %>
The syntax currently breaks the highlighting. I have not worked with Tree-sitter grammars before, although I'm looking into it to see if I can implement this myself. If not, I would appreciate some help getting this working if possible.
As an alternative, I could definitely use a series of if blocks, but the syntax above is perfectly valid (and much more elegant and Elixir-esque IMO) so it would be nice to be able to get that working.
Thanks
I debugged this, it seems to go wrong with multiple clauses:
~H"""
<%= case @some_value do %>
<% 123 -> %>
Some stuff
<% 456 -> %>
Some stuff
<% end %>
"""
gives
sigil [0, 0] - [7, 3]
sigil_name [0, 1] - [0, 2]
quoted_content [0, 5] - [7, 0]
call [1, 4] - [1, 20]
target: identifier [1, 4] - [1, 8]
arguments [1, 9] - [1, 20]
unary_operator [1, 9] - [1, 20]
operand: identifier [1, 10] - [1, 20]
error [1, 21] - [4, 11]
arguments [2, 5] - [2, 8]
integer [2, 5] - [2, 8]
integer [4, 5] - [4, 8]
operator_identifier [4, 10] - [4, 11]
directive [1, 0] - [1, 26]
partial_expression_value [1, 3] - [1, 23]
directive [2, 2] - [2, 14]
partial_expression_value [2, 4] - [2, 11]
text [3, 4] - [3, 14]
directive [4, 2] - [4, 14]
partial_expression_value [4, 4] - [4, 11]
text [5, 4] - [5, 14]
directive [6, 0] - [6, 9]
ending_expression_value [6, 2] - [6, 6]
while
~H"""
<%= case @some_value do %>
<% 123 -> %>
Some stuff
<% end %>
"""
gives
sigil [0, 0] - [5, 3]
sigil_name [0, 1] - [0, 2]
quoted_content [0, 5] - [5, 0]
call [1, 4] - [2, 11]
target: identifier [1, 4] - [1, 8]
arguments [1, 9] - [1, 20]
unary_operator [1, 9] - [1, 20]
operand: identifier [1, 10] - [1, 20]
do_block [1, 21] - [2, 11]
stab_clause [2, 5] - [2, 11]
left: arguments [2, 5] - [2, 8]
integer [2, 5] - [2, 8]
directive [1, 0] - [1, 26]
partial_expression_value [1, 3] - [1, 23]
directive [2, 2] - [2, 14]
partial_expression_value [2, 4] - [2, 11]
text [3, 4] - [3, 14]
directive [4, 0] - [4, 9]
ending_expression_value [4, 2] - [4, 6]
When I check the first example in the original repo using playground:
fragment [0, 0] - [8, 0]
text [0, 0] - [0, 5]
directive [1, 0] - [1, 26]
partial_expression_value [1, 3] - [1, 23]
directive [2, 2] - [2, 14]
partial_expression_value [2, 4] - [2, 11]
text [3, 4] - [3, 14]
directive [4, 2] - [4, 14]
partial_expression_value [4, 4] - [4, 11]
text [5, 4] - [5, 14]
directive [6, 0] - [6, 9]
ending_expression_value [6, 2] - [6, 6]
text [7, 0] - [7, 3]
And here is where my knowledge ends.. 😅
This happens because of the way we delegate to tree-sitter-elixir. The parts within the <%/%> markers are combined and injected with tree-sitter-elixir so tree-sitter-elixir sees this:
case some_value do
something -> something_else -> _ ->
end
which causes the errors in the parse tree (:point_up:). To properly fix this, I believe the grammar would need to be rewritten to take a dependency on tree-sitter-elixir and parse HEEx and Elixir together rather than only parsing HEEx and injecting Elixir. It would be a very large change though so I'm not sure if it's a good tradeoff.
Could we inject something like:
case some_value do
something -> ; something_else -> ; _ -> ;
end
?
Tree-sitter doesn't have a way to add new text when parsing or injecting AFAIK so we're stuck with what we have in the source