@mnemonik/shared 7.143.0 → 7.144.1
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/dist/ast/astChunker.d.ts.map +1 -1
- package/dist/ast/astChunker.js +6 -1
- package/dist/ast/astChunker.js.map +1 -1
- package/dist/ast/grammars.d.ts +4 -2
- package/dist/ast/grammars.d.ts.map +1 -1
- package/dist/ast/grammars.js +37 -0
- package/dist/ast/grammars.js.map +1 -1
- package/dist/codeScanner.d.ts +3 -0
- package/dist/codeScanner.d.ts.map +1 -1
- package/dist/codeScanner.js +7 -0
- package/dist/codeScanner.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/sourceRedaction.d.ts.map +1 -1
- package/dist/sourceRedaction.js +667 -37
- package/dist/sourceRedaction.js.map +1 -1
- package/dist/vueSource.d.ts +17 -0
- package/dist/vueSource.d.ts.map +1 -0
- package/dist/vueSource.js +63 -0
- package/dist/vueSource.js.map +1 -0
- package/package.json +3 -1
- package/queries/cmake.tags.scm +6 -0
- package/queries/nix.tags.scm +4 -0
- package/queries/objcpp.tags.scm +4 -0
- package/queries/terraform.tags.scm +8 -0
- package/scripts/vendor-grammars.ts +468 -40
- package/src/ast/astChunker.ts +10 -1
- package/src/ast/grammars.ts +34 -1
- package/src/codeScanner.ts +6 -0
- package/src/index.ts +5 -0
- package/src/sourceRedaction.ts +726 -37
- package/src/vueSource.ts +77 -0
- package/wasm/bash.wasm +0 -0
- package/wasm/cmake.LICENSE +21 -0
- package/wasm/cmake.tags.scm +6 -0
- package/wasm/cmake.wasm +0 -0
- package/wasm/cpp.LICENSE +21 -0
- package/wasm/cpp.wasm +0 -0
- package/wasm/groovy.LICENSE +25 -0
- package/wasm/groovy.wasm +0 -0
- package/wasm/nix.LICENSE +21 -0
- package/wasm/nix.tags.scm +4 -0
- package/wasm/nix.wasm +0 -0
- package/wasm/objcpp.LICENSE +28 -0
- package/wasm/objcpp.tags.scm +4 -0
- package/wasm/objcpp.wasm +0 -0
- package/wasm/sql.wasm +0 -0
- package/wasm/terraform.LICENSE +201 -0
- package/wasm/terraform.tags.scm +8 -0
- package/wasm/terraform.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -50,7 +50,7 @@ const OURS_DIR = fileURLToPath(new URL('../queries/', import.meta.url));
|
|
|
50
50
|
interface GrammarSpec {
|
|
51
51
|
/** Vendored artifact basename, and the id the registry keys on. */
|
|
52
52
|
id: string;
|
|
53
|
-
/** npm package
|
|
53
|
+
/** npm package/source archive, or the pinned ObjC++ source repository. */
|
|
54
54
|
pkg: string;
|
|
55
55
|
/**
|
|
56
56
|
* `.wasm` basename inside the tarball when it differs from the package's own
|
|
@@ -73,9 +73,9 @@ interface GrammarSpec {
|
|
|
73
73
|
* remove.
|
|
74
74
|
*
|
|
75
75
|
* Absent on purpose:
|
|
76
|
-
* julia,
|
|
77
|
-
*
|
|
78
|
-
*
|
|
76
|
+
* julia, haskell - large grammars that ALSO ship no tag query, so each
|
|
77
|
+
* costs both its size (6.1/3.7 MB) and a hand-written query. Dropped to
|
|
78
|
+
* bound the payload; still indexed via the
|
|
79
79
|
* allowlist, still chunked heuristically.
|
|
80
80
|
* dart - its bundled .wasm (package v1.0.0, 2023) fails Language.load under
|
|
81
81
|
* web-tree-sitter 0.26.11 with a dylink-metadata error: the artifact
|
|
@@ -89,6 +89,20 @@ interface GrammarSpec {
|
|
|
89
89
|
* unit; an AST would not improve on them.
|
|
90
90
|
*/
|
|
91
91
|
const GRAMMARS: GrammarSpec[] = [
|
|
92
|
+
{
|
|
93
|
+
// Uy Ha 0.7.5, MIT; build the committed ABI-14 source without native dependencies.
|
|
94
|
+
id: 'cmake',
|
|
95
|
+
pkg: 'https://codeload.github.com/uyha/tree-sitter-cmake/tar.gz/58993af75218bc99a1f5a04c832a5937e7c422cb',
|
|
96
|
+
wasmFile: 'tree-sitter-cmake.wasm',
|
|
97
|
+
tags: 'ours',
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
// nix-community 0.3.0, MIT; use its committed generated ABI-15 parser unchanged.
|
|
101
|
+
id: 'nix',
|
|
102
|
+
pkg: 'https://codeload.github.com/nix-community/tree-sitter-nix/tar.gz/32c3ce98afdafc2ec9aedf0280a678750f76254c',
|
|
103
|
+
wasmFile: 'tree-sitter-nix.wasm',
|
|
104
|
+
tags: 'ours',
|
|
105
|
+
},
|
|
92
106
|
{
|
|
93
107
|
id: 'typescript',
|
|
94
108
|
pkg: 'tree-sitter-typescript@0.23.2',
|
|
@@ -106,7 +120,15 @@ const GRAMMARS: GrammarSpec[] = [
|
|
|
106
120
|
{ id: 'go', pkg: 'tree-sitter-go', tags: 'upstream' },
|
|
107
121
|
{ id: 'java', pkg: 'tree-sitter-java', tags: 'upstream' },
|
|
108
122
|
{ id: 'c', pkg: 'tree-sitter-c', tags: 'upstream' },
|
|
109
|
-
|
|
123
|
+
// MIT 0.23.4, gitHead f41e1a044c8a84ea9fa8577fdd2eab92ec96de02.
|
|
124
|
+
{ id: 'cpp', pkg: 'tree-sitter-cpp@0.23.4', tags: 'upstream' },
|
|
125
|
+
{
|
|
126
|
+
// MIT Objective-C++ 0.1.0; committed ABI-15 parser, not the pure Objective-C npm grammar.
|
|
127
|
+
id: 'objcpp',
|
|
128
|
+
pkg: 'https://tangled.org/dunkirk.sh/dots',
|
|
129
|
+
wasmFile: 'tree-sitter-objcpp.wasm',
|
|
130
|
+
tags: 'ours',
|
|
131
|
+
},
|
|
110
132
|
{
|
|
111
133
|
id: 'c-sharp',
|
|
112
134
|
pkg: 'tree-sitter-c-sharp',
|
|
@@ -119,7 +141,8 @@ const GRAMMARS: GrammarSpec[] = [
|
|
|
119
141
|
{ id: 'scala', pkg: 'tree-sitter-scala', tags: 'upstream' },
|
|
120
142
|
{ id: 'elixir', pkg: 'tree-sitter-elixir', tags: 'upstream' },
|
|
121
143
|
{ id: 'solidity', pkg: 'tree-sitter-solidity', tags: 'upstream' },
|
|
122
|
-
|
|
144
|
+
// MIT 0.25.1, gitHead 801326684a26ffc4e749bb016c50c6c30bdfa345.
|
|
145
|
+
{ id: 'bash', pkg: 'tree-sitter-bash@0.25.1', tags: 'ours' },
|
|
123
146
|
{
|
|
124
147
|
// Upstream MIT 0.4.1, gitHead 816840c592ab973500ae9750763c707b447e7fef; shipped ABI-15 WASM.
|
|
125
148
|
id: 'lua',
|
|
@@ -127,7 +150,15 @@ const GRAMMARS: GrammarSpec[] = [
|
|
|
127
150
|
wasmFile: 'tree-sitter-lua.wasm',
|
|
128
151
|
tags: 'upstream',
|
|
129
152
|
},
|
|
130
|
-
{
|
|
153
|
+
{
|
|
154
|
+
// Apache-2.0 v1.2.0, gitHead fad991865fee927dd1de5e172fb3f08ac674d914; packaged ABI-14 WASM.
|
|
155
|
+
id: 'terraform',
|
|
156
|
+
pkg: '@tree-sitter-grammars/tree-sitter-hcl@1.2.0',
|
|
157
|
+
wasmFile: 'tree-sitter-terraform.wasm',
|
|
158
|
+
tags: 'ours',
|
|
159
|
+
},
|
|
160
|
+
// MIT 0.1.2, gitHead 70efb0b9b50f95bcbd89dcfd42b275e0304e10cf.
|
|
161
|
+
{ id: 'groovy', pkg: 'tree-sitter-groovy@0.1.2', tags: 'ours' },
|
|
131
162
|
{ id: 'powershell', pkg: 'tree-sitter-powershell', tags: 'ours' },
|
|
132
163
|
{
|
|
133
164
|
id: 'swift',
|
|
@@ -269,7 +300,37 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
269
300
|
if (!grammar.includes(before)) throw new Error('TypeScript grammar patch no longer applies');
|
|
270
301
|
grammar = grammar.replace(before, after);
|
|
271
302
|
}
|
|
303
|
+
// Import types are primary types, so postfix [] applies without changing their expression aliases.
|
|
304
|
+
const importTypes = ` prec(-1, alias($._type_query_member_expression_in_type_annotation, $.member_expression)),
|
|
305
|
+
prec(-1, alias($._type_query_call_expression_in_type_annotation, $.call_expression)),
|
|
306
|
+
`;
|
|
307
|
+
const exportSpecifier = ` export_specifier: (_, previous) => seq(
|
|
308
|
+
optional(choice('type', 'typeof')),
|
|
309
|
+
previous,
|
|
310
|
+
),`;
|
|
311
|
+
if (
|
|
312
|
+
!grammar.includes(importTypes) ||
|
|
313
|
+
!grammar.includes(exportSpecifier) ||
|
|
314
|
+
!grammar.includes(' primary_type: $ => choice(')
|
|
315
|
+
)
|
|
316
|
+
throw new Error('TypeScript import-type/export patch no longer applies');
|
|
317
|
+
grammar = grammar
|
|
318
|
+
.replace(importTypes, '')
|
|
319
|
+
.replace(
|
|
320
|
+
' primary_type: $ => choice(',
|
|
321
|
+
' primary_type: $ => choice(\n' + importTypes.trimEnd()
|
|
322
|
+
);
|
|
323
|
+
grammar = grammar.replace(
|
|
324
|
+
exportSpecifier,
|
|
325
|
+
` export_specifier: $ => seq(
|
|
326
|
+
optional(choice('type', 'typeof')),
|
|
327
|
+
field('name', choice($._module_export_name, alias('type', $.identifier))),
|
|
328
|
+
optional(seq('as', field('alias', $._module_export_name))),
|
|
329
|
+
),`
|
|
330
|
+
);
|
|
272
331
|
writeFileSync(grammarPath, grammar);
|
|
332
|
+
// Retain our type/enum declaration captures when the vendor loop copies the query.
|
|
333
|
+
copyFileSync(join(WASM_DIR, 'typescript.tags.scm'), join(dir, 'queries', 'tags.scm'));
|
|
273
334
|
const tools = join(work, 'typescript-build');
|
|
274
335
|
execFileSync('npm', [
|
|
275
336
|
'install',
|
|
@@ -284,7 +345,7 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
284
345
|
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
285
346
|
for (const dialect of ['typescript', 'tsx']) {
|
|
286
347
|
if (only && only !== dialect) continue;
|
|
287
|
-
//
|
|
348
|
+
// Apply the JSX scanner and attribute repairs only to TSX.
|
|
288
349
|
if (dialect === 'tsx') {
|
|
289
350
|
patchJsxScanner(join(dir, 'common', 'scanner.h'));
|
|
290
351
|
patchJsxAttributes(join(tools, 'node_modules', 'tree-sitter-javascript', 'grammar.js'));
|
|
@@ -299,6 +360,7 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
299
360
|
['build', '--wasm', '--docker', '--output', join(dir, `tree-sitter-${dialect}.wasm`)],
|
|
300
361
|
options
|
|
301
362
|
);
|
|
363
|
+
chmodSync(join(dir, `tree-sitter-${dialect}.wasm`), 0o644);
|
|
302
364
|
}
|
|
303
365
|
}
|
|
304
366
|
|
|
@@ -413,6 +475,52 @@ ${continuation}`
|
|
|
413
475
|
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'swift.LICENSE'));
|
|
414
476
|
}
|
|
415
477
|
|
|
478
|
+
/** Build committed generated C without installing the dots repository or its grammar ancestors. */
|
|
479
|
+
function vendorObjcpp(work: string, repository: string): string {
|
|
480
|
+
const root = join(work, 'objcpp-source');
|
|
481
|
+
mkdirSync(root);
|
|
482
|
+
const git = (args: string[]): void => {
|
|
483
|
+
execFileSync('git', args, { cwd: root });
|
|
484
|
+
};
|
|
485
|
+
git(['init', '--quiet']);
|
|
486
|
+
git(['remote', 'add', 'origin', repository]);
|
|
487
|
+
git(['config', 'remote.origin.promisor', 'true']);
|
|
488
|
+
git(['config', 'remote.origin.partialclonefilter', 'blob:none']);
|
|
489
|
+
git(['sparse-checkout', 'set', '--no-cone', '/LICENSE.md', '/packages/tree-sitter-objcpp/']);
|
|
490
|
+
git([
|
|
491
|
+
'fetch',
|
|
492
|
+
'--quiet',
|
|
493
|
+
'--depth=1',
|
|
494
|
+
'--filter=blob:none',
|
|
495
|
+
'origin',
|
|
496
|
+
'8c861a98d84c6325a0300ec88dfa334aa6ab150e',
|
|
497
|
+
]);
|
|
498
|
+
git(['checkout', '--quiet', '--detach', 'FETCH_HEAD']);
|
|
499
|
+
const dir = join(root, 'packages', 'tree-sitter-objcpp');
|
|
500
|
+
const tools = join(work, 'objcpp-build');
|
|
501
|
+
execFileSync('npm', [
|
|
502
|
+
'install',
|
|
503
|
+
'--prefix',
|
|
504
|
+
tools,
|
|
505
|
+
'--no-audit',
|
|
506
|
+
'--no-fund',
|
|
507
|
+
'--no-package-lock',
|
|
508
|
+
'tree-sitter-cli@0.24.4',
|
|
509
|
+
]);
|
|
510
|
+
// Upstream generated this ABI-15 parser with CLI 0.25.10; 0.24.4 builds it with emsdk 3.1.64.
|
|
511
|
+
execFileSync(
|
|
512
|
+
join(tools, 'node_modules', '.bin', 'tree-sitter'),
|
|
513
|
+
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-objcpp.wasm')],
|
|
514
|
+
{ cwd: dir }
|
|
515
|
+
);
|
|
516
|
+
writeFileSync(
|
|
517
|
+
join(WASM_DIR, 'objcpp.LICENSE'),
|
|
518
|
+
readFileSync(join(root, 'LICENSE.md'), 'utf8').replace(/[\u201c\u201d]/g, '"') +
|
|
519
|
+
'\nInherited C/C++ parser and scanner portions: Copyright (c) 2014 Max Brunsfeld.\nThe MIT grant and conditions above apply to these portions too.\n'
|
|
520
|
+
);
|
|
521
|
+
return dir;
|
|
522
|
+
}
|
|
523
|
+
|
|
416
524
|
/** Upstream package.json pins CLI 0.24.7. SQL function bodies only, not general PL/pgSQL. */
|
|
417
525
|
function rebuildSql(dir: string, work: string): void {
|
|
418
526
|
const grammarPath = join(dir, 'grammar.js');
|
|
@@ -473,6 +581,26 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
473
581
|
|
|
474
582
|
drop_table: $ => seq(`
|
|
475
583
|
);
|
|
584
|
+
// Only the policy clauses and RLS action observed in the four fixed PostgreSQL migrations.
|
|
585
|
+
patch(' $.create_trigger,', ' $.create_trigger,\n $.create_policy,');
|
|
586
|
+
patch(
|
|
587
|
+
' _alter_specifications: $ => choice(',
|
|
588
|
+
` _alter_specifications: $ => choice(
|
|
589
|
+
seq(make_keyword("enable"), $.keyword_row, $.keyword_level, $.keyword_security),`
|
|
590
|
+
);
|
|
591
|
+
patch(
|
|
592
|
+
' create_table: $ => prec.left(',
|
|
593
|
+
` policy_relation: $ => $.object_reference,
|
|
594
|
+
create_policy: $ => seq(
|
|
595
|
+
$.keyword_create, make_keyword("policy"), field('name', $.identifier),
|
|
596
|
+
$.keyword_on, alias($.policy_relation, $.relation),
|
|
597
|
+
optional(seq($.keyword_for, choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete))),
|
|
598
|
+
optional(seq($.keyword_to, $.identifier)),
|
|
599
|
+
optional(seq($.keyword_using, wrapped_in_parenthesis($._expression))),
|
|
600
|
+
optional(seq($.keyword_with, $.keyword_check, wrapped_in_parenthesis($._expression))),
|
|
601
|
+
),
|
|
602
|
+
create_table: $ => prec.left(`
|
|
603
|
+
);
|
|
476
604
|
// Dollar-quoted procedural code is one literal, never a parsed SQL statement list.
|
|
477
605
|
patch(' $.reset_statement,', ' $.reset_statement,\n $.do_statement,');
|
|
478
606
|
patch(
|
|
@@ -481,7 +609,20 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
481
609
|
|
|
482
610
|
_cte: $ => seq(`
|
|
483
611
|
);
|
|
484
|
-
|
|
612
|
+
// Keep both parses until NOT NULL (constraint) or NOT LIKE (expression) is known.
|
|
613
|
+
// Match _expression's precedence so it cannot discard the completed default first.
|
|
614
|
+
patch(
|
|
615
|
+
' _inner_default_expression: $ => choice(',
|
|
616
|
+
' _inner_default_expression: $ => prec(1, choice('
|
|
617
|
+
);
|
|
618
|
+
patch(
|
|
619
|
+
'alias($.implicit_cast, $.cast),\n ),\n\n constraints:',
|
|
620
|
+
'alias($.implicit_cast, $.cast),\n )),\n\n constraints:'
|
|
621
|
+
);
|
|
622
|
+
patch(
|
|
623
|
+
' conflicts: $ => [',
|
|
624
|
+
' conflicts: $ => [\n [$._expression, $._inner_default_expression],\n [$.create_function],'
|
|
625
|
+
);
|
|
485
626
|
const functionStart = grammar.indexOf(' create_function: $ => seq(');
|
|
486
627
|
const functionEnd = grammar.indexOf(' _function_return:', functionStart);
|
|
487
628
|
if (functionStart < 0 || functionEnd < 0) throw new Error('SQL function patch no longer applies');
|
|
@@ -490,13 +631,12 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
490
631
|
const optionsStart = original.indexOf(' repeat(');
|
|
491
632
|
const optionsEnd = original.indexOf(' // ensure');
|
|
492
633
|
const options = original.slice(optionsStart, optionsEnd).replace(languageOption, '');
|
|
493
|
-
// A dedicated keyword selects the opaque branch; ordinary LANGUAGE SQL keeps its AST.
|
|
494
634
|
const procedural =
|
|
495
635
|
original.slice(0, optionsStart) +
|
|
496
636
|
options +
|
|
497
|
-
|
|
637
|
+
' alias($.plpgsql_function_language, $.function_language),\n' +
|
|
498
638
|
options +
|
|
499
|
-
|
|
639
|
+
' alias($.opaque_function_body, $.function_body),\n' +
|
|
500
640
|
options +
|
|
501
641
|
' )';
|
|
502
642
|
patch(
|
|
@@ -506,7 +646,94 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
506
646
|
original.slice(original.indexOf('seq('), -1) +
|
|
507
647
|
'),'
|
|
508
648
|
);
|
|
649
|
+
patch(
|
|
650
|
+
' $._dollar_quoted_string,\n ],',
|
|
651
|
+
' $._dollar_quoted_string,\n $._trailing_plpgsql_body,\n ],'
|
|
652
|
+
);
|
|
653
|
+
// Named rules retain complete body/language ranges; aliasing a sequence only names its first token.
|
|
654
|
+
patch(
|
|
655
|
+
' function_body: $ => choice(',
|
|
656
|
+
` opaque_function_body: $ => seq(
|
|
657
|
+
$.keyword_as,
|
|
658
|
+
alias(choice($._dollar_quoted_string, $._single_quote_string, $._double_quote_string), $.literal),
|
|
659
|
+
),
|
|
660
|
+
plpgsql_function_language: $ => seq(
|
|
661
|
+
$.keyword_language, alias(make_keyword("plpgsql"), $.identifier),
|
|
662
|
+
),
|
|
663
|
+
function_body: $ => choice(
|
|
664
|
+
seq(
|
|
665
|
+
$.keyword_as,
|
|
666
|
+
alias($._dollar_quoted_string_start_tag, $.dollar_quote),
|
|
667
|
+
alias($._trailing_plpgsql_body, $.literal),
|
|
668
|
+
alias($._dollar_quoted_string_end_tag, $.dollar_quote),
|
|
669
|
+
),`
|
|
670
|
+
);
|
|
671
|
+
const languageStart = grammar.indexOf(' function_language: $ => seq(');
|
|
672
|
+
const languageEnd = grammar.indexOf(' function_volatility:', languageStart);
|
|
673
|
+
if (languageStart < 0 || languageEnd < 0) throw new Error('SQL language patch no longer applies');
|
|
674
|
+
const language = grammar.slice(languageStart, languageEnd);
|
|
675
|
+
patch(
|
|
676
|
+
language,
|
|
677
|
+
language.replace(
|
|
678
|
+
' $.identifier',
|
|
679
|
+
` choice(
|
|
680
|
+
$.identifier,
|
|
681
|
+
alias(token(prec(1, seq("'", make_keyword("plpgsql"), "'"))), $.identifier),
|
|
682
|
+
)`
|
|
683
|
+
)
|
|
684
|
+
);
|
|
509
685
|
writeFileSync(grammarPath, grammar);
|
|
686
|
+
const scannerPath = join(dir, 'src', 'scanner.c');
|
|
687
|
+
let scanner = readFileSync(scannerPath, 'utf8');
|
|
688
|
+
const token = ' DOLLAR_QUOTED_STRING\n';
|
|
689
|
+
const start =
|
|
690
|
+
' if (valid_symbols[DOLLAR_QUOTED_STRING_START_TAG] && state->start_tag == NULL) {';
|
|
691
|
+
if (!scanner.includes(token) || !scanner.includes(start))
|
|
692
|
+
throw new Error('SQL procedural scanner patch no longer applies');
|
|
693
|
+
scanner = scanner.replace(token, ' DOLLAR_QUOTED_STRING,\n TRAILING_PLPGSQL_BODY\n');
|
|
694
|
+
scanner = scanner.replace(
|
|
695
|
+
start,
|
|
696
|
+
() =>
|
|
697
|
+
` if (valid_symbols[TRAILING_PLPGSQL_BODY] && state->start_tag != NULL) {
|
|
698
|
+
bool consumed = false;
|
|
699
|
+
for (;;) {
|
|
700
|
+
if (lexer->eof(lexer)) return false;
|
|
701
|
+
if (lexer->lookahead != '$') {
|
|
702
|
+
lexer->advance(lexer, false);
|
|
703
|
+
consumed = true;
|
|
704
|
+
continue;
|
|
705
|
+
}
|
|
706
|
+
lexer->mark_end(lexer);
|
|
707
|
+
char *tag = scan_dollar_string_tag(lexer);
|
|
708
|
+
bool closing = tag != NULL && strcmp(tag, state->start_tag) == 0;
|
|
709
|
+
free(tag);
|
|
710
|
+
if (closing) break;
|
|
711
|
+
consumed = true;
|
|
712
|
+
}
|
|
713
|
+
if (!consumed) return false;
|
|
714
|
+
// Look ahead without moving the marked body end; SQL bodies keep their normal AST.
|
|
715
|
+
while (iswspace(lexer->lookahead)) lexer->advance(lexer, false);
|
|
716
|
+
const char *keyword = "language";
|
|
717
|
+
for (unsigned i = 0; keyword[i]; i++) {
|
|
718
|
+
if (towlower(lexer->lookahead) != keyword[i]) return false;
|
|
719
|
+
lexer->advance(lexer, false);
|
|
720
|
+
}
|
|
721
|
+
while (iswspace(lexer->lookahead)) lexer->advance(lexer, false);
|
|
722
|
+
bool quoted = lexer->lookahead == 39;
|
|
723
|
+
if (quoted) lexer->advance(lexer, false);
|
|
724
|
+
const char *language = "plpgsql";
|
|
725
|
+
for (unsigned i = 0; language[i]; i++) {
|
|
726
|
+
if (towlower(lexer->lookahead) != language[i]) return false;
|
|
727
|
+
lexer->advance(lexer, false);
|
|
728
|
+
}
|
|
729
|
+
if (quoted ? lexer->lookahead != 39 : (iswalnum(lexer->lookahead) || lexer->lookahead == '_' || lexer->lookahead == '$')) return false;
|
|
730
|
+
lexer->result_symbol = TRAILING_PLPGSQL_BODY;
|
|
731
|
+
return true;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
` + start
|
|
735
|
+
);
|
|
736
|
+
writeFileSync(scannerPath, scanner);
|
|
510
737
|
const tools = join(work, 'sql-build');
|
|
511
738
|
execFileSync('npm', [
|
|
512
739
|
'install',
|
|
@@ -527,6 +754,188 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
527
754
|
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'sql.LICENSE'));
|
|
528
755
|
}
|
|
529
756
|
|
|
757
|
+
/** Permit existing dotted property expressions as command-call arguments. */
|
|
758
|
+
function rebuildGroovy(dir: string, work: string): void {
|
|
759
|
+
const path = join(dir, 'grammar.js');
|
|
760
|
+
let source = readFileSync(path, 'utf8');
|
|
761
|
+
const before =
|
|
762
|
+
' _juxt_argument_list: $ => commaSep1(choice($._literal, $.map_item, $.identifier)),';
|
|
763
|
+
if (!source.includes(before)) throw new Error('Groovy argument patch no longer applies');
|
|
764
|
+
source = source.replace(before, before.replace('$.identifier)', '$.identifier, $.field_access)'));
|
|
765
|
+
const conflicts = ' conflicts: ($, original) => original.concat([';
|
|
766
|
+
if (!source.includes(conflicts)) throw new Error('Groovy conflict patch no longer applies');
|
|
767
|
+
source = source.replace(
|
|
768
|
+
conflicts,
|
|
769
|
+
conflicts +
|
|
770
|
+
`
|
|
771
|
+
[$.method_invocation, $._juxt_argument_list],
|
|
772
|
+
[$.generic_type, $._juxt_argument_list],
|
|
773
|
+
[$.primary_expression, $._unannotated_type, $._juxt_argument_list],
|
|
774
|
+
[$._unannotated_type, $._juxt_argument_list],
|
|
775
|
+
[$.primary_expression, $._juxt_argument_list],`
|
|
776
|
+
);
|
|
777
|
+
writeFileSync(path, source);
|
|
778
|
+
const tools = join(work, 'groovy-build');
|
|
779
|
+
execFileSync('npm', [
|
|
780
|
+
'install',
|
|
781
|
+
'--prefix',
|
|
782
|
+
tools,
|
|
783
|
+
'--no-audit',
|
|
784
|
+
'--no-fund',
|
|
785
|
+
'--no-package-lock',
|
|
786
|
+
'tree-sitter-cli@0.24.4',
|
|
787
|
+
'tree-sitter-java@0.23.4',
|
|
788
|
+
]);
|
|
789
|
+
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
790
|
+
const options = { cwd: dir, env: { ...process.env, NODE_PATH: join(tools, 'node_modules') } };
|
|
791
|
+
execFileSync(cli, ['generate'], options);
|
|
792
|
+
execFileSync(
|
|
793
|
+
cli,
|
|
794
|
+
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-groovy.wasm')],
|
|
795
|
+
options
|
|
796
|
+
);
|
|
797
|
+
// Upstream publishes its MIT declaration in package.json/grammar.js, with no LICENSE file.
|
|
798
|
+
writeFileSync(
|
|
799
|
+
join(WASM_DIR, 'groovy.LICENSE'),
|
|
800
|
+
'tree-sitter-groovy 0.1.2, by Amaan Qureshi <amaanq12@gmail.com>.\n' +
|
|
801
|
+
'Upstream package.json and grammar.js declare MIT. Source: https://github.com/amaanq/tree-sitter-groovy/tree/70efb0b9b50f95bcbd89dcfd42b275e0304e10cf\n\n' +
|
|
802
|
+
'Inherited tree-sitter-java 0.23.4 (MIT):\n' +
|
|
803
|
+
readFileSync(join(tools, 'node_modules', 'tree-sitter-java', 'LICENSE'), 'utf8')
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/** Build the official committed Nix parser without installing its native Node binding. */
|
|
808
|
+
function rebuildNixOrCmake(dir: string, work: string, id: 'nix' | 'cmake'): void {
|
|
809
|
+
const tools = join(work, `${id}-build`);
|
|
810
|
+
execFileSync('npm', [
|
|
811
|
+
'install',
|
|
812
|
+
'--prefix',
|
|
813
|
+
tools,
|
|
814
|
+
'--no-audit',
|
|
815
|
+
'--no-fund',
|
|
816
|
+
'--no-package-lock',
|
|
817
|
+
'tree-sitter-cli@0.24.4',
|
|
818
|
+
]);
|
|
819
|
+
// Build the pinned generated source; CLI 0.24.4 pins emscripten/emsdk:3.1.64.
|
|
820
|
+
execFileSync(
|
|
821
|
+
join(tools, 'node_modules', '.bin', 'tree-sitter'),
|
|
822
|
+
['build', '--wasm', '--docker', '--output', join(dir, `tree-sitter-${id}.wasm`)],
|
|
823
|
+
{ cwd: dir }
|
|
824
|
+
);
|
|
825
|
+
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, `${id}.LICENSE`));
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/** The published grammar JSON freezes its C ancestor; add only the two JNI modifier spellings. */
|
|
829
|
+
function rebuildCpp(dir: string, work: string): void {
|
|
830
|
+
const path = join(dir, 'src', 'grammar.json');
|
|
831
|
+
const grammar = JSON.parse(readFileSync(path, 'utf8')) as {
|
|
832
|
+
rules: Record<string, { type: string; members: unknown[] }>;
|
|
833
|
+
};
|
|
834
|
+
for (const [name, value] of [
|
|
835
|
+
['type_qualifier', 'JNIEXPORT'],
|
|
836
|
+
['ms_call_modifier', 'JNICALL'],
|
|
837
|
+
] as const) {
|
|
838
|
+
const rule = grammar.rules[name];
|
|
839
|
+
if (!rule || rule.type !== 'CHOICE' || !Array.isArray(rule.members))
|
|
840
|
+
throw new Error(`C++ JNI patch no longer applies: ${name}`);
|
|
841
|
+
rule.members.push({ type: 'STRING', value });
|
|
842
|
+
}
|
|
843
|
+
writeFileSync(path, JSON.stringify(grammar));
|
|
844
|
+
const tools = join(work, 'cpp-build');
|
|
845
|
+
execFileSync('npm', [
|
|
846
|
+
'install',
|
|
847
|
+
'--prefix',
|
|
848
|
+
tools,
|
|
849
|
+
'--no-audit',
|
|
850
|
+
'--no-fund',
|
|
851
|
+
'--no-package-lock',
|
|
852
|
+
'tree-sitter-cli@0.24.4',
|
|
853
|
+
]);
|
|
854
|
+
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
855
|
+
execFileSync(cli, ['generate', 'src/grammar.json'], { cwd: dir });
|
|
856
|
+
execFileSync(
|
|
857
|
+
cli,
|
|
858
|
+
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-cpp.wasm')],
|
|
859
|
+
{ cwd: dir }
|
|
860
|
+
);
|
|
861
|
+
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'cpp.LICENSE'));
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/** A radix value may use $name as well as ${name}; keep the source and expansion node intact. */
|
|
865
|
+
function rebuildBash(dir: string, work: string): void {
|
|
866
|
+
const path = join(dir, 'grammar.js');
|
|
867
|
+
const grammar = readFileSync(path, 'utf8');
|
|
868
|
+
const before = 'seq(/-?(0x)?[0-9]+#/, choice($.expansion, $.command_substitution))';
|
|
869
|
+
if (!grammar.includes(before)) throw new Error('Bash radix patch no longer applies');
|
|
870
|
+
writeFileSync(
|
|
871
|
+
path,
|
|
872
|
+
grammar.replace(
|
|
873
|
+
before,
|
|
874
|
+
'seq(/-?(0x)?[0-9]+#/, choice($.simple_expansion, $.expansion, $.command_substitution))'
|
|
875
|
+
)
|
|
876
|
+
);
|
|
877
|
+
const scannerPath = join(dir, 'src', 'scanner.c');
|
|
878
|
+
const scanner = readFileSync(scannerPath, 'utf8');
|
|
879
|
+
const variableScan = ` return false;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
if (valid_symbols[BARE_DOLLAR] && !in_error_recovery(valid_symbols) && scan_bare_dollar(lexer)) {`;
|
|
883
|
+
if (!scanner.includes(variableScan))
|
|
884
|
+
throw new Error('Bash expansion-word patch no longer applies');
|
|
885
|
+
const parenStart = scanner.indexOf(
|
|
886
|
+
" if (lexer->lookahead == '(' && !(advanced_once || advance_once_space)) {"
|
|
887
|
+
);
|
|
888
|
+
const parenEnd = scanner.indexOf(
|
|
889
|
+
String.raw` if (lexer->lookahead == '\'') {`,
|
|
890
|
+
parenStart
|
|
891
|
+
);
|
|
892
|
+
const concatParens = "lexer->lookahead == ')' || lexer->lookahead == '('";
|
|
893
|
+
if (parenStart < 0 || parenEnd <= parenStart || !scanner.includes(concatParens))
|
|
894
|
+
throw new Error('Bash literal-parenthesis patch no longer applies');
|
|
895
|
+
// The variable-name scan consumes a default's prefix but rejects | before reaching expansion_word.
|
|
896
|
+
// Inside ${...}, parentheses are word pieces around expansions, not shell groups.
|
|
897
|
+
writeFileSync(
|
|
898
|
+
scannerPath,
|
|
899
|
+
(scanner.slice(0, parenStart) + scanner.slice(parenEnd))
|
|
900
|
+
.replace(
|
|
901
|
+
variableScan,
|
|
902
|
+
" if (valid_symbols[EXPANSION_WORD] && lexer->lookahead == '|') goto expansion_word;\n\n" +
|
|
903
|
+
variableScan
|
|
904
|
+
)
|
|
905
|
+
.replace(
|
|
906
|
+
concatParens,
|
|
907
|
+
"((lexer->lookahead == ')' || lexer->lookahead == '(') && !valid_symbols[CLOSING_BRACE])"
|
|
908
|
+
)
|
|
909
|
+
);
|
|
910
|
+
const generator = join(work, 'bash-generator');
|
|
911
|
+
execFileSync('npm', [
|
|
912
|
+
'install',
|
|
913
|
+
'--prefix',
|
|
914
|
+
generator,
|
|
915
|
+
'--no-audit',
|
|
916
|
+
'--no-fund',
|
|
917
|
+
'--no-package-lock',
|
|
918
|
+
'tree-sitter-cli@0.25.8',
|
|
919
|
+
]);
|
|
920
|
+
execFileSync(join(generator, 'node_modules', '.bin', 'tree-sitter'), ['generate'], { cwd: dir });
|
|
921
|
+
const tools = join(work, 'bash-build');
|
|
922
|
+
execFileSync('npm', [
|
|
923
|
+
'install',
|
|
924
|
+
'--prefix',
|
|
925
|
+
tools,
|
|
926
|
+
'--no-audit',
|
|
927
|
+
'--no-fund',
|
|
928
|
+
'--no-package-lock',
|
|
929
|
+
'tree-sitter-cli@0.24.4',
|
|
930
|
+
]);
|
|
931
|
+
// CLI 0.24.4 pins emscripten/emsdk:3.1.64 for --docker.
|
|
932
|
+
execFileSync(
|
|
933
|
+
join(tools, 'node_modules', '.bin', 'tree-sitter'),
|
|
934
|
+
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-bash.wasm')],
|
|
935
|
+
{ cwd: dir }
|
|
936
|
+
);
|
|
937
|
+
}
|
|
938
|
+
|
|
530
939
|
function vendor(): Problem[] {
|
|
531
940
|
const only = process.argv.find((arg) => arg.startsWith('--only='))?.slice(7);
|
|
532
941
|
if (only && !GRAMMARS.some((spec) => spec.id === only))
|
|
@@ -544,28 +953,36 @@ function vendor(): Problem[] {
|
|
|
544
953
|
let dir = extracted.get(spec.pkg);
|
|
545
954
|
if (!dir) {
|
|
546
955
|
try {
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
'
|
|
560
|
-
|
|
561
|
-
'
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
956
|
+
if (spec.id === 'objcpp') {
|
|
957
|
+
dir = vendorObjcpp(work, spec.pkg);
|
|
958
|
+
} else {
|
|
959
|
+
const out = execFileSync(
|
|
960
|
+
'npm',
|
|
961
|
+
['pack', spec.pkg, '--silent', '--pack-destination', work],
|
|
962
|
+
{
|
|
963
|
+
cwd: work,
|
|
964
|
+
encoding: 'utf8',
|
|
965
|
+
}
|
|
966
|
+
);
|
|
967
|
+
const tarball = out.trim().split('\n').pop() ?? '';
|
|
968
|
+
dir = join(work, spec.pkg.replace(/[^a-z0-9-]/gi, '_'));
|
|
969
|
+
mkdirSync(dir, { recursive: true });
|
|
970
|
+
execFileSync('tar', [
|
|
971
|
+
'xzf',
|
|
972
|
+
join(work, basename(tarball)),
|
|
973
|
+
'-C',
|
|
974
|
+
dir,
|
|
975
|
+
'--strip-components=1',
|
|
976
|
+
]);
|
|
977
|
+
if (spec.id === 'typescript' || spec.id === 'tsx') rebuildTypescript(dir, work, only);
|
|
978
|
+
if (spec.id === 'javascript') rebuildJavascript(dir, work);
|
|
979
|
+
if (spec.id === 'swift') rebuildSwift(dir, work);
|
|
980
|
+
if (spec.id === 'sql') rebuildSql(dir, work);
|
|
981
|
+
if (spec.id === 'groovy') rebuildGroovy(dir, work);
|
|
982
|
+
if (spec.id === 'cpp') rebuildCpp(dir, work);
|
|
983
|
+
if (spec.id === 'bash') rebuildBash(dir, work);
|
|
984
|
+
if (spec.id === 'nix' || spec.id === 'cmake') rebuildNixOrCmake(dir, work, spec.id);
|
|
985
|
+
}
|
|
569
986
|
extracted.set(spec.pkg, dir);
|
|
570
987
|
} catch (err) {
|
|
571
988
|
problems.push({
|
|
@@ -584,7 +1001,18 @@ function vendor(): Problem[] {
|
|
|
584
1001
|
} else {
|
|
585
1002
|
copyFileSync(wasmSrc, join(WASM_DIR, `${spec.id}.wasm`));
|
|
586
1003
|
if (spec.id === 'lua') copyFileSync(join(dir, 'LICENSE.md'), join(WASM_DIR, 'lua.LICENSE'));
|
|
587
|
-
if (spec.id === '
|
|
1004
|
+
if (spec.id === 'terraform')
|
|
1005
|
+
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'terraform.LICENSE'));
|
|
1006
|
+
if (
|
|
1007
|
+
spec.id === 'javascript' ||
|
|
1008
|
+
spec.id === 'tsx' ||
|
|
1009
|
+
spec.id === 'objcpp' ||
|
|
1010
|
+
spec.id === 'groovy' ||
|
|
1011
|
+
spec.id === 'cpp' ||
|
|
1012
|
+
spec.id === 'bash' ||
|
|
1013
|
+
spec.id === 'nix' ||
|
|
1014
|
+
spec.id === 'cmake'
|
|
1015
|
+
)
|
|
588
1016
|
chmodSync(join(WASM_DIR, `${spec.id}.wasm`), 0o644);
|
|
589
1017
|
}
|
|
590
1018
|
|
|
@@ -629,13 +1057,13 @@ if (problems.length > 0) {
|
|
|
629
1057
|
}
|
|
630
1058
|
|
|
631
1059
|
const sizes = GRAMMARS.map((g) => statSync(join(WASM_DIR, `${g.id}.wasm`)).size);
|
|
632
|
-
const
|
|
1060
|
+
const totalBytes = sizes.reduce((a, b) => a + b, 0);
|
|
1061
|
+
const totalMB = +(totalBytes / 1048576).toFixed(1);
|
|
633
1062
|
console.log(
|
|
634
1063
|
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, totalWasmMB: totalMB })}`
|
|
635
1064
|
);
|
|
636
|
-
//
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
console.error(`VENDOR_GRAMMARS_TOO_LARGE ${totalMB}MB exceeds the 40MB ceiling`);
|
|
1065
|
+
// Owner-approved Objective-C++ cost: repaired bundle 43.58 MiB (43.67 with Terraform 667475e93), bounded at 45 MiB.
|
|
1066
|
+
if (totalBytes > 45 * 1048576) {
|
|
1067
|
+
console.error(`VENDOR_GRAMMARS_TOO_LARGE ${totalMB}MB exceeds the 45MB ceiling`);
|
|
640
1068
|
process.exit(1);
|
|
641
1069
|
}
|
package/src/ast/astChunker.ts
CHANGED
|
@@ -57,7 +57,12 @@
|
|
|
57
57
|
|
|
58
58
|
import type { Node, Query, Tree } from 'web-tree-sitter';
|
|
59
59
|
import { Parser } from 'web-tree-sitter';
|
|
60
|
-
import {
|
|
60
|
+
import {
|
|
61
|
+
loadGrammar,
|
|
62
|
+
objcppSyntaxIssue,
|
|
63
|
+
type AstLanguageId,
|
|
64
|
+
type GrammarBinding,
|
|
65
|
+
} from './grammars.js';
|
|
61
66
|
|
|
62
67
|
export interface AstChunk {
|
|
63
68
|
/** Verbatim contiguous source: exactly the lines `startLine..endLine`. */
|
|
@@ -298,6 +303,10 @@ export async function chunkWithAst(
|
|
|
298
303
|
const parseMs = performance.now() - startedAt;
|
|
299
304
|
|
|
300
305
|
try {
|
|
306
|
+
if (languageId === 'objcpp') {
|
|
307
|
+
const issue = objcppSyntaxIssue(tree.rootNode);
|
|
308
|
+
if (issue) return { unsupported: 'parse_failed', detail: issue };
|
|
309
|
+
}
|
|
301
310
|
const lines = content.split('\n');
|
|
302
311
|
// A trailing newline TERMINATES the last line, it does not open a new one,
|
|
303
312
|
// but `split` yields a phantom '' for it. Dropping it here - before
|