@willbooster/tree-sitter-typescript 1.2.9 → 1.2.10

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.
@@ -21,17 +21,60 @@ const TYPESCRIPT_CONTEXTUAL_KEYWORDS = [
21
21
  'new',
22
22
  ];
23
23
 
24
+ // Every primary expression but a `new` without arguments reduces to `_type_arguments_target` before
25
+ // `primary_expression`, so the JavaScript grammar's precedences and conflicts for `primary_expression` take effect only
26
+ // on `_type_arguments_target`.
27
+ function withTypeArgumentsTarget($, lists) {
28
+ return lists.map((list) =>
29
+ list.map((entry) =>
30
+ entry.type === 'SYMBOL' && entry.name === 'primary_expression' ? $._type_arguments_target : entry
31
+ )
32
+ );
33
+ }
34
+
35
+ // Dynamic precedences for the readings of `<` and `>` that GLR keeps where TypeScript's parser, which tries type
36
+ // arguments first and keeps them only before what may follow them (see `scan_type_arguments_end` in scanner.h), reads
37
+ // one way. Comparisons have 0.
38
+ const DYNAMIC_PRECEDENCE = {
39
+ // The type arguments of a call, a tagged template, or a `new`: they also outweigh comparisons that contain
40
+ // instantiation expressions (`f<A<B> | C>(x)`) and an extends clause's type arguments in a misreading
41
+ // (`class C extends f<A<B>, D>(x) {}`).
42
+ TYPE_ARGUMENTS: 3,
43
+ // An extends clause's type arguments, which TypeScript also gives the clause where an instantiation expression could
44
+ // take them (`class C extends B<T>` before a line break and `{`).
45
+ EXTENDS_TYPE_ARGUMENTS: 2,
46
+ // An instantiation expression whose type arguments TypeScript keeps before what may start an expression, which
47
+ // comparisons could then read as their right operand: after a line break (`a<B>` before a line break and `c`) or
48
+ // before a `/`.
49
+ INSTANTIATION_BEFORE_EXPRESSION: 1,
50
+ // An instantiation expression elsewhere, so that comparisons containing it lose to an enclosing generic call.
51
+ INSTANTIATION: -1,
52
+ // A leading `|` or `&` in a type, which TypeScript allows only at the start of a type: `a < b || c > (d)` compares
53
+ // rather than calling `a` with `b | | c`.
54
+ LEADING_TYPE_OPERATOR: -4,
55
+ };
56
+
24
57
  module.exports = function defineGrammar(dialect) {
25
58
  return grammar(JavaScript, {
26
59
  name: dialect,
27
60
 
28
- externals: ($, previous) => [...previous, $._function_signature_automatic_semicolon, $.__error_recovery],
61
+ externals: ($, previous) => [
62
+ ...previous,
63
+ $._function_signature_automatic_semicolon,
64
+ $._type_arguments_end,
65
+ $._type_arguments_end_before_expression,
66
+ $._new_type_arguments_end,
67
+ $.__error_recovery,
68
+ ],
29
69
 
30
70
  supertypes: ($, previous) => [...previous, $.type, $.primary_type],
31
71
 
32
72
  precedences: ($, previous) => [
33
- ...previous,
73
+ ...withTypeArgumentsTarget($, previous),
34
74
  ['call', 'instantiation', 'unary', 'binary', $.await_expression, $.arrow_function],
75
+ // A type assertion's operand takes the member accesses and subscripts that follow it, also after an instantiation
76
+ // expression (`<T>a<B>` before a line break and `[0]`).
77
+ ['member', 'unary'],
35
78
  ['extends', 'instantiation'],
36
79
  ['new', 'generic_call', 'instantiation', 'unary', 'binary'],
37
80
  [
@@ -43,67 +86,67 @@ module.exports = function defineGrammar(dialect) {
43
86
  $.type_predicate,
44
87
  $.readonly_type,
45
88
  ],
46
- [$.mapped_type_clause, $.primary_expression],
47
- [$.accessibility_modifier, $.primary_expression],
89
+ [$.mapped_type_clause, $._type_arguments_target],
90
+ [$.accessibility_modifier, $._type_arguments_target],
48
91
  ['unary_void', $.expression],
49
- [$.extends_clause, $.primary_expression],
92
+ [$.extends_clause, $._type_arguments_target],
50
93
  ['unary', 'assign'],
51
94
  ['declaration', $.expression],
52
95
  [$.predefined_type, $.unary_expression],
53
96
  [$.type, $.flow_maybe_type],
54
97
  [$.tuple_type, $.array_type, $.pattern, $.type],
55
98
  [$.readonly_type, $.pattern],
56
- [$.readonly_type, $.primary_expression],
99
+ [$.readonly_type, $._type_arguments_target],
57
100
  [$.type_query, $.subscript_expression, $.expression],
58
101
  [$.type_query, $._type_query_subscript_expression],
59
102
  [$.nested_type_identifier, $.generic_type, $.primary_type, $.lookup_type, $.index_type_query, $.type],
103
+ // A qualified type name takes every `.` and name that follow it: `x as a.b.C` is not `(x as a.b).C`.
104
+ [$.nested_identifier, $.nested_type_identifier],
60
105
  [$.as_expression, $.satisfies_expression, $.primary_type],
61
106
  [$._type_query_member_expression, $.member_expression],
62
107
  [$.member_expression, $._type_query_member_expression_in_type_annotation],
63
- [$._type_query_member_expression, $.primary_expression],
108
+ [$._type_query_member_expression, $._type_arguments_target],
64
109
  [$._type_query_subscript_expression, $.subscript_expression],
65
- [$._type_query_subscript_expression, $.primary_expression],
66
- [$._type_query_call_expression, $.primary_expression],
67
- [$._type_query_instantiation_expression, $.primary_expression],
68
- [$.type_query, $.primary_expression],
69
- [$.override_modifier, $.primary_expression],
110
+ [$._type_query_subscript_expression, $._type_arguments_target],
111
+ [$._type_query_call_expression, $._type_arguments_target],
112
+ [$._type_query_instantiation_expression, $._type_arguments_target],
113
+ [$.type_query, $._type_arguments_target],
114
+ [$.override_modifier, $._type_arguments_target],
70
115
  [$.decorator_call_expression, $.decorator],
71
116
  [$.literal_type, $.pattern],
72
117
  [$.predefined_type, $.pattern],
73
118
  [$.call_expression, $._type_query_call_expression],
74
119
  [$.call_expression, $._type_query_call_expression_in_type_annotation],
75
- [$.new_expression, $.primary_expression],
76
- [$.meta_property, $.primary_expression],
120
+ [$.new_expression, $._type_arguments_target],
121
+ [$.meta_property, $._type_arguments_target],
77
122
  [$.construct_signature, $._property_name],
78
123
  ],
79
124
 
80
125
  conflicts: ($, previous) => [
81
- ...previous,
82
- [$.primary_expression, $.using_declaration],
83
- [$.primary_expression, $._for_header, $._for_using_declaration],
126
+ ...withTypeArgumentsTarget($, previous),
127
+ [$._type_arguments_target, $.using_declaration],
128
+ [$._type_arguments_target, $._for_header, $._for_using_declaration],
84
129
  [$._for_header, $._binding_identifier],
85
- [$.expression, $.call_expression, $.instantiation_expression],
86
130
  [$._field_name, $._property_name],
87
131
  [$._property_name, $.public_field_definition],
88
132
 
89
133
  // This appears to be necessary to parse a parenthesized class expression
90
134
  [$.class],
91
135
 
92
- [$.nested_identifier, $.nested_type_identifier, $.primary_expression],
93
- [$.nested_identifier, $.nested_type_identifier],
136
+ [$.nested_identifier, $.nested_type_identifier, $._type_arguments_target],
94
137
 
95
138
  [$._call_signature, $.function_type],
96
139
  [$._call_signature, $.constructor_type],
97
140
 
98
- [$.primary_expression, $._parameter_name],
99
- [$.primary_expression, $._parameter_name, $.primary_type],
100
- [$.primary_expression, $.literal_type],
101
- [$.primary_expression, $.literal_type, $.rest_pattern],
102
- [$.primary_expression, $.predefined_type, $.rest_pattern],
103
- [$.primary_expression, $.primary_type],
104
- [$.primary_expression, $.generic_type],
105
- [$.primary_expression, $.predefined_type],
106
- [$.primary_expression, $.pattern, $.primary_type],
141
+ [$._type_arguments_target, $._parameter_name],
142
+ [$._type_arguments_target, $._parameter_name, $.primary_type],
143
+ [$._type_arguments_target, $.literal_type],
144
+ [$._type_arguments_target, $.literal_type, $.rest_pattern],
145
+ [$._type_arguments_target, $.predefined_type, $.rest_pattern],
146
+ [$._type_arguments_target, $.primary_type],
147
+ [$._type_arguments_target, $.generic_type],
148
+ [$._type_arguments_target, $.predefined_type],
149
+ [$._type_arguments_target, $.pattern, $.primary_type],
107
150
  [$._parameter_name, $.primary_type],
108
151
  [$.pattern, $.primary_type],
109
152
 
@@ -112,7 +155,7 @@ module.exports = function defineGrammar(dialect) {
112
155
  [$._tuple_label, $.index_type_query],
113
156
  [$._tuple_label, $.readonly_type],
114
157
  [$._tuple_label, $.predefined_type],
115
- [$.rest_pattern, $.primary_type, $.primary_expression],
158
+ [$.rest_pattern, $.primary_type, $._type_arguments_target],
116
159
 
117
160
  [$.object, $.object_type],
118
161
  [$.object, $.object_pattern, $.object_type],
@@ -131,6 +174,14 @@ module.exports = function defineGrammar(dialect) {
131
174
  [$.jsx_opening_element, $.type_parameter],
132
175
  [$.jsx_namespace_name, $.primary_type],
133
176
  ]),
177
+ [
178
+ $.primary_expression,
179
+ $.call_expression,
180
+ $._argumentless_new_expression,
181
+ $.new_expression,
182
+ $.instantiation_expression,
183
+ ],
184
+ [$.primary_expression, $.call_expression, $.instantiation_expression],
134
185
  ],
135
186
 
136
187
  inline: ($, previous) => [
@@ -234,15 +285,15 @@ module.exports = function defineGrammar(dialect) {
234
285
  choice(
235
286
  prec('call', seq(field('function', choice($.expression, $.import)), field('arguments', $.arguments))),
236
287
  // Type arguments follow a primary expression, as in TypeScript: `a + b<T>(c)` calls `b`. Where comparisons
237
- // could also read the input, as in `a < b > (c)`, TypeScript reads a generic call, hence the dynamic
238
- // precedence. A tag with type arguments is parsed like a generic call. Optional type arguments in the
239
- // `template_call` alternative below would make the parser commit to a tagged template at the `<` of `f<T>(x)`.
288
+ // could also read the input, as in `a < b > (c)`, TypeScript reads a generic call. A tag with type arguments
289
+ // is parsed like a generic call. Optional type arguments in the `template_call` alternative below would make
290
+ // the parser commit to a tagged template at the `<` of `f<T>(x)`.
240
291
  prec.dynamic(
241
- 1,
292
+ DYNAMIC_PRECEDENCE.TYPE_ARGUMENTS,
242
293
  prec(
243
294
  'generic_call',
244
295
  seq(
245
- field('function', $.primary_expression),
296
+ field('function', $._type_arguments_target),
246
297
  field('type_arguments', $.type_arguments),
247
298
  field('arguments', choice($.arguments, $.template_string))
248
299
  )
@@ -260,23 +311,37 @@ module.exports = function defineGrammar(dialect) {
260
311
  )
261
312
  ),
262
313
 
263
- // tree-sitter-javascript's two forms of `new`, with type arguments; its 'member' and 'new' precedences group nested
264
- // `new` as ECMAScript does (`new new A().b` constructs `new A().b`), and both forms are primary expressions.
265
- new_expression: ($) =>
266
- prec(
267
- 'new',
268
- seq(
269
- 'new',
270
- field('constructor', $.primary_expression),
271
- field('type_arguments', optional($.type_arguments)),
272
- field('arguments', $.arguments)
314
+ new_expression: ($, previous) =>
315
+ choice(
316
+ previous,
317
+ prec.dynamic(
318
+ DYNAMIC_PRECEDENCE.TYPE_ARGUMENTS,
319
+ prec(
320
+ 'new',
321
+ seq(
322
+ 'new',
323
+ field('constructor', $._type_arguments_target),
324
+ field('type_arguments', $.type_arguments),
325
+ field('arguments', $.arguments)
326
+ )
327
+ )
273
328
  )
274
329
  ),
275
330
 
276
- _argumentless_new_expression: ($) =>
277
- prec.right(
278
- 'new',
279
- seq('new', field('constructor', $.primary_expression), field('type_arguments', optional($.type_arguments)))
331
+ // TypeScript reads `new A<B>c` as comparisons, but `new A<B>` before a line break and `c` as a `new` with type
332
+ // arguments, which also take precedence over an extends clause's (`class C extends new A<B>, D {}`).
333
+ _argumentless_new_expression: ($, previous) =>
334
+ choice(
335
+ previous,
336
+ prec.dynamic(
337
+ DYNAMIC_PRECEDENCE.TYPE_ARGUMENTS,
338
+ seq(
339
+ 'new',
340
+ field('constructor', $._type_arguments_target),
341
+ field('type_arguments', $.type_arguments),
342
+ $._new_type_arguments_end
343
+ )
344
+ )
280
345
  ),
281
346
 
282
347
  assignment_expression: ($) =>
@@ -289,7 +354,17 @@ module.exports = function defineGrammar(dialect) {
289
354
 
290
355
  _lhs_expression: ($, previous) => choice(previous, $.non_null_expression),
291
356
 
292
- primary_expression: ($, previous) => choice(previous, $.non_null_expression),
357
+ primary_expression: ($) =>
358
+ choice($._type_arguments_target, alias($._argumentless_new_expression, $.new_expression)),
359
+
360
+ // The primary expressions that type arguments in an expression may follow: TypeScript gives the type arguments
361
+ // after `new A` to the `new` (`new A<T>()`, `new new A<T>()`), so a `new` without arguments takes none.
362
+ _type_arguments_target: ($) => {
363
+ const members = JavaScript.grammar.rules.primary_expression.members.filter(
364
+ (member) => member.type !== 'ALIAS' || member.content.name !== '_argumentless_new_expression'
365
+ );
366
+ return choice(...members, $.non_null_expression);
367
+ },
293
368
 
294
369
  // If the dialect is regular typescript, we exclude JSX expressions and
295
370
  // include type assertions. If the dialect is TSX, we do the opposite.
@@ -568,8 +643,17 @@ module.exports = function defineGrammar(dialect) {
568
643
 
569
644
  satisfies_expression: ($) => prec.left('binary', seq($.expression, 'satisfies', $.type)),
570
645
 
571
- instantiation_expression: ($) =>
572
- prec.dynamic(-1, prec('instantiation', seq($.primary_expression, field('type_arguments', $.type_arguments)))),
646
+ instantiation_expression: ($) => {
647
+ const instantiation = (end) =>
648
+ prec('instantiation', seq($._type_arguments_target, field('type_arguments', $.type_arguments), end));
649
+ return choice(
650
+ prec.dynamic(DYNAMIC_PRECEDENCE.INSTANTIATION, instantiation($._type_arguments_end)),
651
+ prec.dynamic(
652
+ DYNAMIC_PRECEDENCE.INSTANTIATION_BEFORE_EXPRESSION,
653
+ instantiation($._type_arguments_end_before_expression)
654
+ )
655
+ );
656
+ },
573
657
 
574
658
  class_heritage: ($) => choice(seq($.extends_clause, optional($.implements_clause)), $.implements_clause),
575
659
 
@@ -578,7 +662,16 @@ module.exports = function defineGrammar(dialect) {
578
662
  extends_clause: ($) => seq('extends', commaSep1($._extends_clause_single)),
579
663
 
580
664
  _extends_clause_single: ($) =>
581
- prec('extends', seq(field('value', $.expression), field('type_arguments', optional($.type_arguments)))),
665
+ prec(
666
+ 'extends',
667
+ choice(
668
+ field('value', $.expression),
669
+ prec.dynamic(
670
+ DYNAMIC_PRECEDENCE.EXTENDS_TYPE_ARGUMENTS,
671
+ seq(field('value', $.expression), field('type_arguments', $.type_arguments))
672
+ )
673
+ )
674
+ ),
582
675
 
583
676
  implements_clause: ($) => seq('implements', commaSep1($.type)),
584
677
 
@@ -1112,10 +1205,14 @@ module.exports = function defineGrammar(dialect) {
1112
1205
  tuple_type: ($) => seq('[', commaSep($._tuple_type_member), optional(','), ']'),
1113
1206
  readonly_type: ($) => seq('readonly', $.type),
1114
1207
 
1115
- // TypeScript allows a leading `|` or `&` only at the start of a type, so `a < b || c > (d)` compares instead of
1116
- // calling `a` with `b | | c`. The negative dynamic precedence outweighs that of the generic call.
1117
- union_type: ($) => prec.left(choice(seq($.type, '|', $.type), prec.dynamic(-2, seq('|', $.type)))),
1118
- intersection_type: ($) => prec.left(choice(seq($.type, '&', $.type), prec.dynamic(-2, seq('&', $.type)))),
1208
+ union_type: ($) =>
1209
+ prec.left(
1210
+ choice(seq($.type, '|', $.type), prec.dynamic(DYNAMIC_PRECEDENCE.LEADING_TYPE_OPERATOR, seq('|', $.type)))
1211
+ ),
1212
+ intersection_type: ($) =>
1213
+ prec.left(
1214
+ choice(seq($.type, '&', $.type), prec.dynamic(DYNAMIC_PRECEDENCE.LEADING_TYPE_OPERATOR, seq('&', $.type)))
1215
+ ),
1119
1216
 
1120
1217
  function_type: ($) =>
1121
1218
  prec.left(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willbooster/tree-sitter-typescript",
3
- "version": "1.2.9",
3
+ "version": "1.2.10",
4
4
  "description": "TypeScript and TSX grammars for tree-sitter",
5
5
  "keywords": [
6
6
  "incremental",
Binary file
Binary file
package/tree-sitter.json CHANGED
@@ -83,7 +83,7 @@
83
83
  }
84
84
  ],
85
85
  "metadata": {
86
- "version": "1.2.9",
86
+ "version": "1.2.10",
87
87
  "license": "MIT",
88
88
  "description": "TypeScript and TSX grammars for tree-sitter",
89
89
  "authors": [
@@ -3111,7 +3111,99 @@
3111
3111
  "required": false,
3112
3112
  "types": [
3113
3113
  {
3114
- "type": "primary_expression",
3114
+ "type": "array",
3115
+ "named": true
3116
+ },
3117
+ {
3118
+ "type": "arrow_function",
3119
+ "named": true
3120
+ },
3121
+ {
3122
+ "type": "call_expression",
3123
+ "named": true
3124
+ },
3125
+ {
3126
+ "type": "class",
3127
+ "named": true
3128
+ },
3129
+ {
3130
+ "type": "false",
3131
+ "named": true
3132
+ },
3133
+ {
3134
+ "type": "function_expression",
3135
+ "named": true
3136
+ },
3137
+ {
3138
+ "type": "generator_function",
3139
+ "named": true
3140
+ },
3141
+ {
3142
+ "type": "identifier",
3143
+ "named": true
3144
+ },
3145
+ {
3146
+ "type": "member_expression",
3147
+ "named": true
3148
+ },
3149
+ {
3150
+ "type": "meta_property",
3151
+ "named": true
3152
+ },
3153
+ {
3154
+ "type": "new_expression",
3155
+ "named": true
3156
+ },
3157
+ {
3158
+ "type": "non_null_expression",
3159
+ "named": true
3160
+ },
3161
+ {
3162
+ "type": "null",
3163
+ "named": true
3164
+ },
3165
+ {
3166
+ "type": "number",
3167
+ "named": true
3168
+ },
3169
+ {
3170
+ "type": "object",
3171
+ "named": true
3172
+ },
3173
+ {
3174
+ "type": "parenthesized_expression",
3175
+ "named": true
3176
+ },
3177
+ {
3178
+ "type": "regex",
3179
+ "named": true
3180
+ },
3181
+ {
3182
+ "type": "string",
3183
+ "named": true
3184
+ },
3185
+ {
3186
+ "type": "subscript_expression",
3187
+ "named": true
3188
+ },
3189
+ {
3190
+ "type": "super",
3191
+ "named": true
3192
+ },
3193
+ {
3194
+ "type": "template_string",
3195
+ "named": true
3196
+ },
3197
+ {
3198
+ "type": "this",
3199
+ "named": true
3200
+ },
3201
+ {
3202
+ "type": "true",
3203
+ "named": true
3204
+ },
3205
+ {
3206
+ "type": "undefined",
3115
3207
  "named": true
3116
3208
  }
3117
3209
  ]
@@ -3107,7 +3107,99 @@
3107
3107
  "required": false,
3108
3108
  "types": [
3109
3109
  {
3110
- "type": "primary_expression",
3110
+ "type": "array",
3111
+ "named": true
3112
+ },
3113
+ {
3114
+ "type": "arrow_function",
3115
+ "named": true
3116
+ },
3117
+ {
3118
+ "type": "call_expression",
3119
+ "named": true
3120
+ },
3121
+ {
3122
+ "type": "class",
3123
+ "named": true
3124
+ },
3125
+ {
3126
+ "type": "false",
3127
+ "named": true
3128
+ },
3129
+ {
3130
+ "type": "function_expression",
3131
+ "named": true
3132
+ },
3133
+ {
3134
+ "type": "generator_function",
3135
+ "named": true
3136
+ },
3137
+ {
3138
+ "type": "identifier",
3139
+ "named": true
3140
+ },
3141
+ {
3142
+ "type": "member_expression",
3143
+ "named": true
3144
+ },
3145
+ {
3146
+ "type": "meta_property",
3147
+ "named": true
3148
+ },
3149
+ {
3150
+ "type": "new_expression",
3151
+ "named": true
3152
+ },
3153
+ {
3154
+ "type": "non_null_expression",
3155
+ "named": true
3156
+ },
3157
+ {
3158
+ "type": "null",
3159
+ "named": true
3160
+ },
3161
+ {
3162
+ "type": "number",
3163
+ "named": true
3164
+ },
3165
+ {
3166
+ "type": "object",
3167
+ "named": true
3168
+ },
3169
+ {
3170
+ "type": "parenthesized_expression",
3171
+ "named": true
3172
+ },
3173
+ {
3174
+ "type": "regex",
3175
+ "named": true
3176
+ },
3177
+ {
3178
+ "type": "string",
3179
+ "named": true
3180
+ },
3181
+ {
3182
+ "type": "subscript_expression",
3183
+ "named": true
3184
+ },
3185
+ {
3186
+ "type": "super",
3187
+ "named": true
3188
+ },
3189
+ {
3190
+ "type": "template_string",
3191
+ "named": true
3192
+ },
3193
+ {
3194
+ "type": "this",
3195
+ "named": true
3196
+ },
3197
+ {
3198
+ "type": "true",
3199
+ "named": true
3200
+ },
3201
+ {
3202
+ "type": "undefined",
3111
3203
  "named": true
3112
3204
  }
3113
3205
  ]