UserNobody14 / tree-sitter-dart

Attempt to make a tree-sitter grammar for dart
MIT License
56 stars 33 forks source link

Records & Patterns support #42

Closed TimWhiting closed 1 year ago

TimWhiting commented 1 year ago

https://github.com/dart-lang/language/blob/main/accepted/future-releases/records/records-feature-specification.md

https://github.com/dart-lang/language/blob/main/accepted/future-releases/0546-patterns/feature-specification.md

https://github.com/dart-lang/sdk/commits/9d78eaf1adf427a95eaecd4e26f2d6314b43ccdd/tools/spec_parser/Dart.g

There are a few minor modifications that might need adjusting on the new features. Just see the commits to the spec parser for changes.

RobertBrunhage commented 1 year ago

@TimWhiting any updates on this?

Here is a case of highlighting not working (you can see the (true, false) scenario using NeoVim

image.

TimWhiting commented 1 year ago

I've implemented some basic records support, but not any patterns support. I hope to finish this in the next week or two

TimWhiting commented 1 year ago

Support has been merged. I ended up having to add a lot of rules that partially conflict with others, which mainly means that there might be some performance regressions. That being said, my Macbook parses everything in the flutter repo under packages/ in 30 seconds or less. There isn't much pattern code out there in the wild yet, so although the flutter master channel does have some that I was able to debug and fix a few issues, don't expect it to be perfect first try. I did have time to test the records pretty thoroughly, but not patterns yet.

Let me know of any issues you encounter and I'll try to be pretty quick to respond.

dalugm commented 1 year ago

Hi, thanks for your hard work.

After using the latest commit, almost everything works fine except the type_cast_expression:

We can see the example here

https://dart.dev/language/pattern-types#cast

Code like this was parsered correctly:

// Returns multiple values in a record:
(String, int) userInfo(Map<String, dynamic> json) {
  return (json['name'] as String, json['age'] as int);  // <- Type case
}

Syntax tree

(comment //)
(function_signature
 (record_type (
  (record_type_field (type_identifier))
  ,
  (record_type_field (type_identifier))
  ))
 name: (identifier)
 (formal_parameter_list (
  (formal_parameter name: (type_identifier)
   (type_arguments < (type_identifier) , (type_identifier) >)
   (identifier))
  )))
(function_body
 (block {
  (return_statement return
   (record_literal (
    (record_field
     (type_cast_expression (identifier)
      (selector
       (unconditional_assignable_selector
        (index_selector [
         (string_literal ' ')
         ])))
      (type_cast             <---------- The cast was parsered correctly.
       (as_operator as)
       (type_identifier))))
    ,
    (record_field
     (type_cast_expression (identifier)
      (selector
       (unconditional_assignable_selector
        (index_selector [
         (string_literal ' ')
         ])))
      (type_cast
       (as_operator as)
       (type_identifier))))
    ))
   ;)
  }))

But code like this was not parsered correctly:

void record() {
  (num, String) record = (1, "s");
  var (i as int, String s) = record;  // <- Another type case
  print('i: $i, s: $s');
}

syntax tree

(function_signature (void_type) name: (identifier)
 (formal_parameter_list ( )))
(function_body
 (block {
  (local_variable_declaration
   (initialized_variable_definition
    name:
     (record_type (
      (record_type_field (type_identifier))
      ,
      (record_type_field (type_identifier))
      ))
    (identifier) value: =
    (record_literal (
     (record_field (decimal_integer_literal))
     ,
     (record_field
      (string_literal " "))
     )))
   ;)
  (local_variable_declaration
   (initialized_variable_definition
    name: (inferred_type var)
    (record_type (
     (record_type_field (type_identifier)  <---------- Throw an error, not recognized as type cast.
      (ERROR (identifier))
      (identifier))
     ,
     (record_type_field (type_identifier) (identifier))
     ))
    (ERROR =)
    (identifier))
   ;)
  (expression_statement (identifier)
   (selector
    (argument_part
     (arguments (
      (argument
       (string_literal '
        (template_substitution $ (identifier_dollar_escaped))
        (template_substitution $ (identifier_dollar_escaped))
        '))
      ))))
   ;)
  }))

Is this a bug or something else? thx

TimWhiting commented 1 year ago

It's a bug, i forgot to add the patterns to local variable declarations, it should be a quick fix

TimWhiting commented 1 year ago

Should be working now

dalugm commented 1 year ago

Thx, fix confirmed