@dekobon/tree-sitter-groovy 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -166,6 +166,27 @@ These are documented in detail in
166
166
  as `a + b` rather than splitting into two statements. Idiomatic
167
167
  Groovy places continuation operators at the end of the previous
168
168
  line.
169
+ - **A `{` after `new T(...)` is always an anonymous class body** --
170
+ Groovy instead calls a closure on the new object when the `{`
171
+ starts a later line (outside parentheses and brackets) or cannot be
172
+ a class body, so `new ArrayList()\n{ list.add(1) }` and
173
+ `new T() { x -> x }` get an `ERROR` inside a `class_body`. Write
174
+ `new ArrayList().call { ... }` to keep the call.
175
+ - **A `{ ... }` straight after a field with no initializer is an
176
+ instance initializer block** -- `int x { ... }` parses with no
177
+ `ERROR`. A record's compact constructor (`public Name { ... }`),
178
+ which is unsupported, takes the same reading. After a field *with*
179
+ an initializer a next-line `{` is that expression's trailing
180
+ closure, as in Groovy: end the field with `;` to get an
181
+ initializer block.
182
+ - **`sealed` and `trait` are keywords where a class member can
183
+ start** -- a field or enum constant named `sealed` or `trait` is an
184
+ `ERROR` when it follows a modifier (`private boolean sealed`) or
185
+ opens the member (`static trait = 1`, `enum E { trait }`).
186
+ `boolean sealed` and `String trait`, with no modifier, parse.
187
+ `record` is not affected: it is a keyword only directly before a
188
+ record header (`record Name(`), so `private Record record` and
189
+ `record.key()` parse.
169
190
 
170
191
  ## Contributing
171
192
 
package/grammar.js CHANGED
@@ -7,12 +7,12 @@
7
7
  * SPECIFICATION.md at the repository root. Every rule below maps to
8
8
  * a section there. Read the spec before making non-trivial changes.
9
9
  *
10
- * The external scanner (src/scanner.c) handles four context-sensitive
10
+ * The external scanner (src/scanner.c) handles three context-sensitive
11
11
  * lexing situations that pure grammar rules cannot disambiguate:
12
12
  * - Slashy-string-start vs. division
13
- * - Automatic-semicolon (newline-as-terminator)
14
- * - Labelled-statement colon
15
- * - Block-comment / Groovydoc single-token emit
13
+ * - Line / block / Groovydoc comment single-token emit
14
+ * - The contextual `record` keyword, emitted only before a record
15
+ * header so the word stays an identifier everywhere else
16
16
  * See SPECIFICATION.md §6.
17
17
  */
18
18
 
@@ -79,6 +79,18 @@ module.exports = grammar({
79
79
  // is the contract this rule set will fulfil.
80
80
  word: $ => $.identifier,
81
81
 
82
+ // §5.2 — `new` is a hard keyword. Keyword extraction alone still
83
+ // lexes it as `identifier` wherever the keyword has no action,
84
+ // which let `def f = (Foo) new T()` after another member split
85
+ // into a field `= (Foo)` and a method `T()` returning `new`. The
86
+ // empty `property` set keeps `foo.new` (Apache `namePart`) valid;
87
+ // `_property_name` also names methods, so `new` is not reserved
88
+ // where a method name may follow (`def new`, `int new`).
89
+ reserved: {
90
+ global: _ => ['new'],
91
+ property: _ => [],
92
+ },
93
+
82
94
  extras: $ => [
83
95
  /\s/,
84
96
  $.line_comment,
@@ -102,6 +114,7 @@ module.exports = grammar({
102
114
  $.line_comment,
103
115
  $.block_comment,
104
116
  $.groovydoc_comment,
117
+ $._record_keyword,
105
118
  ],
106
119
 
107
120
  conflicts: $ => [
@@ -109,7 +122,7 @@ module.exports = grammar({
109
122
  // (list_literal vs map_literal — tree-sitter resolves without
110
123
  // an explicit conflict because `:` after the first element
111
124
  // always disambiguates within one token of lookahead.)
112
- //
125
+
113
126
  // §5.15 — inside `( … )` an identifier could be either an
114
127
  // _expression (parenthesized_expression) or a _type
115
128
  // (parenthesized_type_cast). Tree-sitter explores both via
@@ -145,6 +158,25 @@ module.exports = grammar({
145
158
  // decides; the conflict keeps both alternatives alive until
146
159
  // then.
147
160
  [$.variable_declarator, $._property_name],
161
+
162
+ // §4 — `static NAME` inside a class body: after one or more
163
+ // modifiers and one identifier, that identifier could be the
164
+ // modifier-only field_declaration's variable_declarator name
165
+ // (`static MEDIUM_TTL = 900`) or the start of a typed
166
+ // field_declaration/method_declaration's `_type` (`static Foo
167
+ // bar`). The next token (`=`/`,`/`;` vs a second identifier)
168
+ // disambiguates.
169
+ [$.variable_declarator, $._type],
170
+
171
+ // §4 — `enum E { E(v, w) { } }`: after `E(` an identifier could be
172
+ // a constant's argument (`_expression`) or a constructor's untyped
173
+ // parameter (`formal_parameter`); the `{` after `)` decides. The
174
+ // conflict is global by necessity — it is between the two
175
+ // reductions, not their containers — and was checked inert
176
+ // outside an enum body: declaring it on the v0.3.0 grammar makes
177
+ // tree-sitter report it unnecessary. Regenerate without it to
178
+ // confirm that still holds.
179
+ [$.formal_parameter, $._expression],
148
180
  ],
149
181
 
150
182
  rules: {
@@ -232,9 +264,9 @@ module.exports = grammar({
232
264
  field('statement', $._statement),
233
265
  )),
234
266
 
235
- // §4 — block of statements, used in control-flow bodies and
236
- // (eventually) method bodies. Shares `{ ... }` syntax with
237
- // closure (§5.8). A `prec(1, …)` keeps block preferred at use
267
+ // §4 — block of statements: control-flow, method and constructor
268
+ // bodies, static / instance initializers. Shares `{ ... }` syntax
269
+ // with closure (§5.8). A `prec(1, …)` keeps block preferred at use
238
270
  // sites where both `block` and a closure-bearing `_statement`
239
271
  // are valid alternatives (e.g. the body slot of `if` / `while`).
240
272
  block: $ => prec(1, seq(
@@ -390,9 +422,10 @@ module.exports = grammar({
390
422
 
391
423
  // §4 — `catch_formal_parameter` accepts either a single _type
392
424
  // or a multi_type for Java 7+ / Groovy multi-catch. Closes
393
- // murtaza64 #39.
425
+ // murtaza64 #39. The type itself is optional — Groovy allows a
426
+ // bare `catch (e) { … }`, implicitly typed as Exception.
394
427
  catch_formal_parameter: $ => seq(
395
- field('type', choice($._type, $.multi_type)),
428
+ optional(field('type', choice($._type, $.multi_type))),
396
429
  field('name', $.identifier),
397
430
  ),
398
431
 
@@ -525,23 +558,56 @@ module.exports = grammar({
525
558
  field('body', $.class_body),
526
559
  ),
527
560
 
528
- // §4 — `{ method* }` for v1. Field declarations, static
529
- // initialisers, and inner classes land later.
561
+ // §4 — member list shared by class / interface / trait / record /
562
+ // `@interface` bodies and the anonymous inner class body of
563
+ // `object_creation_expression`.
530
564
  // The body accepts `;` as an empty member / terminator the same
531
565
  // way statement lists do (§5.10): a field or abstract method is
532
566
  // commonly written `int x = 1;` / `void f();`, and a stray `;` is
533
567
  // a no-op member. `;` is anonymous, so it never appears in the AST.
568
+ //
569
+ // A bare `block` is an instance initializer. It sits in the member
570
+ // repeat — here and in the three identical repeats of `enum_body` —
571
+ // rather than in `_class_member`, because `enum_body` also places
572
+ // a lone `_class_member` directly after its constants. A block in
573
+ // that slot is an LR conflict on `A() {` (constructor, or constant
574
+ // plus initializer) and, once that is resolved, silently accepts
575
+ // `A { }` (a constant with an anonymous class body, unsupported)
576
+ // as constant-plus-initializer.
534
577
  class_body: $ => seq(
535
578
  '{',
536
- repeat(choice($._class_member, ';')),
579
+ repeat(choice($._class_member, $.block, ';')),
537
580
  '}',
538
581
  ),
539
582
 
583
+ // Nested type declarations are members, as in Apache's
584
+ // `memberDeclaration`. Each kind must be listed: a declaration
585
+ // keyword with no action at member start lexes as an identifier,
586
+ // so `class Inner { … }` would silently parse as a field `Inner`
587
+ // of type `class` followed by an instance initializer block, and
588
+ // a nested `record R(int x) { }` as a method `R` returning
589
+ // `record`. The record keyword comes from the scanner (§6.7), so
590
+ // listing it here does not reserve `record` as a member name.
591
+ //
592
+ // The price: `trait` and `sealed` are keywords wherever a member
593
+ // can start, as they already are where a statement can. A member
594
+ // cannot open with one of them as a plain identifier, with or
595
+ // without modifiers (`static trait = 1`, `sealed() { }`), nor use
596
+ // one as the name after `modifier(s) Type`, because `private Foo`
597
+ // is already a complete field (`private boolean sealed` is an
598
+ // ERROR; `boolean sealed` is not). See divergence 12. No
599
+ // `conflicts` entry is needed.
540
600
  _class_member: $ => choice(
541
601
  $.method_declaration,
542
602
  $.field_declaration,
543
603
  $.constructor_declaration,
544
604
  $.static_initializer,
605
+ $.enum_declaration,
606
+ $.class_declaration,
607
+ $.interface_declaration,
608
+ $.trait_declaration,
609
+ $.record_declaration,
610
+ $.annotation_type_declaration,
545
611
  ),
546
612
 
547
613
  // §4 — constructors share the method_declaration shape but have
@@ -573,12 +639,28 @@ module.exports = grammar({
573
639
  // more declarators (each with optional initializer). Method
574
640
  // declarations share the same prefix; `prec(2, …)` on
575
641
  // `method_declaration` and the trailing `(` discriminate.
576
- field_declaration: $ => seq(
577
- repeat($.annotation),
578
- repeat($._modifier),
579
- choice('def', field('type', $._type)),
580
- $.variable_declarator,
581
- repeat(seq(',', $.variable_declarator)),
642
+ //
643
+ // A modifier alone (no `def`, no type) also introduces a field —
644
+ // `static MEDIUM_TTL = 900` infers Object, a common constant-field
645
+ // idiom. Gated behind `repeat1($._modifier)` (not `repeat`) so this
646
+ // alternative can't match a bare, modifier-less identifier, which
647
+ // would collide with a plain expression_statement.
648
+ field_declaration: $ => choice(
649
+ // Prefer the typed field when both parses succeed, rather than
650
+ // splitting `private final int v\n C() {}` after `int`.
651
+ prec.dynamic(1, seq(
652
+ repeat($.annotation),
653
+ repeat($._modifier),
654
+ choice('def', field('type', $._type)),
655
+ $.variable_declarator,
656
+ repeat(seq(',', $.variable_declarator)),
657
+ )),
658
+ seq(
659
+ repeat($.annotation),
660
+ repeat1($._modifier),
661
+ $.variable_declarator,
662
+ repeat(seq(',', $.variable_declarator)),
663
+ ),
582
664
  ),
583
665
 
584
666
  // §4 — `def name(params) body`. Typed return type (`String foo()
@@ -626,10 +708,13 @@ module.exports = grammar({
626
708
  ')',
627
709
  ),
628
710
 
629
- // §5.13 — formal parameter with optional type, optional
630
- // varargs marker (`Type... name`), and optional default value
711
+ // §5.13 — formal parameter with optional annotations (Spring's
712
+ // `@PathVariable`, `@RequestBody`, JPA's `@Param`, … — ubiquitous
713
+ // on framework-facing methods), optional type, optional varargs
714
+ // marker (`Type... name`), and optional default value
631
715
  // (`name = expr`).
632
716
  formal_parameter: $ => seq(
717
+ repeat($.annotation),
633
718
  optional(field('type', choice($._type, $.varargs_type))),
634
719
  field('name', $.identifier),
635
720
  optional(seq('=', field('default', $._expression))),
@@ -637,13 +722,36 @@ module.exports = grammar({
637
722
 
638
723
  varargs_type: $ => seq($._type, '...'),
639
724
 
640
- // §4 — enum. Closes murtaza64 #36 first half. Constants list
641
- // (optionally trailing-comma) optionally followed by `;` and
642
- // further class members. Constants may carry constructor
643
- // arguments (`RED(0xff0000)`); v1 supports that via the
644
- // optional argument_list.
725
+ // §4 — enum. Closes murtaza64 #36 first half. Constants may
726
+ // carry constructor arguments (`RED(0xff0000)`) via the optional
727
+ // argument_list.
728
+ //
729
+ // The body follows GroovyParser.g4 `classBody` for `t == 2`:
730
+ // after the constants either a trailing `,` closes the list, or
731
+ // members follow after `;`, `,;`, or nothing at all — Groovy's
732
+ // own parser treats the newline as the separator (GROOVY-7773,
733
+ // GROOVY-9306), and newlines are extras here, so the member
734
+ // simply follows the last constant. `A,` directly before a
735
+ // member is rejected, as in Groovy. With no constants the body
736
+ // is an ordinary member list.
737
+ //
738
+ // An instance initializer (`block`) is accepted wherever the
739
+ // member list repeats — after `;`, after a first member, or with
740
+ // no constants — but not directly after a constant. Newlines are
741
+ // extras, so `A\n{ … }` (in the .g4 a constant, then an
742
+ // initializer) cannot be told from `A { … }` (a constant with an
743
+ // anonymous class body, unsupported); both stay errors.
744
+ //
745
+ // The three member repeats are spelled out, and must stay
746
+ // identical to the one in `class_body`, so that the generator
747
+ // folds all four into one aux symbol (`aux_sym_class_body_repeat1`).
748
+ // A differing copy, or a hidden rule that is not inlined, adds a
749
+ // symbol and renumbers every id after it — the alias kinds
750
+ // `named_argument`, `quoted_identifier` and `type_identifier`
751
+ // included — which a patch release must not do.
645
752
  enum_declaration: $ => seq(
646
753
  repeat($.annotation),
754
+ repeat($._modifier),
647
755
  'enum',
648
756
  field('name', $.identifier),
649
757
  field('body', $.enum_body),
@@ -651,30 +759,77 @@ module.exports = grammar({
651
759
 
652
760
  enum_body: $ => seq(
653
761
  '{',
654
- optional(seq(
655
- $.enum_constant,
656
- repeat(seq(',', $.enum_constant)),
657
- optional(','),
658
- )),
659
- optional(seq(';', repeat(choice($._class_member, ';')))),
762
+ choice(
763
+ seq(
764
+ $.enum_constant,
765
+ repeat(seq(',', $.enum_constant)),
766
+ optional(choice(
767
+ ',',
768
+ seq(optional(','), ';', repeat(choice($._class_member, $.block, ';'))),
769
+ seq($._class_member, repeat(choice($._class_member, $.block, ';'))),
770
+ )),
771
+ ),
772
+ repeat(choice($._class_member, $.block, ';')),
773
+ ),
660
774
  '}',
661
775
  ),
662
776
 
663
- enum_constant: $ => seq(
777
+ // §4 — `prec(1)` makes a bare identifier at the start of the body
778
+ // a constant rather than the type of the first member: `A\n E() { }`
779
+ // is a constant followed by a constructor, not a method `E`
780
+ // returning `A`. The mirror case with no constants, `int f() { }`
781
+ // as the first thing in the body, therefore reads as constant `int`
782
+ // plus constructor `f` — a newline is whitespace here and nothing
783
+ // else tells the two apart; a modifier, `def`, or a leading `;`
784
+ // makes it a member. Static precedence rather than `prec.dynamic`
785
+ // with an `[enum_constant, _type]` conflict: both yield the same
786
+ // tree on every valid shape, but the GLR form silently accepts
787
+ // `A\n B` (constants missing their comma, which Groovy rejects) as
788
+ // a field `A B`, where this form reports the ERROR. Annotations
789
+ // share the prefix with an annotated member; the same precedence
790
+ // decides after them, so `@Foo A\n int x` is a constant and a
791
+ // field.
792
+ enum_constant: $ => prec(1, seq(
793
+ repeat($.annotation),
664
794
  field('name', $.identifier),
665
795
  optional(field('arguments', $.argument_list)),
666
- ),
796
+ )),
667
797
 
668
- // §4 — record (Groovy 4+). `record Name(Type a, Type b) [{ body }]`.
669
- // `record` is a contextual keyword — tree-sitter's word: directive
670
- // keeps `record` usable as a plain identifier elsewhere.
671
- record_declaration: $ => prec.right(seq(
798
+ // §4 — record (Groovy 4+), after Apache's `classDeclaration`:
799
+ // `[modifiers] record Name[<T>](Type a, Type b) [implements I] [{ body }]`.
800
+ // Records cannot `extends`, and the body is optional here where
801
+ // Groovy requires it.
802
+ // §5.2 / §6.7 — `record` is a contextual keyword. The keyword
803
+ // comes from the external scanner, which emits it only when a
804
+ // name follows on the same line and `(` or `<` after that; in
805
+ // every other position the word lexes as `identifier`. A grammar literal
806
+ // cannot do this: keyword extraction yields the keyword wherever
807
+ // it has an action, which made `record.key()` at statement start,
808
+ // and `private Record record` once record_declaration became a
809
+ // class member, errors. The alias keeps the anonymous `record`
810
+ // node that the queries capture.
811
+ //
812
+ // The dynamic precedence settles a GLR tie the scanner creates.
813
+ // After `private Record`, the `[variable_declarator, _type]`
814
+ // conflict forks on the next word: `record` is the field's name
815
+ // in one branch and a type in the other. When a record header
816
+ // follows on the next line, the first branch lexes its `record`
817
+ // as the keyword and the second as that field's name, and both
818
+ // survive (`private Record` / `record record` / constructor
819
+ // `Inner(int x) { }` is a valid member list). Without a weight,
820
+ // which tree wins depends on tree shape, and a comment between
821
+ // the two lines flipped it. Favouring the record declaration is
822
+ // right whenever both parse.
823
+ record_declaration: $ => prec.dynamic(1, prec.right(seq(
672
824
  repeat($.annotation),
673
- 'record',
825
+ repeat($._modifier),
826
+ alias($._record_keyword, 'record'),
674
827
  field('name', $.identifier),
828
+ optional(field('type_parameters', $.type_parameters)),
675
829
  field('components', $.record_components),
830
+ optional($.super_interfaces),
676
831
  optional(field('body', $.class_body)),
677
- )),
832
+ ))),
678
833
 
679
834
  record_components: $ => seq(
680
835
  '(',
@@ -779,16 +934,18 @@ module.exports = grammar({
779
934
  optional(field('arguments', $.argument_list)),
780
935
  ),
781
936
 
782
- // §4 — `for (x in xs)`. Untyped variable for v1. Typed
783
- // (`for (Type x in xs)`) lands later. The `in` keyword here
784
- // is a structural delimiter, not the membership_expression
785
- // operator — context disambiguates because the for-header is
786
- // not an expression position.
937
+ // §4 — `for (x in xs)`, plus the Java-compatible enhanced-for
938
+ // form Groovy accepts side by side: `for (Type x : xs)` / `for
939
+ // (def x : xs)`. The `in` / `:` keyword here is a structural
940
+ // delimiter, not the membership_expression operator or a
941
+ // labelled_statement colon — context disambiguates because the
942
+ // for-header is not an expression position.
787
943
  for_in_statement: $ => seq(
788
944
  'for',
789
945
  '(',
946
+ optional(choice('def', field('type', $._type))),
790
947
  field('variable', $.identifier),
791
- 'in',
948
+ choice('in', ':'),
792
949
  field('value', $._expression),
793
950
  ')',
794
951
  field('body', choice($.block, $._statement)),
@@ -965,17 +1122,48 @@ module.exports = grammar({
965
1122
  ))));
966
1123
  },
967
1124
 
968
- // §3.2 / §5.15 — `new Foo(args)`. We only handle the plain
969
- // constructor-call form here; array creation `new Foo[10]`,
970
- // generic types, and array initialisers land later. PREC.PRIMARY
971
- // so it composes with the access tier from the left
972
- // (`new Foo().bar`).
1125
+ // §3.2 — `new Foo(args)` and the anonymous inner class
1126
+ // `new Foo(args) { members }`. Array creation `new Foo[10]` and
1127
+ // array initialisers land later. PREC.PRIMARY only labels the
1128
+ // §3.1 tier. The number decides nothing: the rule's one conflict
1129
+ // (below) is against itself, where it cancels out, and
1130
+ // `new Foo().bar` composes without any precedence.
1131
+ //
1132
+ // The optional body takes every `{` that follows the arguments.
1133
+ // Right associativity does that statically — the shift into
1134
+ // `class_body` beats reducing the bodiless form — so no conflict
1135
+ // is declared and the closure reading never forks.
1136
+ //
1137
+ // Apache is narrower. Its `creator` has no `nls` before the body,
1138
+ // so `new T()\n{ … }` is a closure called on the new object
1139
+ // (observed on Groovy 4.0.33). By the same grammar a same-line
1140
+ // `{` whose content cannot be class members should be one too
1141
+ // (`new T() { x -> x }`; not run through the compiler). Here both
1142
+ // are read as a body, usually with an ERROR in it (divergence 11).
1143
+ // Parsing them needs a declared conflict on this rule with
1144
+ // `prec.dynamic` on the body, and that form was not taken: a body
1145
+ // holding one member `class_body` cannot parse, or one still
1146
+ // being typed, would then fall back silently to the closure tree
1147
+ // that #68 reported.
973
1148
  object_creation_expression: $ => prec.right(PREC.PRIMARY, seq(
974
1149
  'new',
975
- field('type', $._type),
1150
+ field('type', choice($._type, alias($._diamond_type, $.generic_type))),
976
1151
  field('arguments', $.argument_list),
1152
+ optional(field('body', $.class_body)),
977
1153
  )),
978
1154
 
1155
+ // §3.2 — Apache's createdName permits diamond, but ordinary types
1156
+ // (including nested type arguments) do not. Keep the public shape.
1157
+ _diamond_type: $ => prec.right(PREC.ARRAY_TYPE, seq(
1158
+ field('base', choice(
1159
+ alias($.identifier, $.type_identifier),
1160
+ $.qualified_type,
1161
+ )),
1162
+ field('arguments', alias($._diamond_type_arguments, $.type_arguments)),
1163
+ )),
1164
+
1165
+ _diamond_type_arguments: _ => seq(token.immediate('<'), '>'),
1166
+
979
1167
  // §5.15 — C-style cast `(Foo) x`. Distinct from
980
1168
  // `parenthesized_expression` followed by something (resolved
981
1169
  // by tree-sitter's GLR; declared as a conflict if needed).
@@ -1102,7 +1290,7 @@ module.exports = grammar({
1102
1290
  // keywords, or special chars. `map."key with spaces"` and
1103
1291
  // `def "abstract"() { … }` both rely on this.
1104
1292
  _property_name: $ => choice(
1105
- $.identifier,
1293
+ reserved('property', $.identifier),
1106
1294
  alias($.string_literal, $.quoted_identifier),
1107
1295
  ),
1108
1296
 
@@ -1135,10 +1323,35 @@ module.exports = grammar({
1135
1323
  // expression so subscript / future field_access / future
1136
1324
  // safe_navigation chains compose naturally. PREC.POSTFIX
1137
1325
  // matches subscript so chains like `obj[i](x)[j]` work.
1138
- method_invocation: $ => prec.left(PREC.POSTFIX, seq(
1139
- field('function', $._expression),
1140
- field('arguments', $.argument_list),
1141
- )),
1326
+ //
1327
+ // Trailing closure (§5.5's command_chain covers the bare-
1328
+ // identifier statement form; this covers the general expression
1329
+ // form used constantly on property-access chains: `list.find {
1330
+ // it > 5 }`, `list.inject(0) { acc, x -> acc + x }`). Groovy
1331
+ // treats a closure literal as the call's last argument whether
1332
+ // or not parens are present, so `argument_list` becomes optional
1333
+ // once a trailing closure is there to anchor the call.
1334
+ //
1335
+ // The args-and-closure alternative sits one precedence level
1336
+ // above plain POSTFIX so `f(x) { … }` reduces to a single
1337
+ // method_invocation node (arguments AND closure fields on the
1338
+ // same node) instead of GLR instead reaching the same span by
1339
+ // nesting a closure-only method_invocation around a plain call.
1340
+ method_invocation: $ => choice(
1341
+ prec.left(PREC.POSTFIX + 1, seq(
1342
+ field('function', $._expression),
1343
+ field('arguments', $.argument_list),
1344
+ field('closure', $.closure),
1345
+ )),
1346
+ prec.left(PREC.POSTFIX, seq(
1347
+ field('function', $._expression),
1348
+ field('arguments', $.argument_list),
1349
+ )),
1350
+ prec.left(PREC.POSTFIX, seq(
1351
+ field('function', $._expression),
1352
+ field('closure', $.closure),
1353
+ )),
1354
+ ),
1142
1355
 
1143
1356
  // §3.2 / §5.11 — argument list. Positional args are `_expression`;
1144
1357
  // named args (Groovy's `k: v` in call position) are `map_entry`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dekobon/tree-sitter-groovy",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Apache Groovy grammar for tree-sitter (dekobon fork)",
5
5
  "main": "bindings/node",
6
6
  "types": "bindings/node",
@@ -67,10 +67,16 @@
67
67
  }
68
68
  },
69
69
  "devDependencies": {
70
- "eslint": "^9.39.4",
70
+ "eslint": "^10.14.0",
71
71
  "eslint-config-treesitter": "^1.0.2",
72
+ "globals": "^17.14.0",
72
73
  "prebuildify": "^6.0.1",
73
- "tree-sitter-cli": "^0.26.13"
74
+ "tree-sitter-cli": "^0.27.2"
75
+ },
76
+ "overrides": {
77
+ "eslint-config-treesitter": {
78
+ "eslint-plugin-jsdoc": "^62.9.0"
79
+ }
74
80
  },
75
81
  "tree-sitter": [
76
82
  {