elm-tooling / tree-sitter-elm

Tree sitter implementation for elm
https://elm-tooling.github.io/tree-sitter-elm/
MIT License
74 stars 12 forks source link

Parenthesized patterns and type expressions lack a container node #159

Open HiPhish opened 1 month ago

HiPhish commented 1 month ago

Hello, maintainer of HiPhish/rainbow-delimiters.nvim here. I have trouble properly determining the nesting or parenthesized patterns because the parentheses are on the same level as their content without any common parent container node. Take the following snippet:

unwrapCustomType { c } (CustomType (CustomType ({ a } as b))) =
    (a + (c * 1)) * (a - (a + (b.a * 1)))

The tree has the following structure:

(value_declaration
  functionDeclarationLeft: (function_declaration_left
    (lower_case_identifier)
    pattern: (record_pattern
      "{"
      patternList: (lower_pattern
        (lower_case_identifier))
      "}")
    pattern: "("
    pattern: (
     ;; Omitted for brevity
    )
    pattern: ")")
  (eq)
  body: (bin_op_expr
    part: (
      ;; Omitted for brevity
    )
    part: (
      ;; Omitted for brevity
    )
    part: (
      ;; Omitted for brevity
    )))

As you can see the parentheses are their own patterns. The is different from parenthesized_expr, which is a container node for the parentheses and their content.

I know very little Elm, so I don't know if this is even valid Elm code. If it is not I am gladly going to remove that pattern, but if it is I should be able to support it in rainbow delimiters.

razzeee commented 3 weeks ago

It's valid elm. Not very common one, but valid.

The thing is, that we'll probably get breakage across the whole stack, when we change this, so I'm unsure if there is bandwidth for that.

turboMaCk commented 3 weeks ago

It's probably what most people (read parser implementers) would consider valid elm syntactically. Semantically it would not make complete sense because of what CustomType must be.

What would be prefectly valid elm you can find in real world is:

unwrapCustomType { c } (CustomType1 (CustomType2 ({ a } as b))) =
    (a + (c * 1)) * (a - (a + (b.a * 1)))

Which I think is exactly the same case for your parser.

In terms of tree this should be producing something similar to this JS snipped:

let unwrapCustomType = ({ c }, { customType: {customType: { a, ...b} }}) => {
    return (a + (c * 1)) * (a - (a + (b.a * 1)))
}