@willbooster/tree-sitter-typescript 1.2.3 → 1.2.5

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
@@ -105,7 +105,8 @@ cargo test
105
105
  Cases run with the `typescript` grammar unless they carry `:language(tsx)`;
106
106
  - an incremental-parsing check (`test/unit/incremental.test.ts`): `script/fuzz-corpus` runs `tree-sitter fuzz`, which
107
107
  edits each corpus case of each grammar at random, reparses it, undoes the edits, and reparses again, on the
108
- WillBooster/tree-sitter runtime version locked in `Cargo.lock` (the first run builds that CLI with `cargo`).
108
+ WillBooster/tree-sitter runtime version locked in `Cargo.lock` (the first run downloads that CLI from its GitHub
109
+ Release, or builds it with `cargo` when the download fails or the release has no binary that runs here).
109
110
  `TREE_SITTER_SEED`, `TREE_SITTER_ITERATIONS`, and `TREE_SITTER_EDITS` run other or more edits;
110
111
  - a check that the real-world files in `examples/`, the checked-in ones and those of the cloned repositories, fail to
111
112
  parse exactly as listed in `script/known-failures.txt`. `.ts` files are parsed with the `typescript` grammar and
@@ -1,6 +1,26 @@
1
1
  // oxlint-disable unicorn/prefer-module -- This package is CommonJS, so tree-sitter loads the grammar as CommonJS.
2
2
  const JavaScript = require('@willbooster/tree-sitter-javascript/grammar');
3
3
 
4
+ // Words that are keywords only in some positions and identifiers elsewhere, besides the JavaScript grammar's.
5
+ const TYPESCRIPT_CONTEXTUAL_KEYWORDS = [
6
+ 'declare',
7
+ 'namespace',
8
+ 'type',
9
+ 'public',
10
+ 'private',
11
+ 'protected',
12
+ 'override',
13
+ 'readonly',
14
+ 'module',
15
+ 'any',
16
+ 'number',
17
+ 'boolean',
18
+ 'string',
19
+ 'symbol',
20
+ 'object',
21
+ 'new',
22
+ ];
23
+
4
24
  module.exports = function defineGrammar(dialect) {
5
25
  return grammar(JavaScript, {
6
26
  name: dialect,
@@ -63,6 +83,8 @@ module.exports = function defineGrammar(dialect) {
63
83
  [$.primary_expression, $._for_header, $._for_using_declaration],
64
84
  [$._for_header, $._binding_identifier],
65
85
  [$.expression, $.call_expression, $.instantiation_expression],
86
+ [$._field_name, $._property_name],
87
+ [$._property_name, $.public_field_definition],
66
88
 
67
89
  // This appears to be necessary to parse a parenthesized class expression
68
90
  [$.class],
@@ -118,6 +140,9 @@ module.exports = function defineGrammar(dialect) {
118
140
  ],
119
141
 
120
142
  rules: {
143
+ // A field named `get`, `set`, or `static` is told apart from a member that the word modifies by the line-break
144
+ // sentinels allowed right after the name, as in the JavaScript grammar's field_definition. They are not allowed
145
+ // after a type annotation, which may continue on the next line.
121
146
  public_field_definition: ($) =>
122
147
  seq(
123
148
  repeat(field('decorator', $.decorator)),
@@ -128,17 +153,64 @@ module.exports = function defineGrammar(dialect) {
128
153
  )
129
154
  ),
130
155
  choice(
131
- seq(optional('static'), optional($.override_modifier), optional('readonly')),
132
- seq(optional('abstract'), optional('readonly')),
133
- seq(optional('readonly'), optional('abstract')),
134
- optional('accessor')
135
- ),
136
- field('name', $._property_name),
137
- optional(choice('?', '!')),
138
- field('type', optional($.type_annotation)),
139
- optional($._initializer)
156
+ seq(
157
+ choice(
158
+ seq(optional('static'), optional($.override_modifier), optional('readonly')),
159
+ seq(optional('abstract'), optional('readonly')),
160
+ seq(optional('readonly'), optional('abstract')),
161
+ optional('accessor')
162
+ ),
163
+ choice(
164
+ seq(
165
+ field('name', $._field_name),
166
+ choice(
167
+ optional(choice($._initializer, $._line_break_after_field)),
168
+ seq($._field_annotations, optional($._initializer))
169
+ )
170
+ ),
171
+ // A line break after `get` or `set` continues a getter or setter. Allowing both sentinels here tells
172
+ // the scanner that a `*` on the next line cannot continue the member, unlike after `static`.
173
+ seq(
174
+ field('name', alias(choice('get', 'set'), $.property_identifier)),
175
+ choice(
176
+ optional(choice($._initializer, $._line_break_after_modifier, $._line_break_after_field)),
177
+ seq($._field_annotations, optional($._initializer))
178
+ )
179
+ )
180
+ )
181
+ ),
182
+ // A line break after a leading `static` continues a static member.
183
+ seq(
184
+ field('name', alias('static', $.property_identifier)),
185
+ choice(
186
+ optional(choice($._initializer, $._line_break_after_modifier)),
187
+ seq($._field_annotations, optional($._initializer))
188
+ )
189
+ ),
190
+ // After a modifier, `static` is a field name, which a line break ends.
191
+ seq(
192
+ choice(
193
+ seq('static', optional($.override_modifier), optional('readonly')),
194
+ seq($.override_modifier, optional('readonly')),
195
+ seq('readonly', optional('abstract')),
196
+ seq('abstract', optional('readonly')),
197
+ 'accessor'
198
+ ),
199
+ field('name', alias('static', $.property_identifier)),
200
+ choice(
201
+ optional(choice($._initializer, $._line_break_after_field)),
202
+ seq($._field_annotations, optional($._initializer))
203
+ )
204
+ )
205
+ )
140
206
  ),
141
207
 
208
+ _field_annotations: ($) =>
209
+ choice(seq(choice('?', '!'), field('type', optional($.type_annotation))), field('type', $.type_annotation)),
210
+
211
+ _field_name: ($, previous) =>
212
+ choice(previous, alias(choice(...TYPESCRIPT_CONTEXTUAL_KEYWORDS), $.property_identifier)),
213
+
142
214
  // override original catch_clause, add optional type annotation
143
215
  catch_clause: ($) =>
144
216
  seq(
@@ -251,15 +323,6 @@ module.exports = function defineGrammar(dialect) {
251
323
  )
252
324
  ),
253
325
 
254
- // Any identifier name may name a JSX attribute, such as `class` in `<div class="x" />`, which the JavaScript
255
- // grammar's reserved words reject (WillBooster/tree-sitter-javascript#25).
256
- _jsx_attribute_name: ($) =>
257
- choice(
258
- alias($.jsx_identifier, $.property_identifier),
259
- alias(reserved('properties', $.identifier), $.property_identifier),
260
- $.jsx_namespace_name
261
- ),
262
-
263
326
  // This rule is only referenced by expression when the dialect is 'tsx'
264
327
  jsx_opening_element: ($) => prec.dynamic(-1, seq($._jsx_start_opening_element, '>')),
265
328
 
@@ -268,9 +331,7 @@ module.exports = function defineGrammar(dialect) {
268
331
 
269
332
  export_specifier: (_, previous) => seq(optional(choice('type', 'typeof')), previous),
270
333
 
271
- // Any identifier name may be exported or imported. The JavaScript grammar rejects reserved words other than
272
- // `default`, for which it leaves no node (WillBooster/tree-sitter-javascript#17 and #24).
273
- _module_export_name: ($) => choice(reserved('properties', $.identifier), $.string),
334
+ _local_export_specifier: (_, previous) => seq(optional(choice('type', 'typeof')), previous),
274
335
 
275
336
  _import_identifier: ($) => choice($.identifier, alias('type', $.identifier)),
276
337
 
@@ -301,7 +362,7 @@ module.exports = function defineGrammar(dialect) {
301
362
  'import',
302
363
  optional(choice('type', 'typeof')),
303
364
  choice(seq($.import_clause, $._from_clause), $.import_require_clause, field('source', $.string)),
304
- optional($.import_attribute),
365
+ optional(choice($.import_attribute, $._line_break_before_attributes)),
305
366
  $._semicolon
306
367
  ),
307
368
 
@@ -314,33 +375,6 @@ module.exports = function defineGrammar(dialect) {
314
375
  seq('export', 'as', 'namespace', $.identifier, $._semicolon)
315
376
  ),
316
377
 
317
- // The JavaScript grammar leaves `await (x).y` ambiguous with a call of an identifier named `await`, and GLR keeps
318
- // the call; TypeScript and V8 read the operator (WillBooster/tree-sitter-javascript#23).
319
- await_expression: ($) => prec.dynamic(2, prec('unary_void', seq('await', $.expression))),
320
-
321
- // The JavaScript grammar's for header takes no `using` declaration, although ECMAScript allows one.
322
- for_statement: ($) =>
323
- seq(
324
- 'for',
325
- '(',
326
- choice(
327
- field(
328
- 'initializer',
329
- choice(
330
- alias($.for_lexical_declaration, $.lexical_declaration),
331
- alias($.for_variable_declaration, $.variable_declaration),
332
- alias($._for_using_declaration, $.using_declaration)
333
- )
334
- ),
335
- seq(field('initializer', $._expressions), ';'),
336
- field('initializer', $.empty_statement)
337
- ),
338
- field('condition', choice(seq($._expressions, ';'), $.empty_statement)),
339
- field('increment', optional($._expressions)),
340
- ')',
341
- field('body', $.statement)
342
- ),
343
-
344
378
  // ECMAScript binds only identifiers in a using declaration, so `using [a] = b` assigns to a subscript of a
345
379
  // variable named `using`.
346
380
  using_declaration: ($) =>
@@ -391,8 +425,11 @@ module.exports = function defineGrammar(dialect) {
391
425
  choice(
392
426
  seq(
393
427
  field('name', choice($._binding_identifier, $._destructuring_pattern)),
394
- field('type', optional($.type_annotation)),
395
- optional($._initializer)
428
+ // The line-break sentinel applies only right after the name: a type may continue on the next line.
429
+ choice(
430
+ optional(choice($._initializer, $._line_break_after_binding)),
431
+ seq(field('type', $.type_annotation), optional($._initializer))
432
+ )
396
433
  ),
397
434
  prec('declaration', seq(field('name', $._binding_identifier), '!', field('type', $.type_annotation)))
398
435
  ),
@@ -450,7 +487,14 @@ module.exports = function defineGrammar(dialect) {
450
487
  prec(
451
488
  'call',
452
489
  seq(
453
- field('function', choice($.identifier, alias($.decorator_member_expression, $.member_expression))),
490
+ field(
491
+ 'function',
492
+ choice(
493
+ $.identifier,
494
+ alias($.decorator_member_expression, $.member_expression),
495
+ alias($.decorator_parenthesized_expression, $.parenthesized_expression)
496
+ )
497
+ ),
454
498
  optional(field('type_arguments', $.type_arguments)),
455
499
  field('arguments', $.arguments)
456
500
  )
@@ -458,18 +502,6 @@ module.exports = function defineGrammar(dialect) {
458
502
 
459
503
  decorator_parenthesized_expression: ($) => seq('(', $._expressions, ')'),
460
504
 
461
- // A decorator's member name may be any identifier name, as a member expression's may, which the JavaScript
462
- // grammar's reserved words reject.
463
- decorator_member_expression: ($) =>
464
- prec(
465
- 'member',
466
- seq(
467
- field('object', choice($.identifier, alias($.decorator_member_expression, $.member_expression))),
468
- '.',
469
- field('property', reserved('properties', alias($.identifier, $.property_identifier)))
470
- )
471
- ),
472
-
473
505
  class_body: ($) =>
474
506
  seq(
475
507
  '{',
@@ -508,7 +540,7 @@ module.exports = function defineGrammar(dialect) {
508
540
  field('name', $._property_name),
509
541
  optional('?'),
510
542
  $._call_signature,
511
- field('body', $.statement_block)
543
+ field('body', alias($._class_member_body, $.statement_block))
512
544
  )
513
545
  ),
514
546
 
@@ -619,17 +651,6 @@ module.exports = function defineGrammar(dialect) {
619
651
 
620
652
  import_alias: ($) => seq('import', $.identifier, '=', choice($.identifier, $.nested_identifier), $._semicolon),
621
653
 
622
- // A qualified name may end in any identifier name, as a member expression may.
623
- nested_identifier: ($) =>
624
- prec(
625
- 'member',
626
- seq(
627
- field('object', choice($.identifier, alias($.nested_identifier, $.member_expression))),
628
- '.',
629
- field('property', reserved('properties', alias($.identifier, $.property_identifier)))
630
- )
631
- ),
632
-
633
654
  nested_type_identifier: ($) =>
634
655
  prec(
635
656
  'member',
@@ -1112,29 +1133,7 @@ module.exports = function defineGrammar(dialect) {
1112
1133
  // allowed on the identifier inside the alias: around the alias, the keyword token still wins in the lexer.
1113
1134
  _type_identifier: ($) => alias(reserved('properties', $.identifier), $.type_identifier),
1114
1135
 
1115
- _reserved_identifier: (_, previous) =>
1116
- choice(
1117
- 'declare',
1118
- 'namespace',
1119
- 'type',
1120
- 'public',
1121
- 'private',
1122
- 'protected',
1123
- 'override',
1124
- 'readonly',
1125
- 'module',
1126
- 'any',
1127
- 'number',
1128
- 'boolean',
1129
- 'string',
1130
- 'symbol',
1131
- 'export',
1132
- 'object',
1133
- 'new',
1134
- 'readonly',
1135
- 'using',
1136
- previous
1137
- ),
1136
+ _reserved_identifier: (_, previous) => choice(...TYPESCRIPT_CONTEXTUAL_KEYWORDS, previous),
1138
1137
  },
1139
1138
  });
1140
1139
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willbooster/tree-sitter-typescript",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "TypeScript and TSX grammars for tree-sitter",
5
5
  "keywords": [
6
6
  "incremental",
@@ -43,14 +43,13 @@
43
43
  "verify-full": "bun wb verify --full"
44
44
  },
45
45
  "devDependencies": {
46
- "@semantic-release/exec": "7.1.0",
47
46
  "@tsconfig/bun": "1.0.11",
48
47
  "@types/bun": "1.4.2",
49
48
  "@vitest/browser-playwright": "5.0.1",
50
49
  "@willbooster/oxfmt-config": "1.2.2",
51
50
  "@willbooster/oxlint-config": "1.4.8",
52
- "@willbooster/tree-sitter-javascript": "1.0.3",
53
- "@willbooster/wb": "22.11.5",
51
+ "@willbooster/tree-sitter-javascript": "1.0.15",
52
+ "@willbooster/wb": "22.13.0",
54
53
  "@willbooster/web-tree-sitter": "1.0.7",
55
54
  "conventional-changelog-conventionalcommits": "10.4.0",
56
55
  "lefthook": "2.1.14",
Binary file
Binary file
package/tree-sitter.json CHANGED
@@ -77,7 +77,7 @@
77
77
  }
78
78
  ],
79
79
  "metadata": {
80
- "version": "1.2.3",
80
+ "version": "1.2.5",
81
81
  "license": "MIT",
82
82
  "description": "TypeScript and TSX grammars for tree-sitter",
83
83
  "authors": [
@@ -159,6 +159,10 @@
159
159
  "type": "object_pattern",
160
160
  "named": true
161
161
  },
162
+ {
163
+ "type": "parenthesized_expression",
164
+ "named": true
165
+ },
162
166
  {
163
167
  "type": "rest_pattern",
164
168
  "named": true
@@ -2018,7 +2022,7 @@
2018
2022
  }
2019
2023
  },
2020
2024
  "children": {
2021
- "multiple": false,
2025
+ "multiple": true,
2022
2026
  "required": false,
2023
2027
  "types": [
2024
2028
  {
@@ -2033,6 +2037,10 @@
2033
2037
  "type": "identifier",
2034
2038
  "named": true
2035
2039
  },
2040
+ {
2041
+ "type": "import_attribute",
2042
+ "named": true
2043
+ },
2036
2044
  {
2037
2045
  "type": "namespace_export",
2038
2046
  "named": true
@@ -4739,6 +4747,10 @@
4739
4747
  "type": "object_pattern",
4740
4748
  "named": true
4741
4749
  },
4750
+ {
4751
+ "type": "parenthesized_expression",
4752
+ "named": true
4753
+ },
4742
4754
  {
4743
4755
  "type": "subscript_expression",
4744
4756
  "named": true
@@ -155,6 +155,10 @@
155
155
  "type": "object_pattern",
156
156
  "named": true
157
157
  },
158
+ {
159
+ "type": "parenthesized_expression",
160
+ "named": true
161
+ },
158
162
  {
159
163
  "type": "rest_pattern",
160
164
  "named": true
@@ -2014,7 +2018,7 @@
2014
2018
  }
2015
2019
  },
2016
2020
  "children": {
2017
- "multiple": false,
2021
+ "multiple": true,
2018
2022
  "required": false,
2019
2023
  "types": [
2020
2024
  {
@@ -2029,6 +2033,10 @@
2029
2033
  "type": "identifier",
2030
2034
  "named": true
2031
2035
  },
2036
+ {
2037
+ "type": "import_attribute",
2038
+ "named": true
2039
+ },
2032
2040
  {
2033
2041
  "type": "namespace_export",
2034
2042
  "named": true
@@ -4490,6 +4498,10 @@
4490
4498
  "type": "object_pattern",
4491
4499
  "named": true
4492
4500
  },
4501
+ {
4502
+ "type": "parenthesized_expression",
4503
+ "named": true
4504
+ },
4493
4505
  {
4494
4506
  "type": "subscript_expression",
4495
4507
  "named": true