@willbooster/tree-sitter-typescript 1.2.9 → 1.2.11

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,19 +21,79 @@ 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'],
80
+ // `as` and `satisfies` bind like the relational operators: looser than `**`, `*`, `+`, and `<<`, and tighter than
81
+ // `==`, `&`, `&&`, `||`, and `??`.
82
+ [
83
+ 'binary_exp',
84
+ 'binary_times',
85
+ 'binary_plus',
86
+ 'binary_shift',
87
+ 'binary_relation',
88
+ 'binary',
89
+ 'binary_equality',
90
+ 'bitwise_and',
91
+ 'bitwise_xor',
92
+ 'bitwise_or',
93
+ 'logical_and',
94
+ 'logical_or',
95
+ 'ternary',
96
+ ],
37
97
  [
38
98
  $.intersection_type,
39
99
  $.union_type,
@@ -43,67 +103,67 @@ module.exports = function defineGrammar(dialect) {
43
103
  $.type_predicate,
44
104
  $.readonly_type,
45
105
  ],
46
- [$.mapped_type_clause, $.primary_expression],
47
- [$.accessibility_modifier, $.primary_expression],
106
+ [$.mapped_type_clause, $._type_arguments_target],
107
+ [$.accessibility_modifier, $._type_arguments_target],
48
108
  ['unary_void', $.expression],
49
- [$.extends_clause, $.primary_expression],
109
+ [$.extends_clause, $._type_arguments_target],
50
110
  ['unary', 'assign'],
51
111
  ['declaration', $.expression],
52
112
  [$.predefined_type, $.unary_expression],
53
113
  [$.type, $.flow_maybe_type],
54
114
  [$.tuple_type, $.array_type, $.pattern, $.type],
55
115
  [$.readonly_type, $.pattern],
56
- [$.readonly_type, $.primary_expression],
116
+ [$.readonly_type, $._type_arguments_target],
57
117
  [$.type_query, $.subscript_expression, $.expression],
58
118
  [$.type_query, $._type_query_subscript_expression],
59
119
  [$.nested_type_identifier, $.generic_type, $.primary_type, $.lookup_type, $.index_type_query, $.type],
120
+ // A qualified type name takes every `.` and name that follow it: `x as a.b.C` is not `(x as a.b).C`.
121
+ [$.nested_identifier, $.nested_type_identifier],
60
122
  [$.as_expression, $.satisfies_expression, $.primary_type],
61
123
  [$._type_query_member_expression, $.member_expression],
62
124
  [$.member_expression, $._type_query_member_expression_in_type_annotation],
63
- [$._type_query_member_expression, $.primary_expression],
125
+ [$._type_query_member_expression, $._type_arguments_target],
64
126
  [$._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],
127
+ [$._type_query_subscript_expression, $._type_arguments_target],
128
+ [$._type_query_call_expression, $._type_arguments_target],
129
+ [$._type_query_instantiation_expression, $._type_arguments_target],
130
+ [$.type_query, $._type_arguments_target],
131
+ [$.override_modifier, $._type_arguments_target],
70
132
  [$.decorator_call_expression, $.decorator],
71
133
  [$.literal_type, $.pattern],
72
134
  [$.predefined_type, $.pattern],
73
135
  [$.call_expression, $._type_query_call_expression],
74
136
  [$.call_expression, $._type_query_call_expression_in_type_annotation],
75
- [$.new_expression, $.primary_expression],
76
- [$.meta_property, $.primary_expression],
137
+ [$.new_expression, $._type_arguments_target],
138
+ [$.meta_property, $._type_arguments_target],
77
139
  [$.construct_signature, $._property_name],
78
140
  ],
79
141
 
80
142
  conflicts: ($, previous) => [
81
- ...previous,
82
- [$.primary_expression, $.using_declaration],
83
- [$.primary_expression, $._for_header, $._for_using_declaration],
143
+ ...withTypeArgumentsTarget($, previous),
144
+ [$._type_arguments_target, $.using_declaration],
145
+ [$._type_arguments_target, $._for_header, $._for_using_declaration],
84
146
  [$._for_header, $._binding_identifier],
85
- [$.expression, $.call_expression, $.instantiation_expression],
86
147
  [$._field_name, $._property_name],
87
148
  [$._property_name, $.public_field_definition],
88
149
 
89
150
  // This appears to be necessary to parse a parenthesized class expression
90
151
  [$.class],
91
152
 
92
- [$.nested_identifier, $.nested_type_identifier, $.primary_expression],
93
- [$.nested_identifier, $.nested_type_identifier],
153
+ [$.nested_identifier, $.nested_type_identifier, $._type_arguments_target],
94
154
 
95
155
  [$._call_signature, $.function_type],
96
156
  [$._call_signature, $.constructor_type],
97
157
 
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],
158
+ [$._type_arguments_target, $._parameter_name],
159
+ [$._type_arguments_target, $._parameter_name, $.primary_type],
160
+ [$._type_arguments_target, $.literal_type],
161
+ [$._type_arguments_target, $.literal_type, $.rest_pattern],
162
+ [$._type_arguments_target, $.predefined_type, $.rest_pattern],
163
+ [$._type_arguments_target, $.primary_type],
164
+ [$._type_arguments_target, $.generic_type],
165
+ [$._type_arguments_target, $.predefined_type],
166
+ [$._type_arguments_target, $.pattern, $.primary_type],
107
167
  [$._parameter_name, $.primary_type],
108
168
  [$.pattern, $.primary_type],
109
169
 
@@ -112,7 +172,7 @@ module.exports = function defineGrammar(dialect) {
112
172
  [$._tuple_label, $.index_type_query],
113
173
  [$._tuple_label, $.readonly_type],
114
174
  [$._tuple_label, $.predefined_type],
115
- [$.rest_pattern, $.primary_type, $.primary_expression],
175
+ [$.rest_pattern, $.primary_type, $._type_arguments_target],
116
176
 
117
177
  [$.object, $.object_type],
118
178
  [$.object, $.object_pattern, $.object_type],
@@ -131,6 +191,14 @@ module.exports = function defineGrammar(dialect) {
131
191
  [$.jsx_opening_element, $.type_parameter],
132
192
  [$.jsx_namespace_name, $.primary_type],
133
193
  ]),
194
+ [
195
+ $.primary_expression,
196
+ $.call_expression,
197
+ $._argumentless_new_expression,
198
+ $.new_expression,
199
+ $.instantiation_expression,
200
+ ],
201
+ [$.primary_expression, $.call_expression, $.instantiation_expression],
134
202
  ],
135
203
 
136
204
  inline: ($, previous) => [
@@ -234,15 +302,15 @@ module.exports = function defineGrammar(dialect) {
234
302
  choice(
235
303
  prec('call', seq(field('function', choice($.expression, $.import)), field('arguments', $.arguments))),
236
304
  // 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)`.
305
+ // could also read the input, as in `a < b > (c)`, TypeScript reads a generic call. A tag with type arguments
306
+ // is parsed like a generic call. Optional type arguments in the `template_call` alternative below would make
307
+ // the parser commit to a tagged template at the `<` of `f<T>(x)`.
240
308
  prec.dynamic(
241
- 1,
309
+ DYNAMIC_PRECEDENCE.TYPE_ARGUMENTS,
242
310
  prec(
243
311
  'generic_call',
244
312
  seq(
245
- field('function', $.primary_expression),
313
+ field('function', $._type_arguments_target),
246
314
  field('type_arguments', $.type_arguments),
247
315
  field('arguments', choice($.arguments, $.template_string))
248
316
  )
@@ -260,23 +328,37 @@ module.exports = function defineGrammar(dialect) {
260
328
  )
261
329
  ),
262
330
 
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)
331
+ new_expression: ($, previous) =>
332
+ choice(
333
+ previous,
334
+ prec.dynamic(
335
+ DYNAMIC_PRECEDENCE.TYPE_ARGUMENTS,
336
+ prec(
337
+ 'new',
338
+ seq(
339
+ 'new',
340
+ field('constructor', $._type_arguments_target),
341
+ field('type_arguments', $.type_arguments),
342
+ field('arguments', $.arguments)
343
+ )
344
+ )
273
345
  )
274
346
  ),
275
347
 
276
- _argumentless_new_expression: ($) =>
277
- prec.right(
278
- 'new',
279
- seq('new', field('constructor', $.primary_expression), field('type_arguments', optional($.type_arguments)))
348
+ // TypeScript reads `new A<B>c` as comparisons, but `new A<B>` before a line break and `c` as a `new` with type
349
+ // arguments, which also take precedence over an extends clause's (`class C extends new A<B>, D {}`).
350
+ _argumentless_new_expression: ($, previous) =>
351
+ choice(
352
+ previous,
353
+ prec.dynamic(
354
+ DYNAMIC_PRECEDENCE.TYPE_ARGUMENTS,
355
+ seq(
356
+ 'new',
357
+ field('constructor', $._type_arguments_target),
358
+ field('type_arguments', $.type_arguments),
359
+ $._new_type_arguments_end
360
+ )
361
+ )
280
362
  ),
281
363
 
282
364
  assignment_expression: ($) =>
@@ -289,7 +371,17 @@ module.exports = function defineGrammar(dialect) {
289
371
 
290
372
  _lhs_expression: ($, previous) => choice(previous, $.non_null_expression),
291
373
 
292
- primary_expression: ($, previous) => choice(previous, $.non_null_expression),
374
+ primary_expression: ($) =>
375
+ choice($._type_arguments_target, alias($._argumentless_new_expression, $.new_expression)),
376
+
377
+ // The primary expressions that type arguments in an expression may follow: TypeScript gives the type arguments
378
+ // after `new A` to the `new` (`new A<T>()`, `new new A<T>()`), so a `new` without arguments takes none.
379
+ _type_arguments_target: ($) => {
380
+ const members = JavaScript.grammar.rules.primary_expression.members.filter(
381
+ (member) => member.type !== 'ALIAS' || member.content.name !== '_argumentless_new_expression'
382
+ );
383
+ return choice(...members, $.non_null_expression);
384
+ },
293
385
 
294
386
  // If the dialect is regular typescript, we exclude JSX expressions and
295
387
  // include type assertions. If the dialect is TSX, we do the opposite.
@@ -568,8 +660,17 @@ module.exports = function defineGrammar(dialect) {
568
660
 
569
661
  satisfies_expression: ($) => prec.left('binary', seq($.expression, 'satisfies', $.type)),
570
662
 
571
- instantiation_expression: ($) =>
572
- prec.dynamic(-1, prec('instantiation', seq($.primary_expression, field('type_arguments', $.type_arguments)))),
663
+ instantiation_expression: ($) => {
664
+ const instantiation = (end) =>
665
+ prec('instantiation', seq($._type_arguments_target, field('type_arguments', $.type_arguments), end));
666
+ return choice(
667
+ prec.dynamic(DYNAMIC_PRECEDENCE.INSTANTIATION, instantiation($._type_arguments_end)),
668
+ prec.dynamic(
669
+ DYNAMIC_PRECEDENCE.INSTANTIATION_BEFORE_EXPRESSION,
670
+ instantiation($._type_arguments_end_before_expression)
671
+ )
672
+ );
673
+ },
573
674
 
574
675
  class_heritage: ($) => choice(seq($.extends_clause, optional($.implements_clause)), $.implements_clause),
575
676
 
@@ -578,7 +679,16 @@ module.exports = function defineGrammar(dialect) {
578
679
  extends_clause: ($) => seq('extends', commaSep1($._extends_clause_single)),
579
680
 
580
681
  _extends_clause_single: ($) =>
581
- prec('extends', seq(field('value', $.expression), field('type_arguments', optional($.type_arguments)))),
682
+ prec(
683
+ 'extends',
684
+ choice(
685
+ field('value', $.expression),
686
+ prec.dynamic(
687
+ DYNAMIC_PRECEDENCE.EXTENDS_TYPE_ARGUMENTS,
688
+ seq(field('value', $.expression), field('type_arguments', $.type_arguments))
689
+ )
690
+ )
691
+ ),
582
692
 
583
693
  implements_clause: ($) => seq('implements', commaSep1($.type)),
584
694
 
@@ -1112,10 +1222,14 @@ module.exports = function defineGrammar(dialect) {
1112
1222
  tuple_type: ($) => seq('[', commaSep($._tuple_type_member), optional(','), ']'),
1113
1223
  readonly_type: ($) => seq('readonly', $.type),
1114
1224
 
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)))),
1225
+ union_type: ($) =>
1226
+ prec.left(
1227
+ choice(seq($.type, '|', $.type), prec.dynamic(DYNAMIC_PRECEDENCE.LEADING_TYPE_OPERATOR, seq('|', $.type)))
1228
+ ),
1229
+ intersection_type: ($) =>
1230
+ prec.left(
1231
+ choice(seq($.type, '&', $.type), prec.dynamic(DYNAMIC_PRECEDENCE.LEADING_TYPE_OPERATOR, seq('&', $.type)))
1232
+ ),
1119
1233
 
1120
1234
  function_type: ($) =>
1121
1235
  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.11",
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.11",
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
  ]