@willbooster/tree-sitter-typescript 1.2.13 → 1.3.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
@@ -108,7 +108,12 @@ runtime this package ships. The first run downloads that CLI from its GitHub Rel
108
108
  `cargo` (with the `cmake` that `mise.toml` pins) when the download fails or the release has no binary that runs here.
109
109
 
110
110
  `bun run test/ci-setup` installs Chromium for the browser tests. `bun run build/ci` regenerates `typescript/src/` and
111
- `tsx/src/` and builds both Wasm files. `bun run test` runs:
111
+ `tsx/src/` and builds both Wasm files. It also refreshes `common/typeScriptKeywords.h` from the pinned
112
+ `typescript-reference` API (TypeScript 5.9.3), which supplies the global-augmentation lookahead vocabulary.
113
+ The native TypeScript package remains the type checker. Run `bun run generate-keywords` after changing the reference;
114
+ verification checks the committed header with `bun run check-keywords`.
115
+
116
+ `bun run test` runs:
112
117
 
113
118
  - the corpus in `test/corpus`, with the native build and with the Wasm build (the first run downloads the WASI SDK).
114
119
  Cases run with the `typescript` grammar unless they carry `:language(tsx)`;
@@ -4,6 +4,7 @@ const JavaScript = require('@willbooster/tree-sitter-javascript/grammar');
4
4
  // Words that are keywords only in some positions and identifiers elsewhere, besides the JavaScript grammar's.
5
5
  const TYPESCRIPT_CONTEXTUAL_KEYWORDS = [
6
6
  'declare',
7
+ 'global',
7
8
  'namespace',
8
9
  'type',
9
10
  'public',
@@ -18,6 +19,7 @@ const TYPESCRIPT_CONTEXTUAL_KEYWORDS = [
18
19
  'string',
19
20
  'symbol',
20
21
  'object',
22
+ 'out',
21
23
  'new',
22
24
  ];
23
25
 
@@ -64,6 +66,8 @@ module.exports = function defineGrammar(dialect) {
64
66
  $._type_arguments_end,
65
67
  $._type_arguments_end_before_expression,
66
68
  $._new_type_arguments_end,
69
+ $._global_declaration_start,
70
+ $._global_declaration_end,
67
71
  $.__error_recovery,
68
72
  ],
69
73
 
@@ -118,7 +122,7 @@ module.exports = function defineGrammar(dialect) {
118
122
  [$.type_query, $._type_query_subscript_expression],
119
123
  [$.nested_type_identifier, $.generic_type, $.primary_type, $.lookup_type, $.index_type_query, $.type],
120
124
  // 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],
125
+ [$.nested_identifier, $._in_nested_identifier, $.nested_type_identifier],
122
126
  [$.as_expression, $.satisfies_expression, $.primary_type],
123
127
  [$._type_query_member_expression, $.member_expression],
124
128
  [$.member_expression, $._type_query_member_expression_in_type_annotation],
@@ -189,6 +193,7 @@ module.exports = function defineGrammar(dialect) {
189
193
  ? [[$.primary_type, $.type_parameter]]
190
194
  : [
191
195
  [$.jsx_opening_element, $.type_parameter],
196
+ [$.jsx_opening_element, $.jsx_self_closing_element, $.type_parameter],
192
197
  [$.jsx_namespace_name, $.primary_type],
193
198
  ]),
194
199
  [
@@ -205,6 +210,7 @@ module.exports = function defineGrammar(dialect) {
205
210
  inline: ($, previous) => [
206
211
  ...previous.filter((rule) => !['_formal_parameter', '_call_signature'].includes(rule.name)),
207
212
  $._type_identifier,
213
+ $._type_reference_identifier,
208
214
  $._jsx_start_opening_element,
209
215
  ],
210
216
 
@@ -410,6 +416,35 @@ module.exports = function defineGrammar(dialect) {
410
416
  return choice(...choices);
411
417
  },
412
418
 
419
+ _jsx_identifier: ($, previous) => choice(previous, alias(choice('in', 'out'), $.identifier)),
420
+
421
+ nested_identifier: ($) =>
422
+ prec(
423
+ 'member',
424
+ seq(
425
+ field(
426
+ 'object',
427
+ choice(
428
+ reserved('properties', $.identifier),
429
+ alias('out', $.identifier),
430
+ alias($.nested_identifier, $.member_expression)
431
+ )
432
+ ),
433
+ ...nestedIdentifierTail($)
434
+ )
435
+ ),
436
+
437
+ _in_nested_identifier: ($) =>
438
+ prec(
439
+ 'member',
440
+ seq(
441
+ field('object', choice(alias('in', $.identifier), alias($._in_nested_identifier, $.member_expression))),
442
+ ...nestedIdentifierTail($)
443
+ )
444
+ ),
445
+
446
+ _jsx_element_name: ($, previous) => choice(previous, alias($._in_nested_identifier, $.member_expression)),
447
+
413
448
  _jsx_start_opening_element: ($) =>
414
449
  seq(
415
450
  '<',
@@ -418,7 +453,14 @@ module.exports = function defineGrammar(dialect) {
418
453
  choice(
419
454
  field('name', choice($._jsx_identifier, $.jsx_namespace_name)),
420
455
  seq(
421
- field('name', choice($.identifier, alias($.nested_identifier, $.member_expression))),
456
+ field(
457
+ 'name',
458
+ choice(
459
+ $._jsx_identifier,
460
+ alias($.nested_identifier, $.member_expression),
461
+ alias($._in_nested_identifier, $.member_expression)
462
+ )
463
+ ),
422
464
  field('type_arguments', optional($.type_arguments))
423
465
  )
424
466
  ),
@@ -473,6 +515,7 @@ module.exports = function defineGrammar(dialect) {
473
515
  export_statement: ($, previous) =>
474
516
  choice(
475
517
  previous,
518
+ seq('export', field('declaration', alias($.global_declaration, $.internal_module))),
476
519
  seq('export', 'type', $.export_clause, optional($._from_clause), $._semicolon),
477
520
  seq('export', 'type', choice('*', $.namespace_export), $._from_clause, $._semicolon),
478
521
  seq('export', '=', $.expression, $._semicolon),
@@ -649,6 +692,8 @@ module.exports = function defineGrammar(dialect) {
649
692
  )
650
693
  ),
651
694
 
695
+ statement: ($, previous) => choice(previous, alias($.global_declaration, $.internal_module)),
696
+
652
697
  declaration: ($, previous) =>
653
698
  choice(
654
699
  previous,
@@ -706,7 +751,7 @@ module.exports = function defineGrammar(dialect) {
706
751
  'declare',
707
752
  choice(
708
753
  $.declaration,
709
- seq('global', $.statement_block),
754
+ seq(alias($._global_declaration_start, 'global'), choice($.statement_block, $._global_declaration_end)),
710
755
  seq('module', '.', alias($.identifier, $.property_identifier), ':', $.type, $._semicolon)
711
756
  )
712
757
  ),
@@ -756,22 +801,50 @@ module.exports = function defineGrammar(dialect) {
756
801
 
757
802
  internal_module: ($) => seq('namespace', $._module),
758
803
 
804
+ global_declaration: ($) =>
805
+ seq(
806
+ field('name', alias($._global_declaration_start, $.identifier)),
807
+ choice(field('body', $.statement_block), $._global_declaration_end)
808
+ ),
809
+
759
810
  _module: ($) =>
760
811
  prec.right(
761
812
  seq(
762
- field('name', choice($.string, reserved('properties', $.identifier), $.nested_identifier)),
813
+ field(
814
+ 'name',
815
+ choice($.string, reserved('properties', $.identifier), alias('out', $.identifier), $.nested_identifier)
816
+ ),
763
817
  // On .d.ts files "declare module foo" desugars to "declare module foo {}",
764
818
  // hence why it is optional here
765
819
  field('body', optional($.statement_block))
766
820
  )
767
821
  ),
768
822
 
769
- import_alias: ($) => seq('import', $.identifier, '=', choice($.identifier, $.nested_identifier), $._semicolon),
823
+ import_alias: ($) =>
824
+ seq(
825
+ 'import',
826
+ $.identifier,
827
+ '=',
828
+ choice($.identifier, alias('out', $.identifier), $.nested_identifier),
829
+ $._semicolon
830
+ ),
770
831
 
771
832
  nested_type_identifier: ($) =>
772
833
  prec(
773
834
  'member',
774
- seq(field('module', choice($.identifier, $.nested_identifier)), '.', field('name', $._type_identifier))
835
+ seq(
836
+ field(
837
+ 'module',
838
+ choice(
839
+ $.identifier,
840
+ alias(choice('in', 'out'), $.identifier),
841
+ $.nested_identifier,
842
+ alias($._in_nested_identifier, $.nested_identifier)
843
+ )
844
+ ),
845
+ '.',
846
+ field('name', $._type_reference_identifier)
847
+ )
775
848
  ),
776
849
 
777
850
  interface_declaration: ($) =>
@@ -862,7 +935,7 @@ module.exports = function defineGrammar(dialect) {
862
935
  field('arguments', $.arguments)
863
936
  ),
864
937
 
865
- asserts: ($) => seq('asserts', choice($.type_predicate, $.identifier, $.this)),
938
+ asserts: ($) => seq('asserts', choice($.type_predicate, $.identifier, alias('out', $.identifier), $.this)),
866
939
 
867
940
  asserts_annotation: ($) => seq(seq(':', $.asserts)),
868
941
 
@@ -885,11 +958,8 @@ module.exports = function defineGrammar(dialect) {
885
958
 
886
959
  optional_tuple_parameter: ($) => seq(field('name', $._tuple_label), '?', field('type', $.type_annotation)),
887
960
 
888
- _tuple_rest_label: ($) => seq('...', $._tuple_label),
961
+ _tuple_rest_label: ($) => seq('...', choice($._tuple_label, alias('in', $.identifier))),
889
962
 
890
- // TypeScript accepts any identifier name as a tuple label, but where a tuple member begins, the keywords that
891
- // can begin a type are lexed as those keywords, so they are listed here. Keywords that are rules of their own
892
- // are aliased as rules: repeating their strings would turn those rules into nodes that wrap a token.
893
963
  _tuple_label: ($) =>
894
964
  choice(
895
965
  $.identifier,
@@ -905,6 +975,7 @@ module.exports = function defineGrammar(dialect) {
905
975
  'never',
906
976
  'object',
907
977
  'readonly',
978
+ 'out',
908
979
  'keyof',
909
980
  'infer',
910
981
  'typeof',
@@ -948,7 +1019,7 @@ module.exports = function defineGrammar(dialect) {
948
1019
  choice(
949
1020
  $.parenthesized_type,
950
1021
  $.predefined_type,
951
- $._type_identifier,
1022
+ $._type_reference_identifier,
952
1023
  $.nested_type_identifier,
953
1024
  $.generic_type,
954
1025
  $.object_type,
@@ -995,7 +1066,7 @@ module.exports = function defineGrammar(dialect) {
995
1066
  field(
996
1067
  'name',
997
1068
  choice(
998
- $._type_identifier,
1069
+ $._type_reference_identifier,
999
1070
  $.nested_type_identifier,
1000
1071
  alias($._type_query_member_expression_in_type_annotation, $.member_expression)
1001
1072
  )
@@ -1010,6 +1081,7 @@ module.exports = function defineGrammar(dialect) {
1010
1081
  'name',
1011
1082
  choice(
1012
1083
  $.identifier,
1084
+ alias('out', $.identifier),
1013
1085
  $.this,
1014
1086
  // Sometimes tree-sitter contextual lexing is not good enough to know
1015
1087
  // that 'object' in ':object is foo' is really an identifier and not
@@ -1189,7 +1261,7 @@ module.exports = function defineGrammar(dialect) {
1189
1261
 
1190
1262
  type_parameter: ($) =>
1191
1263
  seq(
1192
- optional('const'),
1264
+ repeat(choice('const', 'in', 'out')),
1193
1265
  field('name', $._type_identifier),
1194
1266
  field('constraint', optional($.constraint)),
1195
1267
  field('value', optional($.default_type))
@@ -1252,13 +1324,28 @@ module.exports = function defineGrammar(dialect) {
1252
1324
 
1253
1325
  // A type name may be a reserved word, which TypeScript reports only as a semantic error. The reserved words must be
1254
1326
  // allowed on the identifier inside the alias: around the alias, the keyword token still wins in the lexer.
1255
- _type_identifier: ($) => alias(reserved('properties', $.identifier), $.type_identifier),
1327
+ _type_identifier: ($) => alias(choice(reserved('properties', $.identifier), 'out'), $.type_identifier),
1328
+
1329
+ _type_reference_identifier: ($) => choice($._type_identifier, alias('in', $.type_identifier)),
1256
1330
 
1257
1331
  _reserved_identifier: (_, previous) => choice(...TYPESCRIPT_CONTEXTUAL_KEYWORDS, previous),
1258
1332
  },
1259
1333
  });
1260
1334
  };
1261
1335
 
1336
+ function nestedIdentifierTail($) {
1337
+ return [
1338
+ '.',
1339
+ field(
1340
+ 'property',
1341
+ choice(
1342
+ reserved('properties', alias($.identifier, $.property_identifier)),
1343
+ alias(choice('in', 'out'), $.property_identifier)
1344
+ )
1345
+ ),
1346
+ ];
1347
+ }
1348
+
1262
1349
  /**
1263
1350
  * Creates a rule to match one or more of the rules separated by a comma
1264
1351
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@willbooster/tree-sitter-typescript",
3
- "version": "1.2.13",
3
+ "version": "1.3.0",
4
4
  "description": "TypeScript and TSX grammars for tree-sitter",
5
5
  "keywords": [
6
6
  "incremental",
@@ -28,9 +28,11 @@
28
28
  ],
29
29
  "scripts": {
30
30
  "build-wasm": "script/tree-sitter build --wasm typescript && script/tree-sitter build --wasm tsx",
31
- "build/ci": "script/tree-sitter generate typescript/grammar.js && script/tree-sitter generate tsx/grammar.js && bun run build-wasm",
32
- "cleanup": "bun wb lint --fix --format",
31
+ "build/ci": "bun run generate-keywords && script/tree-sitter generate typescript/grammar.js && script/tree-sitter generate tsx/grammar.js && bun run build-wasm",
32
+ "check-keywords": "bun scripts/generateGlobalKeywords.ts --check",
33
+ "cleanup": "bun run check-keywords && bun wb lint --fix --format",
33
34
  "format": "bun wb lint --format",
35
+ "generate-keywords": "bun scripts/generateGlobalKeywords.ts",
34
36
  "lint": "bun wb lint",
35
37
  "lint-fix": "bun wb lint --fix",
36
38
  "prepare": "(bun lefthook install || true) && (test ! -f .lefthook/normalize-bun-lockfile.sh || bash .lefthook/normalize-bun-lockfile.sh)",
@@ -48,24 +50,25 @@
48
50
  "devDependencies": {
49
51
  "@tsconfig/bun": "1.0.11",
50
52
  "@types/bun": "1.4.2",
51
- "@vitest/browser-playwright": "5.0.1",
53
+ "@vitest/browser-playwright": "5.0.2",
52
54
  "@willbooster/oxfmt-config": "1.2.2",
53
55
  "@willbooster/oxlint-config": "1.4.8",
54
56
  "@willbooster/tree-sitter-javascript": "1.0.21",
55
- "@willbooster/wb": "22.13.1",
57
+ "@willbooster/wb": "22.18.0",
56
58
  "@willbooster/web-tree-sitter": "1.0.17",
57
59
  "conventional-changelog-conventionalcommits": "10.4.0",
58
60
  "lefthook": "2.1.14",
59
61
  "oxfmt": "0.70.0",
60
62
  "oxlint": "1.85.0",
61
- "oxlint-tsgolint": "7.0.2002",
63
+ "oxlint-tsgolint": "7.0.2003",
62
64
  "playwright": "1.63.0",
63
65
  "semantic-release": "25.0.9",
64
66
  "sort-package-json": "4.0.0",
65
67
  "typescript": "7.0.2",
68
+ "typescript-reference": "npm:typescript@5.9.3",
66
69
  "vite": "8.3.0",
67
- "vitest": "5.0.1",
68
- "wrangler": "4.135.0"
70
+ "vitest": "5.0.2",
71
+ "wrangler": "4.141.0"
69
72
  },
70
73
  "peerDependencies": {
71
74
  "@willbooster/web-tree-sitter": "^1.0.0"
@@ -33,3 +33,6 @@
33
33
  "override"
34
34
  "satisfies"
35
35
  ] @keyword
36
+
37
+ (type_parameter
38
+ ["in" "out"] @keyword)
Binary file
Binary file
package/tree-sitter.json CHANGED
@@ -83,7 +83,7 @@
83
83
  }
84
84
  ],
85
85
  "metadata": {
86
- "version": "1.2.13",
86
+ "version": "1.3.0",
87
87
  "license": "MIT",
88
88
  "description": "TypeScript and TSX grammars for tree-sitter",
89
89
  "authors": [
@@ -413,6 +413,10 @@
413
413
  "type": "import_statement",
414
414
  "named": true
415
415
  },
416
+ {
417
+ "type": "internal_module",
418
+ "named": true
419
+ },
416
420
  {
417
421
  "type": "labeled_statement",
418
422
  "named": true
@@ -647,7 +651,7 @@
647
651
  "fields": {},
648
652
  "children": {
649
653
  "multiple": true,
650
- "required": true,
654
+ "required": false,
651
655
  "types": [
652
656
  {
653
657
  "type": "declaration",
@@ -6238,6 +6242,10 @@
6238
6242
  "type": "optional_chain",
6239
6243
  "named": true
6240
6244
  },
6245
+ {
6246
+ "type": "out",
6247
+ "named": false
6248
+ },
6241
6249
  {
6242
6250
  "type": "override",
6243
6251
  "named": false
@@ -409,6 +409,10 @@
409
409
  "type": "import_statement",
410
410
  "named": true
411
411
  },
412
+ {
413
+ "type": "internal_module",
414
+ "named": true
415
+ },
412
416
  {
413
417
  "type": "labeled_statement",
414
418
  "named": true
@@ -643,7 +647,7 @@
643
647
  "fields": {},
644
648
  "children": {
645
649
  "multiple": true,
646
- "required": true,
650
+ "required": false,
647
651
  "types": [
648
652
  {
649
653
  "type": "declaration",
@@ -5988,6 +5992,10 @@
5988
5992
  "type": "optional_chain",
5989
5993
  "named": true
5990
5994
  },
5995
+ {
5996
+ "type": "out",
5997
+ "named": false
5998
+ },
5991
5999
  {
5992
6000
  "type": "override",
5993
6001
  "named": false