tree-sitter / tree-sitter-c-sharp

C# Grammar for tree-sitter
MIT License
188 stars 51 forks source link

Improve declaration expression parsing #289

Open tamasvajk opened 1 year ago

tamasvajk commented 1 year ago

(a, var b) = (1, 2); parses as

(compilation_unit [0, 0] - [0, 20]
  (global_statement [0, 0] - [0, 20]
    (expression_statement [0, 0] - [0, 20]
      (assignment_expression [0, 0] - [0, 19]
        left: (tuple_expression [0, 0] - [0, 10]
          (argument [0, 1] - [0, 2]
            (identifier [0, 1] - [0, 2]))
          (argument [0, 4] - [0, 9]
            (declaration_expression [0, 4] - [0, 9]
              type: (implicit_type [0, 4] - [0, 7])
              name: (identifier [0, 8] - [0, 9]))))
        (assignment_operator [0, 11] - [0, 12])
        right: (tuple_expression [0, 13] - [0, 19]
          (argument [0, 14] - [0, 15]
            (integer_literal [0, 14] - [0, 15]))
          (argument [0, 17] - [0, 18]
            (integer_literal [0, 17] - [0, 18])))))))

This looks correct. But var (a, b) = (1, 2); parses as

(compilation_unit [0, 0] - [0, 20]
  (global_statement [0, 0] - [0, 20]
    (local_declaration_statement [0, 0] - [0, 20]
      (variable_declaration [0, 0] - [0, 19]
        type: (implicit_type [0, 0] - [0, 3])
        (variable_declarator [0, 4] - [0, 19]
          (tuple_pattern [0, 4] - [0, 10]
            (identifier [0, 5] - [0, 6])
            (identifier [0, 8] - [0, 9]))
          (equals_value_clause [0, 11] - [0, 19]
            (tuple_expression [0, 13] - [0, 19]
              (argument [0, 14] - [0, 15]
                (integer_literal [0, 14] - [0, 15]))
              (argument [0, 17] - [0, 18]
                (integer_literal [0, 17] - [0, 18])))))))))

There should be no "pattern" in this tree. Roslyn parses var (a, b) as a declaration expression, and the = is an assignment and not a variable declarator. Finally tuple_pattern doesn't exist in Roslyn, so maybe the best would be to remove it altogether.

damieng commented 1 year ago

It seems the equivalent in Roslyn is ParenthesizedVariableDesignation to indicate that there are multiple parts being assigned (with two SingleVariableDesignation inside it in this example) rather than tuple_pattern with two identifiers.

https://github.com/dotnet/roslyn/blob/main/docs/features/deconstruction.md has more details