Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for case statements #34

Open
arcanemachine opened this issue Aug 17, 2023 · 4 comments
Open

Support for case statements #34

arcanemachine opened this issue Aug 17, 2023 · 4 comments

Comments

@arcanemachine
Copy link

arcanemachine commented Aug 17, 2023

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

@dvic
Copy link
Contributor

dvic commented Aug 17, 2023

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.. 😅

@the-mikedavis
Copy link
Member

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.

@josevalim
Copy link
Member

Could we inject something like:

case some_value do
something ->  ; something_else  -> ; _ -> ;
end

?

@the-mikedavis
Copy link
Member

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants