@mnemonik/shared 7.144.2 → 7.145.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/grammars.d.ts +6 -6
- package/dist/ast/grammars.d.ts.map +1 -1
- package/dist/ast/grammars.js +51 -10
- package/dist/ast/grammars.js.map +1 -1
- package/dist/sourceRedaction.d.ts.map +1 -1
- package/dist/sourceRedaction.js +743 -64
- package/dist/sourceRedaction.js.map +1 -1
- package/package.json +2 -1
- package/queries/clojure.tags.scm +1 -0
- package/queries/dart.tags.scm +3 -0
- package/queries/erlang.tags.scm +2 -0
- package/queries/graphql.tags.scm +3 -0
- package/queries/haskell.tags.scm +3 -0
- package/queries/julia.tags.scm +1 -0
- package/queries/kotlin.tags.scm +3 -0
- package/queries/ocaml.tags.scm +2 -0
- package/queries/ocaml_interface.tags.scm +1 -0
- package/queries/perl.tags.scm +2 -0
- package/queries/protobuf.tags.scm +5 -0
- package/queries/r.tags.scm +2 -0
- package/queries/zig.tags.scm +2 -0
- package/scripts/vendor-grammars.ts +586 -35
- package/src/ast/grammars.ts +51 -10
- package/src/sourceRedaction.ts +765 -12
- package/wasm/bash.wasm.gz +0 -0
- package/wasm/c-sharp.wasm.gz +0 -0
- package/wasm/c.wasm.gz +0 -0
- package/wasm/clojure.LICENSE +21 -0
- package/wasm/clojure.tags.scm +1 -0
- package/wasm/clojure.wasm.gz +0 -0
- package/wasm/cmake.wasm.gz +0 -0
- package/wasm/cpp.wasm.gz +0 -0
- package/wasm/dart.LICENSE +20 -0
- package/wasm/dart.tags.scm +3 -0
- package/wasm/dart.wasm.gz +0 -0
- package/wasm/elixir.wasm.gz +0 -0
- package/wasm/erlang.LICENSE +201 -0
- package/wasm/erlang.tags.scm +2 -0
- package/wasm/erlang.wasm.gz +0 -0
- package/wasm/go.wasm.gz +0 -0
- package/wasm/graphql.LICENSE +21 -0
- package/wasm/graphql.tags.scm +3 -0
- package/wasm/graphql.wasm.gz +0 -0
- package/wasm/groovy.wasm.gz +0 -0
- package/wasm/haskell.LICENSE +21 -0
- package/wasm/haskell.tags.scm +3 -0
- package/wasm/haskell.wasm.gz +0 -0
- package/wasm/java.wasm.gz +0 -0
- package/wasm/javascript.wasm.gz +0 -0
- package/wasm/julia.LICENSE +21 -0
- package/wasm/julia.tags.scm +1 -0
- package/wasm/julia.wasm.gz +0 -0
- package/wasm/kotlin.LICENSE +9 -0
- package/wasm/kotlin.tags.scm +3 -0
- package/wasm/kotlin.wasm.gz +0 -0
- package/wasm/lua.wasm.gz +0 -0
- package/wasm/nix.wasm.gz +0 -0
- package/wasm/objcpp.wasm.gz +0 -0
- package/wasm/ocaml.LICENSE +21 -0
- package/wasm/ocaml.tags.scm +2 -0
- package/wasm/ocaml.wasm.gz +0 -0
- package/wasm/ocaml_interface.LICENSE +21 -0
- package/wasm/ocaml_interface.tags.scm +1 -0
- package/wasm/ocaml_interface.wasm.gz +0 -0
- package/wasm/perl.LICENSE +7 -0
- package/wasm/perl.tags.scm +2 -0
- package/wasm/perl.wasm.gz +0 -0
- package/wasm/php.wasm.gz +0 -0
- package/wasm/powershell.wasm.gz +0 -0
- package/wasm/protobuf.LICENSE +21 -0
- package/wasm/protobuf.tags.scm +5 -0
- package/wasm/protobuf.wasm.gz +0 -0
- package/wasm/python.wasm.gz +0 -0
- package/wasm/r.LICENSE +9 -0
- package/wasm/r.tags.scm +2 -0
- package/wasm/r.wasm.gz +0 -0
- package/wasm/ruby.wasm.gz +0 -0
- package/wasm/rust.wasm.gz +0 -0
- package/wasm/scala.wasm.gz +0 -0
- package/wasm/solidity.wasm.gz +0 -0
- package/wasm/sql.wasm.gz +0 -0
- package/wasm/swift.wasm.gz +0 -0
- package/wasm/terraform.wasm.gz +0 -0
- package/wasm/tsx.wasm.gz +0 -0
- package/wasm/typescript.wasm.gz +0 -0
- package/wasm/zig.LICENSE +29 -0
- package/wasm/zig.tags.scm +2 -0
- package/wasm/zig.wasm.gz +0 -0
- package/wasm/bash.wasm +0 -0
- package/wasm/c-sharp.wasm +0 -0
- package/wasm/c.wasm +0 -0
- package/wasm/cmake.wasm +0 -0
- package/wasm/cpp.wasm +0 -0
- package/wasm/elixir.wasm +0 -0
- package/wasm/go.wasm +0 -0
- package/wasm/groovy.wasm +0 -0
- package/wasm/java.wasm +0 -0
- package/wasm/javascript.wasm +0 -0
- package/wasm/lua.wasm +0 -0
- package/wasm/nix.wasm +0 -0
- package/wasm/objcpp.wasm +0 -0
- package/wasm/php.wasm +0 -0
- package/wasm/powershell.wasm +0 -0
- package/wasm/python.wasm +0 -0
- package/wasm/ruby.wasm +0 -0
- package/wasm/rust.wasm +0 -0
- package/wasm/scala.wasm +0 -0
- package/wasm/solidity.wasm +0 -0
- package/wasm/sql.wasm +0 -0
- package/wasm/swift.wasm +0 -0
- package/wasm/terraform.wasm +0 -0
- package/wasm/tsx.wasm +0 -0
- package/wasm/typescript.wasm +0 -0
|
@@ -11,13 +11,13 @@
|
|
|
11
11
|
* so there is no peer graph to satisfy, `npm ci` stays fast for every developer
|
|
12
12
|
* and every CI run, and nobody downloads ~283 MB of grammars to build the repo.
|
|
13
13
|
*
|
|
14
|
-
* What ships to a user:
|
|
14
|
+
* What ships to a user: deterministic `.wasm.gz` and `.tags.scm` files, committed
|
|
15
15
|
* here and published inside @mnemonik/shared. A user's install therefore pulls
|
|
16
16
|
* no grammar package, runs no postinstall, needs no compiler, and fetches
|
|
17
17
|
* nothing at runtime - which is the whole reason this plan chose WebAssembly
|
|
18
18
|
* over the native bindings.
|
|
19
19
|
*
|
|
20
|
-
* Run: npx tsx packages/shared/scripts/vendor-grammars.ts [--check | --only=<id>]
|
|
20
|
+
* Run: npx tsx packages/shared/scripts/vendor-grammars.ts [--check | --only=<id>[,<id>...]]
|
|
21
21
|
* JSX repair: run --only=javascript and --only=tsx; other assets stay untouched.
|
|
22
22
|
* --check verify every manifest entry is present and non-empty; write nothing.
|
|
23
23
|
* This is what CI should run to catch a grammar that silently stopped
|
|
@@ -40,6 +40,7 @@ import {
|
|
|
40
40
|
import { tmpdir } from 'node:os';
|
|
41
41
|
import { basename, join } from 'node:path';
|
|
42
42
|
import { fileURLToPath } from 'node:url';
|
|
43
|
+
import { gzipSync, gunzipSync } from 'node:zlib';
|
|
43
44
|
import { Language, Parser, Query } from 'web-tree-sitter';
|
|
44
45
|
import { AST_LANGUAGE_IDS, QUERY_CHAIN, grammarArtifactBasename } from '../src/ast/grammars.js';
|
|
45
46
|
|
|
@@ -64,6 +65,10 @@ interface GrammarSpec {
|
|
|
64
65
|
* maintain when the upstream query is absent or captures unsuitable ranges.
|
|
65
66
|
*/
|
|
66
67
|
tags: 'upstream' | 'ours' | 'inherited';
|
|
68
|
+
/** Compile committed source, regenerating only obsolete parser ABIs. */
|
|
69
|
+
build?: 'source' | 'regenerate';
|
|
70
|
+
/** Copy the source license alongside new grammar artifacts. */
|
|
71
|
+
licenseFile?: string;
|
|
67
72
|
}
|
|
68
73
|
|
|
69
74
|
/**
|
|
@@ -72,23 +77,103 @@ interface GrammarSpec {
|
|
|
72
77
|
* and losing a language is exactly the silent degradation this plan exists to
|
|
73
78
|
* remove.
|
|
74
79
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
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
|
-
* allowlist, still chunked heuristically.
|
|
80
|
-
* dart - its bundled .wasm (package v1.0.0, 2023) fails Language.load under
|
|
81
|
-
* web-tree-sitter 0.26.11 with a dylink-metadata error: the artifact
|
|
82
|
-
* predates the current wasm ABI. Presence is not loadability, which is why
|
|
83
|
-
* --check verifies both. Flutter matters, so this is worth revisiting by
|
|
84
|
-
* compiling from source with tree-sitter-cli.
|
|
85
|
-
* kotlin, perl, zig - bundle no .wasm, so they need a build step
|
|
86
|
-
* with tree-sitter-cli. Deferred until the grammars above are proven; they
|
|
87
|
-
* keep the heuristic chunker meanwhile.
|
|
88
|
-
* markdown - keeps chunkMarkdown. Headers already are a document's semantic
|
|
89
|
-
* unit; an AST would not improve on them.
|
|
80
|
+
* Markdown retains its document-header chunker. Svelte component parsing is
|
|
81
|
+
* owned by its adapter; it does not need another tree-sitter WASM.
|
|
90
82
|
*/
|
|
91
83
|
const GRAMMARS: GrammarSpec[] = [
|
|
84
|
+
// fwcd MIT 0.3.8, e1a2d5ad1f61f5740677183cd4125bb071cd2f30, ABI 14.
|
|
85
|
+
{
|
|
86
|
+
id: 'kotlin',
|
|
87
|
+
pkg: 'tree-sitter-kotlin@0.3.8',
|
|
88
|
+
tags: 'ours',
|
|
89
|
+
build: 'source',
|
|
90
|
+
licenseFile: 'LICENSE',
|
|
91
|
+
},
|
|
92
|
+
// UserNobody14 ISC 1.0.0, 53485a8f301254e19c518aa20c80f1bcf7cf5c62.
|
|
93
|
+
// Rebuild ABI-14 source: its published WASM has obsolete dynamic-link metadata.
|
|
94
|
+
{
|
|
95
|
+
id: 'dart',
|
|
96
|
+
pkg: 'tree-sitter-dart@1.0.0',
|
|
97
|
+
tags: 'ours',
|
|
98
|
+
build: 'source',
|
|
99
|
+
licenseFile: 'LICENSE',
|
|
100
|
+
},
|
|
101
|
+
// WhatsApp Apache-2.0, committed ABI 15. The unscoped npm name is a security holder.
|
|
102
|
+
{
|
|
103
|
+
id: 'erlang',
|
|
104
|
+
pkg: 'https://codeload.github.com/WhatsApp/tree-sitter-erlang/tar.gz/62c82e67b73e13f3ef06e4c8c07ff035a8235d30',
|
|
105
|
+
tags: 'ours',
|
|
106
|
+
build: 'source',
|
|
107
|
+
licenseFile: 'LICENSE',
|
|
108
|
+
},
|
|
109
|
+
// MIT 0.23.1, c30d812bc90827f1a54106a25bc9a6307f5cdcec, packaged ABI 14.
|
|
110
|
+
{ id: 'haskell', pkg: 'tree-sitter-haskell@0.23.1', tags: 'ours', licenseFile: 'LICENSE' },
|
|
111
|
+
// MIT 0.24.2, 0cc270ff90ca09c29d0f2f9dec69ddfef55a3eff, packaged ABI 14.
|
|
112
|
+
{
|
|
113
|
+
id: 'ocaml',
|
|
114
|
+
pkg: 'tree-sitter-ocaml@0.24.2',
|
|
115
|
+
wasmFile: 'tree-sitter-ocaml.wasm',
|
|
116
|
+
tags: 'ours',
|
|
117
|
+
licenseFile: 'LICENSE',
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'ocaml_interface',
|
|
121
|
+
pkg: 'tree-sitter-ocaml@0.24.2',
|
|
122
|
+
wasmFile: 'tree-sitter-ocaml_interface.wasm',
|
|
123
|
+
tags: 'ours',
|
|
124
|
+
licenseFile: 'LICENSE',
|
|
125
|
+
},
|
|
126
|
+
// oakmac MIT 0.4.0, 290a67a3368be3847b1dd15327bd3a63f2f671ad; regenerate ABI 9.
|
|
127
|
+
{
|
|
128
|
+
id: 'clojure',
|
|
129
|
+
pkg: 'tree-sitter-clojure@0.4.0',
|
|
130
|
+
tags: 'ours',
|
|
131
|
+
build: 'regenerate',
|
|
132
|
+
licenseFile: 'LICENSE.md',
|
|
133
|
+
},
|
|
134
|
+
// MIT 0.23.1, a8e1262997d5a45520a06cbe1b86c0737d507054, packaged ABI 14.
|
|
135
|
+
{ id: 'julia', pkg: 'tree-sitter-julia@0.23.1', tags: 'ours', licenseFile: 'LICENSE' },
|
|
136
|
+
// MIT 2.0.0, 50904961d6a87c5191e611276aa2ecb9d66ca4ff, committed ABI 15.
|
|
137
|
+
{
|
|
138
|
+
id: 'perl',
|
|
139
|
+
pkg: 'tree-sitter-perl@2.0.0',
|
|
140
|
+
tags: 'ours',
|
|
141
|
+
build: 'source',
|
|
142
|
+
licenseFile: 'LICENSE',
|
|
143
|
+
},
|
|
144
|
+
// r-lib MIT 1.3.0, committed ABI 14. The unscoped npm name is a security holder.
|
|
145
|
+
{
|
|
146
|
+
id: 'r',
|
|
147
|
+
pkg: 'https://codeload.github.com/r-lib/tree-sitter-r/tar.gz/58a22794466c0fc15b0d3b40531db751593721e8',
|
|
148
|
+
tags: 'ours',
|
|
149
|
+
build: 'source',
|
|
150
|
+
licenseFile: 'LICENSE',
|
|
151
|
+
},
|
|
152
|
+
// GrayJack BSD-3-Clause 0.2.0, fb8e54448f19f5d78d7cdc664b35bffa8ec48876; regenerate ABI 10.
|
|
153
|
+
{
|
|
154
|
+
id: 'zig',
|
|
155
|
+
pkg: 'tree-sitter-zig@0.2.0',
|
|
156
|
+
tags: 'ours',
|
|
157
|
+
build: 'regenerate',
|
|
158
|
+
licenseFile: 'LICENSE',
|
|
159
|
+
},
|
|
160
|
+
// treywood MIT 0.1.0, committed ABI 14; verified upstream source and license.
|
|
161
|
+
{
|
|
162
|
+
id: 'protobuf',
|
|
163
|
+
pkg: 'https://codeload.github.com/treywood/tree-sitter-proto/tar.gz/e9f6b43f6844bd2189b50a422d4e2094313f6aa3',
|
|
164
|
+
wasmFile: 'tree-sitter-proto.wasm',
|
|
165
|
+
tags: 'ours',
|
|
166
|
+
build: 'source',
|
|
167
|
+
licenseFile: 'LICENSE',
|
|
168
|
+
},
|
|
169
|
+
// bkegley MIT 0.0.1, committed ABI 13; avoid the unrelated ISC npm package.
|
|
170
|
+
{
|
|
171
|
+
id: 'graphql',
|
|
172
|
+
pkg: 'https://codeload.github.com/bkegley/tree-sitter-graphql/tar.gz/5e66e961eee421786bdda8495ed1db045e06b5fe',
|
|
173
|
+
tags: 'ours',
|
|
174
|
+
build: 'regenerate',
|
|
175
|
+
licenseFile: 'LICENSE',
|
|
176
|
+
},
|
|
92
177
|
{
|
|
93
178
|
// Uy Ha 0.7.5, MIT; build the committed ABI-14 source without native dependencies.
|
|
94
179
|
id: 'cmake',
|
|
@@ -123,7 +208,7 @@ const GRAMMARS: GrammarSpec[] = [
|
|
|
123
208
|
// MIT 0.23.4, gitHead f41e1a044c8a84ea9fa8577fdd2eab92ec96de02.
|
|
124
209
|
{ id: 'cpp', pkg: 'tree-sitter-cpp@0.23.4', tags: 'upstream' },
|
|
125
210
|
{
|
|
126
|
-
// MIT Objective-C++ 0.1.0;
|
|
211
|
+
// MIT Objective-C++ 0.1.0; pinned source, not the pure Objective-C npm grammar.
|
|
127
212
|
id: 'objcpp',
|
|
128
213
|
pkg: 'https://tangled.org/dunkirk.sh/dots',
|
|
129
214
|
wasmFile: 'tree-sitter-objcpp.wasm',
|
|
@@ -215,7 +300,7 @@ async function checkOnly(): Promise<Problem[]> {
|
|
|
215
300
|
await Parser.init();
|
|
216
301
|
|
|
217
302
|
for (const spec of GRAMMARS) {
|
|
218
|
-
const wasm = join(WASM_DIR, `${spec.id}.wasm`);
|
|
303
|
+
const wasm = join(WASM_DIR, `${spec.id}.wasm.gz`);
|
|
219
304
|
if (!existsSync(wasm) || statSync(wasm).size === 0) {
|
|
220
305
|
problems.push({ id: spec.id, detail: `missing or empty ${spec.id}.wasm` });
|
|
221
306
|
continue;
|
|
@@ -223,7 +308,7 @@ async function checkOnly(): Promise<Problem[]> {
|
|
|
223
308
|
|
|
224
309
|
let language: Language;
|
|
225
310
|
try {
|
|
226
|
-
language = await Language.load(wasm);
|
|
311
|
+
language = await Language.load(gunzipSync(readFileSync(wasm)));
|
|
227
312
|
} catch (err) {
|
|
228
313
|
problems.push({
|
|
229
314
|
id: spec.id,
|
|
@@ -277,9 +362,9 @@ async function checkOnly(): Promise<Problem[]> {
|
|
|
277
362
|
}
|
|
278
363
|
|
|
279
364
|
/**
|
|
280
|
-
*
|
|
281
|
-
* Keep
|
|
282
|
-
*
|
|
365
|
+
* Repair demonstrated syntax omissions in pinned 0.23.2 without changing source positions.
|
|
366
|
+
* Keep contextual names and type-only forms distinct from runtime calls; retain
|
|
367
|
+
* expression ambiguity through explicit GLR conflicts instead of guessing.
|
|
283
368
|
* Source: https://github.com/tree-sitter/tree-sitter-typescript/tree/v0.23.2
|
|
284
369
|
* MIT; CLI 0.24.4 uses emscripten/emsdk:3.1.64 for the WASM build.
|
|
285
370
|
*/
|
|
@@ -289,12 +374,40 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
289
374
|
for (const [before, after] of [
|
|
290
375
|
[
|
|
291
376
|
' _reserved_identifier: (_, previous) => choice(',
|
|
292
|
-
" _reserved_identifier: (_, previous) => choice(\n 'unique',",
|
|
377
|
+
" _reserved_identifier: (_, previous) => choice(\n 'unique',\n 'as',",
|
|
293
378
|
],
|
|
294
379
|
[' [$.call_expression, $._type_query_call_expression],\n', ''],
|
|
295
380
|
[
|
|
296
381
|
' conflicts: ($, previous) => previous.concat([',
|
|
297
|
-
' conflicts: ($, previous) => previous.concat([\n [$.call_expression, $._type_query_call_expression],',
|
|
382
|
+
' conflicts: ($, previous) => previous.concat([\n [$.call_expression, $._type_query_call_expression],\n [$.primary_expression, $.arrow_function, $.method_definition],',
|
|
383
|
+
],
|
|
384
|
+
[
|
|
385
|
+
" field('type_arguments', optional($.type_arguments)),\n field('arguments', $.arguments),",
|
|
386
|
+
" field('type_arguments', optional($.type_arguments)),\n field('arguments', choice($.arguments, alias($._tagged_template_string, $.template_string))),",
|
|
387
|
+
],
|
|
388
|
+
[
|
|
389
|
+
" type_parameter: $ => seq(\n optional('const'),\n field('name', $._type_identifier),",
|
|
390
|
+
" type_parameter: $ => seq(\n optional(choice('const', 'in', 'out', seq('in', 'out'))),\n field('name', choice($._type_identifier, alias('out', $.type_identifier))),",
|
|
391
|
+
],
|
|
392
|
+
[
|
|
393
|
+
' $.export_clause,\n optional($._from_clause),',
|
|
394
|
+
" choice(\n seq($.export_clause, optional($._from_clause)),\n seq(choice('*', $.namespace_export), $._from_clause),\n ),",
|
|
395
|
+
],
|
|
396
|
+
[
|
|
397
|
+
" choice(',', $._semicolon),\n choice(",
|
|
398
|
+
" choice(',', $._semicolon, $._function_signature_automatic_semicolon),\n choice(",
|
|
399
|
+
],
|
|
400
|
+
[
|
|
401
|
+
" mapped_type_clause: $ => seq(\n field('name', $._type_identifier),",
|
|
402
|
+
" mapped_type_clause: $ => seq(\n field('name', choice($._type_identifier, alias('type', $.type_identifier))),",
|
|
403
|
+
],
|
|
404
|
+
[
|
|
405
|
+
' alias($._template_chars, $.string_fragment),\n $.template_type,',
|
|
406
|
+
' alias($._template_chars, $.string_fragment),\n $.escape_sequence,\n $.template_type,',
|
|
407
|
+
],
|
|
408
|
+
[
|
|
409
|
+
" field('name', choice($.identifier, $._destructuring_pattern)),",
|
|
410
|
+
" field('name', choice($.identifier, alias('as', $.identifier), $._destructuring_pattern)),",
|
|
298
411
|
],
|
|
299
412
|
] as const) {
|
|
300
413
|
if (!grammar.includes(before)) throw new Error('TypeScript grammar patch no longer applies');
|
|
@@ -328,7 +441,36 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
328
441
|
optional(seq('as', field('alias', $._module_export_name))),
|
|
329
442
|
),`
|
|
330
443
|
);
|
|
444
|
+
grammar = grammar.replaceAll(
|
|
445
|
+
"field('arguments', $.template_string)",
|
|
446
|
+
"field('arguments', alias($._tagged_template_string, $.template_string))"
|
|
447
|
+
);
|
|
331
448
|
writeFileSync(grammarPath, grammar);
|
|
449
|
+
const scannerPath = join(dir, 'common', 'scanner.h');
|
|
450
|
+
let scanner = readFileSync(scannerPath, 'utf8');
|
|
451
|
+
const before = " case '<':\n";
|
|
452
|
+
if (!scanner.includes(before))
|
|
453
|
+
throw new Error('TypeScript generic-overload ASI patch no longer applies');
|
|
454
|
+
scanner = scanner
|
|
455
|
+
.replace(before, '')
|
|
456
|
+
.replace(
|
|
457
|
+
" case '{':",
|
|
458
|
+
" case '<':\n // Only type-member/signature boundaries may precede a new generic overload.\n return valid_symbols[FUNCTION_SIGNATURE_AUTOMATIC_SEMICOLON] && !valid_symbols[LOGICAL_OR];\n\n case '{':"
|
|
459
|
+
);
|
|
460
|
+
const inBoundary =
|
|
461
|
+
' if (!iswalpha(lexer->lookahead)) {\n return false;\n }';
|
|
462
|
+
if (!scanner.includes(inBoundary))
|
|
463
|
+
throw new Error('TypeScript in-property ASI patch no longer applies');
|
|
464
|
+
scanner = scanner.replace(
|
|
465
|
+
inBoundary,
|
|
466
|
+
' if (!iswalpha(lexer->lookahead)) {\n return !valid_symbols[LOGICAL_OR];\n }'
|
|
467
|
+
);
|
|
468
|
+
const optionalTuple =
|
|
469
|
+
"lexer->lookahead == ':' || lexer->lookahead == ')' || lexer->lookahead == ','";
|
|
470
|
+
if (!scanner.includes(optionalTuple))
|
|
471
|
+
throw new Error('TypeScript optional-tuple patch no longer applies');
|
|
472
|
+
scanner = scanner.replace(optionalTuple, optionalTuple + " || lexer->lookahead == ']'");
|
|
473
|
+
writeFileSync(scannerPath, scanner);
|
|
332
474
|
// Retain our type/enum declaration captures when the vendor loop copies the query.
|
|
333
475
|
copyFileSync(join(WASM_DIR, 'typescript.tags.scm'), join(dir, 'queries', 'tags.scm'));
|
|
334
476
|
const tools = join(work, 'typescript-build');
|
|
@@ -343,8 +485,10 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
343
485
|
'tree-sitter-javascript@0.23.1',
|
|
344
486
|
]);
|
|
345
487
|
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
488
|
+
// CLI 0.24 mis-emits the complementary character class; spell out raw characters.
|
|
489
|
+
patchTaggedTemplates(join(tools, 'node_modules', 'tree-sitter-javascript', 'grammar.js'), false);
|
|
346
490
|
for (const dialect of ['typescript', 'tsx']) {
|
|
347
|
-
if (only && only
|
|
491
|
+
if (only && !only.split(',').includes(dialect)) continue;
|
|
348
492
|
// Apply the JSX scanner and attribute repairs only to TSX.
|
|
349
493
|
if (dialect === 'tsx') {
|
|
350
494
|
patchJsxScanner(join(dir, 'common', 'scanner.h'));
|
|
@@ -364,6 +508,34 @@ function rebuildTypescript(dir: string, work: string, only?: string): void {
|
|
|
364
508
|
}
|
|
365
509
|
}
|
|
366
510
|
|
|
511
|
+
/** Tagged templates retain invalid escape spellings as raw text; ordinary literals stay strict. */
|
|
512
|
+
function patchTaggedTemplates(grammarPath: string, complementaryClass = true): void {
|
|
513
|
+
let grammar = readFileSync(grammarPath, 'utf8');
|
|
514
|
+
const argument = "field('arguments', $.template_string)";
|
|
515
|
+
const template = ' template_string: $ => seq(';
|
|
516
|
+
if (!grammar.includes(argument) || !grammar.includes(template))
|
|
517
|
+
throw new Error('Tagged-template escape patch no longer applies');
|
|
518
|
+
const tagged = [
|
|
519
|
+
' _tagged_template_string: $ => seq(',
|
|
520
|
+
" '`',",
|
|
521
|
+
' repeat(choice(',
|
|
522
|
+
' alias($._template_chars, $.string_fragment),',
|
|
523
|
+
' $.escape_sequence,',
|
|
524
|
+
complementaryClass
|
|
525
|
+
? " alias(token.immediate(prec(1, seq('\\\\', /[\\s\\S]/))), $.escape_sequence),"
|
|
526
|
+
: " alias(token.immediate(prec(1, seq('\\\\', choice(/./, /[\\r\\n\\u2028\\u2029]/)))), $.escape_sequence),",
|
|
527
|
+
' $.template_substitution,',
|
|
528
|
+
' )),',
|
|
529
|
+
" '`',",
|
|
530
|
+
' ),',
|
|
531
|
+
'',
|
|
532
|
+
].join('\n');
|
|
533
|
+
grammar = grammar
|
|
534
|
+
.replaceAll(argument, "field('arguments', alias($._tagged_template_string, $.template_string))")
|
|
535
|
+
.replace(template, tagged + template);
|
|
536
|
+
writeFileSync(grammarPath, grammar);
|
|
537
|
+
}
|
|
538
|
+
|
|
367
539
|
/** Upstream f8637eb: preserve entity boundaries while accepting bare JSX ampersands. */
|
|
368
540
|
function patchJsxScanner(scannerPath: string): void {
|
|
369
541
|
execFileSync('patch', ['--batch', scannerPath], {
|
|
@@ -394,6 +566,7 @@ function patchJsxAttributes(grammarPath: string): void {
|
|
|
394
566
|
|
|
395
567
|
/** 0.25.0's reserved-word DSL needs generator 0.25.8; keep the existing WASM build tool. */
|
|
396
568
|
function rebuildJavascript(dir: string, work: string): void {
|
|
569
|
+
patchTaggedTemplates(join(dir, 'grammar.js'));
|
|
397
570
|
patchJsxScanner(join(dir, 'src', 'scanner.c'));
|
|
398
571
|
patchJsxAttributes(join(dir, 'grammar.js'));
|
|
399
572
|
const generator = join(work, 'javascript-generator');
|
|
@@ -513,6 +686,18 @@ function vendorObjcpp(work: string, repository: string): string {
|
|
|
513
686
|
]);
|
|
514
687
|
git(['checkout', '--quiet', '--detach', 'FETCH_HEAD']);
|
|
515
688
|
const dir = join(root, 'packages', 'tree-sitter-objcpp');
|
|
689
|
+
const grammarPath = join(dir, 'grammar.js');
|
|
690
|
+
let grammar = readFileSync(grammarPath, 'utf8');
|
|
691
|
+
const before = ' _objc_implementation_item: $ => choice(\n';
|
|
692
|
+
if (!grammar.includes(before))
|
|
693
|
+
throw new Error('Objective-C++ macro-body patch no longer applies');
|
|
694
|
+
grammar = grammar.replace(
|
|
695
|
+
before,
|
|
696
|
+
" objc_macro_body: $ => seq($.objc_macro_invocation, field('body', $.compound_statement)),\n\n" +
|
|
697
|
+
before +
|
|
698
|
+
' $.objc_macro_body,\n'
|
|
699
|
+
);
|
|
700
|
+
writeFileSync(grammarPath, grammar);
|
|
516
701
|
const tools = join(work, 'objcpp-build');
|
|
517
702
|
execFileSync('npm', [
|
|
518
703
|
'install',
|
|
@@ -522,10 +707,17 @@ function vendorObjcpp(work: string, repository: string): string {
|
|
|
522
707
|
'--no-fund',
|
|
523
708
|
'--no-package-lock',
|
|
524
709
|
'tree-sitter-cli@0.24.4',
|
|
710
|
+
// Match the pinned source's lockfile; these are grammar sources, never runtime dependencies.
|
|
711
|
+
'tree-sitter-c@0.23.6',
|
|
712
|
+
'tree-sitter-cpp@0.23.4',
|
|
525
713
|
]);
|
|
526
|
-
|
|
714
|
+
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
715
|
+
execFileSync(cli, ['generate'], {
|
|
716
|
+
cwd: dir,
|
|
717
|
+
env: { ...process.env, NODE_PATH: join(tools, 'node_modules') },
|
|
718
|
+
});
|
|
527
719
|
execFileSync(
|
|
528
|
-
|
|
720
|
+
cli,
|
|
529
721
|
['build', '--wasm', '--docker', '--output', join(dir, 'tree-sitter-objcpp.wasm')],
|
|
530
722
|
{ cwd: dir }
|
|
531
723
|
);
|
|
@@ -611,12 +803,35 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
611
803
|
$.keyword_create, make_keyword("policy"), field('name', $.identifier),
|
|
612
804
|
$.keyword_on, alias($.policy_relation, $.relation),
|
|
613
805
|
optional(seq($.keyword_for, choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete))),
|
|
614
|
-
optional(seq($.keyword_to, $.identifier)),
|
|
806
|
+
optional(seq($.keyword_to, comma_list($.identifier, true))),
|
|
615
807
|
optional(seq($.keyword_using, wrapped_in_parenthesis($._expression))),
|
|
616
808
|
optional(seq($.keyword_with, $.keyword_check, wrapped_in_parenthesis($._expression))),
|
|
617
809
|
),
|
|
618
810
|
create_table: $ => prec.left(`
|
|
619
811
|
);
|
|
812
|
+
// These stored migrations use qualified enum names and table/sequence grants.
|
|
813
|
+
patch(
|
|
814
|
+
` alter_type: $ => seq(
|
|
815
|
+
$.keyword_alter,
|
|
816
|
+
$.keyword_type,
|
|
817
|
+
$.identifier,`,
|
|
818
|
+
` alter_type: $ => seq(
|
|
819
|
+
$.keyword_alter,
|
|
820
|
+
$.keyword_type,
|
|
821
|
+
$.object_reference,`
|
|
822
|
+
);
|
|
823
|
+
patch(' $.reset_statement,', ' $.reset_statement,\n $.grant_statement,');
|
|
824
|
+
patch(
|
|
825
|
+
' _cte: $ => seq(',
|
|
826
|
+
` grant_statement: $ => seq(
|
|
827
|
+
make_keyword("grant"),
|
|
828
|
+
comma_list(choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete, make_keyword("usage")), true),
|
|
829
|
+
$.keyword_on, optional($.keyword_sequence), comma_list($.object_reference, true),
|
|
830
|
+
$.keyword_to, comma_list($.identifier, true),
|
|
831
|
+
),
|
|
832
|
+
|
|
833
|
+
_cte: $ => seq(`
|
|
834
|
+
);
|
|
620
835
|
// Dollar-quoted procedural code is one literal, never a parsed SQL statement list.
|
|
621
836
|
patch(' $.reset_statement,', ' $.reset_statement,\n $.do_statement,');
|
|
622
837
|
patch(
|
|
@@ -639,6 +854,240 @@ function rebuildSql(dir: string, work: string): void {
|
|
|
639
854
|
' conflicts: $ => [',
|
|
640
855
|
' conflicts: $ => [\n [$._expression, $._inner_default_expression],\n [$.create_function],'
|
|
641
856
|
);
|
|
857
|
+
// Fixed R2 cohort: change individual upstream rules, retaining the scanner and AST names.
|
|
858
|
+
const patchRule = (name: string, before: string, after: string): void => {
|
|
859
|
+
const start = grammar.indexOf(` ${name}:`);
|
|
860
|
+
if (start < 0) throw new Error(`SQL rule missing: ${name}`);
|
|
861
|
+
const next = grammar.slice(start + 1).search(/^ [a-zA-Z_]\w*\s*:/m);
|
|
862
|
+
const end = next < 0 ? grammar.length : start + 1 + next;
|
|
863
|
+
const rule = grammar.slice(start, end);
|
|
864
|
+
if (!rule.includes(before)) throw new Error(`SQL ${name} patch no longer applies`);
|
|
865
|
+
grammar = grammar.slice(0, start) + rule.replace(before, after) + grammar.slice(end);
|
|
866
|
+
};
|
|
867
|
+
patchRule('_type', 'prec.left(', 'prec.right(');
|
|
868
|
+
patchRule('array_size_definition', 'prec.left(', 'prec.right(');
|
|
869
|
+
patchRule(
|
|
870
|
+
'_type',
|
|
871
|
+
'$.keyword_geography,',
|
|
872
|
+
`seq($.keyword_geography, optional(wrapped_in_parenthesis(
|
|
873
|
+
seq($.identifier, optional(seq(',', $._natural_number)))
|
|
874
|
+
))),`
|
|
875
|
+
);
|
|
876
|
+
patchRule(
|
|
877
|
+
'_column_constraint',
|
|
878
|
+
'$.keyword_auto_increment,',
|
|
879
|
+
`choice($.keyword_auto_increment, make_keyword("autoincrement")),`
|
|
880
|
+
);
|
|
881
|
+
patchRule('function_argument', '$.literal,', '$._expression,');
|
|
882
|
+
patchRule(
|
|
883
|
+
'_inner_default_expression',
|
|
884
|
+
'$.keyword_current_timestamp,',
|
|
885
|
+
`$.keyword_current_timestamp,
|
|
886
|
+
make_keyword("current_date"),`
|
|
887
|
+
);
|
|
888
|
+
patchRule('create_policy', '$.keyword_delete))),', '$.keyword_delete, $.keyword_all))),');
|
|
889
|
+
patchRule(
|
|
890
|
+
'_create_statement',
|
|
891
|
+
'$.create_function,',
|
|
892
|
+
'alias($.create_procedure, $.create_function),\n $.create_function,'
|
|
893
|
+
);
|
|
894
|
+
patchRule(
|
|
895
|
+
'_drop_statement',
|
|
896
|
+
'$.drop_function,',
|
|
897
|
+
'$.drop_function,\n $.drop_procedure,\n $.drop_policy,'
|
|
898
|
+
);
|
|
899
|
+
patchRule('_alter_statement', '$.alter_type,', '$.alter_type,\n $.alter_policy,');
|
|
900
|
+
patchRule(
|
|
901
|
+
'drop_function',
|
|
902
|
+
'$.object_reference,',
|
|
903
|
+
'$.object_reference,\n optional($.function_arguments),'
|
|
904
|
+
);
|
|
905
|
+
patchRule('drop_index', 'field("name", $.identifier)', 'field("name", $.object_reference)');
|
|
906
|
+
patchRule(
|
|
907
|
+
'alter_column',
|
|
908
|
+
"field('type', $._type),",
|
|
909
|
+
"field('type', $._type),\n optional(seq($.keyword_using, $._expression)),"
|
|
910
|
+
);
|
|
911
|
+
patchRule(
|
|
912
|
+
'add_constraint',
|
|
913
|
+
'$.constraint,',
|
|
914
|
+
'$.constraint,\n optional(seq($.keyword_not, make_keyword("valid"))),'
|
|
915
|
+
);
|
|
916
|
+
patchRule(
|
|
917
|
+
'_alter_specifications',
|
|
918
|
+
'$.set_schema,',
|
|
919
|
+
`$.set_schema,
|
|
920
|
+
seq(make_keyword("validate"), $.keyword_constraint, $.identifier),
|
|
921
|
+
seq($.keyword_rename, $.keyword_constraint, $.identifier, $.keyword_to, $.identifier),
|
|
922
|
+
seq($.keyword_set, paren_list(seq($.identifier, '=', $.literal), true)),
|
|
923
|
+
seq($.keyword_reset, paren_list($.identifier, true)),`
|
|
924
|
+
);
|
|
925
|
+
patchRule(
|
|
926
|
+
'_table_settings',
|
|
927
|
+
'$.table_partition,',
|
|
928
|
+
`seq($.keyword_on, $.keyword_commit, $.keyword_drop),
|
|
929
|
+
$.table_partition,`
|
|
930
|
+
);
|
|
931
|
+
patchRule(
|
|
932
|
+
'create_index',
|
|
933
|
+
'$.index_fields',
|
|
934
|
+
`$.index_fields,
|
|
935
|
+
optional(seq(make_keyword("include"), paren_list($.identifier, true)))`
|
|
936
|
+
);
|
|
937
|
+
patchRule(
|
|
938
|
+
'transaction',
|
|
939
|
+
" optional(';'),",
|
|
940
|
+
` optional(choice(
|
|
941
|
+
seq($.keyword_read, $.keyword_only),
|
|
942
|
+
seq($.keyword_isolation, $.keyword_level, $.keyword_repeatable, $.keyword_read)
|
|
943
|
+
)),
|
|
944
|
+
optional(';'),`
|
|
945
|
+
);
|
|
946
|
+
patchRule(
|
|
947
|
+
'limit',
|
|
948
|
+
'$.literal,',
|
|
949
|
+
'choice($.literal, $.parameter, alias($._qualified_field, $.field)),'
|
|
950
|
+
);
|
|
951
|
+
patchRule(
|
|
952
|
+
'offset',
|
|
953
|
+
'$.literal,',
|
|
954
|
+
'choice($.literal, $.parameter, alias($._qualified_field, $.field)),'
|
|
955
|
+
);
|
|
956
|
+
patchRule(
|
|
957
|
+
'statement',
|
|
958
|
+
` optional($.keyword_analyze),
|
|
959
|
+
optional($.keyword_verbose),`,
|
|
960
|
+
` choice(
|
|
961
|
+
seq(optional($.keyword_analyze), optional($.keyword_verbose)),
|
|
962
|
+
paren_list(seq(choice($.identifier, $.keyword_analyze, $.keyword_verbose),
|
|
963
|
+
optional(choice($.keyword_on, $.keyword_off, $.keyword_true, $.keyword_false))), true)
|
|
964
|
+
),`
|
|
965
|
+
);
|
|
966
|
+
patchRule(
|
|
967
|
+
'_ddl_statement',
|
|
968
|
+
'$.reset_statement,',
|
|
969
|
+
`$.reset_statement,
|
|
970
|
+
$.revoke_statement,
|
|
971
|
+
$.alter_default_privileges,
|
|
972
|
+
$.analyze_statement,
|
|
973
|
+
$.lock_statement,
|
|
974
|
+
$.prepare_statement,
|
|
975
|
+
$.execute_statement,
|
|
976
|
+
$.call_statement,`
|
|
977
|
+
);
|
|
978
|
+
patchRule(
|
|
979
|
+
'_delete_from',
|
|
980
|
+
'$.object_reference,',
|
|
981
|
+
`$.object_reference,
|
|
982
|
+
optional($._alias),
|
|
983
|
+
optional(seq($.keyword_using, comma_list($.relation, true))),`
|
|
984
|
+
);
|
|
985
|
+
patchRule(
|
|
986
|
+
'cte',
|
|
987
|
+
'choice($._dml_read, $._dml_write)',
|
|
988
|
+
'choice($._dml_read, $._dml_write, $.values)'
|
|
989
|
+
);
|
|
990
|
+
patchRule(
|
|
991
|
+
'_on_conflict',
|
|
992
|
+
'optional($._column_list),',
|
|
993
|
+
'optional(seq(paren_list($._expression, true), optional($.where))),'
|
|
994
|
+
);
|
|
995
|
+
patchRule('from', `comma_list($.relation, true),`, '$.relation,');
|
|
996
|
+
patchRule(
|
|
997
|
+
'from',
|
|
998
|
+
` $.join,`,
|
|
999
|
+
` seq(',', $.relation),
|
|
1000
|
+
$.join,`
|
|
1001
|
+
);
|
|
1002
|
+
patchRule('from', ' optional($.order_by),\n optional($.limit),', '');
|
|
1003
|
+
patchRule(
|
|
1004
|
+
'_select_statement',
|
|
1005
|
+
' optional($.from),',
|
|
1006
|
+
` optional($.from),
|
|
1007
|
+
optional($.order_by),
|
|
1008
|
+
optional($.limit),`
|
|
1009
|
+
);
|
|
1010
|
+
patchRule(
|
|
1011
|
+
'set_operation',
|
|
1012
|
+
` ),\n ),`,
|
|
1013
|
+
` ),
|
|
1014
|
+
optional($.order_by),
|
|
1015
|
+
optional($.limit),
|
|
1016
|
+
),`
|
|
1017
|
+
);
|
|
1018
|
+
patchRule('op_other', " '<->',", " '<->',\n '<=>',");
|
|
1019
|
+
patchRule('_expression', '$.interval,', '$.interval,\n $.at_time_zone,');
|
|
1020
|
+
const support = ' $.function_support,\n';
|
|
1021
|
+
if (grammar.split(support).length !== 3) throw new Error('SQL function options changed');
|
|
1022
|
+
grammar = grammar.replaceAll(support, support + ' $.function_configuration,\n');
|
|
1023
|
+
patchRule(
|
|
1024
|
+
'grant_statement',
|
|
1025
|
+
`comma_list(choice($.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete, make_keyword("usage")), true),
|
|
1026
|
+
$.keyword_on, optional($.keyword_sequence), comma_list($.object_reference, true),`,
|
|
1027
|
+
`$._privilege_list,
|
|
1028
|
+
$.keyword_on, $._privilege_target,`
|
|
1029
|
+
);
|
|
1030
|
+
patch(
|
|
1031
|
+
' _cte: $ => seq(',
|
|
1032
|
+
` _privilege_list: $ => comma_list(choice(
|
|
1033
|
+
$.keyword_select, $.keyword_insert, $.keyword_update, $.keyword_delete,
|
|
1034
|
+
make_keyword("usage"), make_keyword("execute"), make_keyword("truncate"),
|
|
1035
|
+
seq($.keyword_all, optional(make_keyword("privileges")))
|
|
1036
|
+
), true),
|
|
1037
|
+
routine_signature: $ => seq($.object_reference, optional($.function_arguments)),
|
|
1038
|
+
_privilege_target: $ => choice(
|
|
1039
|
+
seq($.keyword_function, comma_list($.routine_signature, true)),
|
|
1040
|
+
seq($.keyword_schema, comma_list($.identifier, true)),
|
|
1041
|
+
seq($.keyword_all, choice(make_keyword("tables"), make_keyword("sequences"), make_keyword("functions")),
|
|
1042
|
+
$.keyword_in, $.keyword_schema, comma_list($.identifier, true)),
|
|
1043
|
+
seq(optional(choice($.keyword_table, $.keyword_sequence)), comma_list($.object_reference, true))
|
|
1044
|
+
),
|
|
1045
|
+
revoke_statement: $ => seq(make_keyword("revoke"), $._privilege_list, $.keyword_on,
|
|
1046
|
+
$._privilege_target, $.keyword_from, comma_list($.identifier, true)),
|
|
1047
|
+
alter_default_privileges: $ => seq(
|
|
1048
|
+
$.keyword_alter, $.keyword_default, make_keyword("privileges"),
|
|
1049
|
+
optional(seq($.keyword_for, $.keyword_role, comma_list($.identifier, true))),
|
|
1050
|
+
optional(seq($.keyword_in, $.keyword_schema, comma_list($.identifier, true))),
|
|
1051
|
+
choice(
|
|
1052
|
+
seq(make_keyword("grant"), $._privilege_list, $.keyword_on,
|
|
1053
|
+
choice(make_keyword("tables"), make_keyword("sequences"), make_keyword("functions")),
|
|
1054
|
+
$.keyword_to, comma_list($.identifier, true)),
|
|
1055
|
+
seq(make_keyword("revoke"), $._privilege_list, $.keyword_on,
|
|
1056
|
+
choice(make_keyword("tables"), make_keyword("sequences"), make_keyword("functions")),
|
|
1057
|
+
$.keyword_from, comma_list($.identifier, true))
|
|
1058
|
+
)
|
|
1059
|
+
),
|
|
1060
|
+
drop_policy: $ => seq($.keyword_drop, make_keyword("policy"), optional($._if_exists),
|
|
1061
|
+
$.identifier, $.keyword_on, alias($.policy_relation, $.relation)),
|
|
1062
|
+
alter_policy: $ => seq($.keyword_alter, make_keyword("policy"), $.identifier,
|
|
1063
|
+
$.keyword_on, alias($.policy_relation, $.relation), $.keyword_rename, $.keyword_to, $.identifier),
|
|
1064
|
+
function_configuration: $ => seq($.keyword_set, $.object_reference,
|
|
1065
|
+
choice(seq($.keyword_from, make_keyword("current")),
|
|
1066
|
+
seq(choice('=', $.keyword_to), comma_list(choice($.literal, $.identifier), true)))),
|
|
1067
|
+
_procedure_option: $ => choice($.function_security, $.function_configuration),
|
|
1068
|
+
create_procedure: $ => seq(
|
|
1069
|
+
$.keyword_create, optional($._or_replace), $.keyword_procedure,
|
|
1070
|
+
$.object_reference, $.function_arguments, repeat($._procedure_option),
|
|
1071
|
+
choice(
|
|
1072
|
+
seq($.function_language, repeat($._procedure_option), alias($.opaque_function_body, $.function_body)),
|
|
1073
|
+
seq(alias($.opaque_function_body, $.function_body), repeat($._procedure_option), $.function_language)
|
|
1074
|
+
), repeat($._procedure_option)
|
|
1075
|
+
),
|
|
1076
|
+
drop_procedure: $ => seq($.keyword_drop, $.keyword_procedure, optional($._if_exists),
|
|
1077
|
+
$.routine_signature, optional($._drop_behavior)),
|
|
1078
|
+
call_statement: $ => seq(make_keyword("call"), $.invocation),
|
|
1079
|
+
analyze_statement: $ => seq($.keyword_analyze, $.object_reference, optional(paren_list($.identifier, true))),
|
|
1080
|
+
lock_statement: $ => seq(make_keyword("lock"), $.keyword_table, comma_list($.object_reference, true),
|
|
1081
|
+
$.keyword_in, choice(seq(make_keyword("share"), $.keyword_row, make_keyword("exclusive")),
|
|
1082
|
+
seq(make_keyword("access"), make_keyword("exclusive"))), make_keyword("mode")),
|
|
1083
|
+
prepare_statement: $ => seq(make_keyword("prepare"), $.identifier,
|
|
1084
|
+
optional(paren_list($._type, true)), $.keyword_as, choice($._dml_read, $._dml_write)),
|
|
1085
|
+
execute_statement: $ => seq(make_keyword("execute"), $.identifier, optional(paren_list($._expression))),
|
|
1086
|
+
at_time_zone: $ => prec.left('binary_times', seq($._expression,
|
|
1087
|
+
make_keyword("at"), make_keyword("time"), make_keyword("zone"), $._expression)),
|
|
1088
|
+
|
|
1089
|
+
_cte: $ => seq(`
|
|
1090
|
+
);
|
|
642
1091
|
const functionStart = grammar.indexOf(' create_function: $ => seq(');
|
|
643
1092
|
const functionEnd = grammar.indexOf(' _function_return:', functionStart);
|
|
644
1093
|
if (functionStart < 0 || functionEnd < 0) throw new Error('SQL function patch no longer applies');
|
|
@@ -952,9 +1401,95 @@ function rebuildBash(dir: string, work: string): void {
|
|
|
952
1401
|
);
|
|
953
1402
|
}
|
|
954
1403
|
|
|
1404
|
+
/** Reuse the existing offline WASM toolchain; never install native grammar bindings. */
|
|
1405
|
+
function buildPrerequisite(dir: string, work: string, spec: GrammarSpec): void {
|
|
1406
|
+
const config = join(dir, 'tree-sitter.json');
|
|
1407
|
+
const buildRepositories: Record<string, string> = {
|
|
1408
|
+
clojure: 'https://github.com/oakmac/tree-sitter-clojure',
|
|
1409
|
+
zig: 'https://github.com/GrayJack/tree-sitter-zig',
|
|
1410
|
+
graphql: 'https://github.com/bkegley/tree-sitter-graphql',
|
|
1411
|
+
};
|
|
1412
|
+
if (!existsSync(config) && buildRepositories[spec.id]) {
|
|
1413
|
+
// Old packages omit the build metadata required by the current WASM builder.
|
|
1414
|
+
writeFileSync(
|
|
1415
|
+
config,
|
|
1416
|
+
JSON.stringify({
|
|
1417
|
+
grammars: [
|
|
1418
|
+
{
|
|
1419
|
+
name: spec.id === 'protobuf' ? 'proto' : spec.id,
|
|
1420
|
+
scope: `source.${spec.id}`,
|
|
1421
|
+
path: '.',
|
|
1422
|
+
'file-types': [],
|
|
1423
|
+
},
|
|
1424
|
+
],
|
|
1425
|
+
metadata: {
|
|
1426
|
+
version: (
|
|
1427
|
+
JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) as { version: string }
|
|
1428
|
+
).version,
|
|
1429
|
+
license: spec.id === 'zig' ? 'BSD-3-Clause' : 'MIT',
|
|
1430
|
+
description: 'Pinned parser WASM build',
|
|
1431
|
+
authors: [],
|
|
1432
|
+
links: { repository: buildRepositories[spec.id] },
|
|
1433
|
+
},
|
|
1434
|
+
bindings: {},
|
|
1435
|
+
})
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
if (spec.id === 'graphql') {
|
|
1439
|
+
// The pinned quoted-string rule rejects every escape, including valid GraphQL \n.
|
|
1440
|
+
// Keep the upstream block-string rule and all source offsets unchanged.
|
|
1441
|
+
const path = join(dir, 'grammar.js');
|
|
1442
|
+
const grammar = readFileSync(path, 'utf8');
|
|
1443
|
+
const before = String.raw`seq('"', /[^"\\\n]*/, '"')`;
|
|
1444
|
+
const after = String.raw`seq('"', /([^"\\\r\n]|\\(["\\/bfnrt]|u[0-9a-fA-F]{4}))*/, '"')`;
|
|
1445
|
+
if (!grammar.includes(before)) throw new Error('GraphQL string escape patch no longer applies');
|
|
1446
|
+
writeFileSync(path, grammar.replace(before, after));
|
|
1447
|
+
}
|
|
1448
|
+
if (spec.id === 'zig') {
|
|
1449
|
+
const path = join(dir, 'grammar.js');
|
|
1450
|
+
const grammar = readFileSync(path, 'utf8');
|
|
1451
|
+
const before = '/u{[0-9a-fA-F]+}/';
|
|
1452
|
+
if (!grammar.includes(before))
|
|
1453
|
+
throw new Error('Zig Unicode escape compatibility patch no longer applies');
|
|
1454
|
+
writeFileSync(path, grammar.replace(before, String.raw`/u\{[0-9a-fA-F]+\}/`));
|
|
1455
|
+
}
|
|
1456
|
+
const tools = join(work, 'prerequisite-build');
|
|
1457
|
+
const cli = join(tools, 'node_modules', '.bin', 'tree-sitter');
|
|
1458
|
+
if (!existsSync(cli)) {
|
|
1459
|
+
execFileSync('npm', [
|
|
1460
|
+
'install',
|
|
1461
|
+
'--prefix',
|
|
1462
|
+
tools,
|
|
1463
|
+
'--no-audit',
|
|
1464
|
+
'--no-fund',
|
|
1465
|
+
'--no-package-lock',
|
|
1466
|
+
'tree-sitter-cli@0.24.4',
|
|
1467
|
+
]);
|
|
1468
|
+
}
|
|
1469
|
+
const deadline = Date.now() + 300_000;
|
|
1470
|
+
if (spec.build === 'regenerate') {
|
|
1471
|
+
execFileSync(cli, ['generate'], { cwd: dir, timeout: 300_000 });
|
|
1472
|
+
}
|
|
1473
|
+
execFileSync(
|
|
1474
|
+
cli,
|
|
1475
|
+
[
|
|
1476
|
+
'build',
|
|
1477
|
+
'--wasm',
|
|
1478
|
+
'--docker',
|
|
1479
|
+
'--output',
|
|
1480
|
+
join(dir, spec.wasmFile ?? `tree-sitter-${spec.id}.wasm`),
|
|
1481
|
+
],
|
|
1482
|
+
{
|
|
1483
|
+
cwd: dir,
|
|
1484
|
+
timeout: Math.max(1, deadline - Date.now()),
|
|
1485
|
+
}
|
|
1486
|
+
);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
955
1489
|
function vendor(): Problem[] {
|
|
956
1490
|
const only = process.argv.find((arg) => arg.startsWith('--only='))?.slice(7);
|
|
957
|
-
|
|
1491
|
+
const selected = only?.split(',');
|
|
1492
|
+
if (selected?.some((id) => !GRAMMARS.some((spec) => spec.id === id)))
|
|
958
1493
|
throw new Error(`Unknown grammar: ${only}`);
|
|
959
1494
|
mkdirSync(WASM_DIR, { recursive: true });
|
|
960
1495
|
const work = mkdtempSync(join(tmpdir(), 'ts-grammars-'));
|
|
@@ -965,7 +1500,7 @@ function vendor(): Problem[] {
|
|
|
965
1500
|
|
|
966
1501
|
try {
|
|
967
1502
|
for (const spec of GRAMMARS) {
|
|
968
|
-
if (
|
|
1503
|
+
if (selected && !selected.includes(spec.id)) continue;
|
|
969
1504
|
let dir = extracted.get(spec.pkg);
|
|
970
1505
|
if (!dir) {
|
|
971
1506
|
try {
|
|
@@ -998,6 +1533,7 @@ function vendor(): Problem[] {
|
|
|
998
1533
|
if (spec.id === 'cpp') rebuildCpp(dir, work);
|
|
999
1534
|
if (spec.id === 'bash') rebuildBash(dir, work);
|
|
1000
1535
|
if (spec.id === 'nix' || spec.id === 'cmake') rebuildNixOrCmake(dir, work, spec.id);
|
|
1536
|
+
if (spec.build) buildPrerequisite(dir, work, spec);
|
|
1001
1537
|
}
|
|
1002
1538
|
extracted.set(spec.pkg, dir);
|
|
1003
1539
|
} catch (err) {
|
|
@@ -1015,7 +1551,18 @@ function vendor(): Problem[] {
|
|
|
1015
1551
|
if (!existsSync(wasmSrc)) {
|
|
1016
1552
|
problems.push({ id: spec.id, detail: `${spec.pkg} ships no ${wasmName}` });
|
|
1017
1553
|
} else {
|
|
1018
|
-
|
|
1554
|
+
const compressed = gzipSync(readFileSync(wasmSrc), { level: 9 });
|
|
1555
|
+
// Timestamp is zero in Node gzip; normalize the OS byte across build hosts too.
|
|
1556
|
+
compressed[9] = 255;
|
|
1557
|
+
writeFileSync(join(WASM_DIR, `${spec.id}.wasm.gz`), compressed, { mode: 0o644 });
|
|
1558
|
+
rmSync(join(WASM_DIR, `${spec.id}.wasm`), { force: true });
|
|
1559
|
+
if (spec.licenseFile)
|
|
1560
|
+
writeFileSync(
|
|
1561
|
+
join(WASM_DIR, `${spec.id}.LICENSE`),
|
|
1562
|
+
readFileSync(join(dir, spec.licenseFile), 'utf8')
|
|
1563
|
+
.replace(/\r\n/g, '\n')
|
|
1564
|
+
.replace(/[\u201c\u201d]/g, '"')
|
|
1565
|
+
);
|
|
1019
1566
|
if (spec.id === 'lua') copyFileSync(join(dir, 'LICENSE.md'), join(WASM_DIR, 'lua.LICENSE'));
|
|
1020
1567
|
if (spec.id === 'terraform')
|
|
1021
1568
|
copyFileSync(join(dir, 'LICENSE'), join(WASM_DIR, 'terraform.LICENSE'));
|
|
@@ -1029,7 +1576,7 @@ function vendor(): Problem[] {
|
|
|
1029
1576
|
spec.id === 'nix' ||
|
|
1030
1577
|
spec.id === 'cmake'
|
|
1031
1578
|
)
|
|
1032
|
-
chmodSync(join(WASM_DIR, `${spec.id}.wasm`), 0o644);
|
|
1579
|
+
chmodSync(join(WASM_DIR, `${spec.id}.wasm.gz`), 0o644);
|
|
1033
1580
|
}
|
|
1034
1581
|
|
|
1035
1582
|
// A targeted JS scanner rebuild must retain our module-scope binding query additions.
|
|
@@ -1072,11 +1619,15 @@ if (problems.length > 0) {
|
|
|
1072
1619
|
process.exit(1);
|
|
1073
1620
|
}
|
|
1074
1621
|
|
|
1075
|
-
const sizes = GRAMMARS.map((g) => statSync(join(WASM_DIR, `${g.id}.wasm`)).size);
|
|
1622
|
+
const sizes = GRAMMARS.map((g) => statSync(join(WASM_DIR, `${g.id}.wasm.gz`)).size);
|
|
1076
1623
|
const totalBytes = sizes.reduce((a, b) => a + b, 0);
|
|
1624
|
+
const inflatedBytes = GRAMMARS.reduce(
|
|
1625
|
+
(total, g) => total + gunzipSync(readFileSync(join(WASM_DIR, `${g.id}.wasm.gz`))).length,
|
|
1626
|
+
0
|
|
1627
|
+
);
|
|
1077
1628
|
const totalMB = +(totalBytes / 1048576).toFixed(1);
|
|
1078
1629
|
console.log(
|
|
1079
|
-
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, totalWasmMB: totalMB })}`
|
|
1630
|
+
`VENDOR_GRAMMARS_OK ${JSON.stringify({ grammars: GRAMMARS.length, shippedBytes: totalBytes, inflatedBytes, totalWasmMB: totalMB })}`
|
|
1080
1631
|
);
|
|
1081
1632
|
// Owner-approved Objective-C++ cost: repaired bundle 43.58 MiB (43.67 with Terraform 667475e93), bounded at 45 MiB.
|
|
1082
1633
|
if (totalBytes > 45 * 1048576) {
|