@mnemonik/shared 7.97.2 → 7.98.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/dist/ambientPointer.d.ts.map +1 -1
- package/dist/ambientPointer.js +2 -1
- package/dist/ambientPointer.js.map +1 -1
- package/dist/apiOrigin.d.ts +3 -0
- package/dist/apiOrigin.d.ts.map +1 -0
- package/dist/apiOrigin.js +5 -0
- package/dist/apiOrigin.js.map +1 -0
- package/dist/ast/astChunker.d.ts +12 -12
- package/dist/ast/astChunker.js +32 -32
- package/dist/ast/grammars.d.ts +9 -9
- package/dist/ast/grammars.js +15 -15
- package/dist/codeScanner.d.ts +56 -43
- package/dist/codeScanner.d.ts.map +1 -1
- package/dist/codeScanner.js +262 -143
- package/dist/codeScanner.js.map +1 -1
- package/dist/contextBudget.js +2 -2
- package/dist/contextBudget.js.map +1 -1
- package/dist/gitEditDetector.d.ts +6 -6
- package/dist/gitEditDetector.js +7 -7
- package/dist/hookRuntime.d.ts +35 -2
- package/dist/hookRuntime.d.ts.map +1 -1
- package/dist/hookRuntime.js +127 -33
- package/dist/hookRuntime.js.map +1 -1
- package/dist/hookTimeouts.d.ts +6 -6
- package/dist/hookTimeouts.js +6 -6
- package/dist/hostAdapter.d.ts +135 -0
- package/dist/hostAdapter.d.ts.map +1 -0
- package/dist/hostAdapter.js +323 -0
- package/dist/hostAdapter.js.map +1 -0
- package/dist/hostBinary.d.ts +29 -0
- package/dist/hostBinary.d.ts.map +1 -0
- package/dist/hostBinary.js +179 -0
- package/dist/hostBinary.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/instructions.d.ts +26 -26
- package/dist/instructions.js +26 -26
- package/dist/jitDeliveryAck.d.ts.map +1 -1
- package/dist/jitDeliveryAck.js +2 -0
- package/dist/jitDeliveryAck.js.map +1 -1
- package/dist/projectIdentityFile.d.ts +25 -0
- package/dist/projectIdentityFile.d.ts.map +1 -0
- package/dist/projectIdentityFile.js +87 -0
- package/dist/projectIdentityFile.js.map +1 -0
- package/dist/projectSetupHandoff.d.ts +24 -0
- package/dist/projectSetupHandoff.d.ts.map +1 -0
- package/dist/projectSetupHandoff.js +249 -0
- package/dist/projectSetupHandoff.js.map +1 -0
- package/dist/protectedPaths.d.ts +9 -0
- package/dist/protectedPaths.d.ts.map +1 -0
- package/dist/protectedPaths.js +66 -0
- package/dist/protectedPaths.js.map +1 -0
- package/dist/readiness.d.ts +143 -0
- package/dist/readiness.d.ts.map +1 -0
- package/dist/readiness.js +304 -0
- package/dist/readiness.js.map +1 -0
- package/dist/repositoryFingerprint.d.ts +50 -0
- package/dist/repositoryFingerprint.d.ts.map +1 -0
- package/dist/repositoryFingerprint.js +160 -0
- package/dist/repositoryFingerprint.js.map +1 -0
- package/dist/repositoryRoot.d.ts +56 -0
- package/dist/repositoryRoot.d.ts.map +1 -0
- package/dist/repositoryRoot.js +226 -0
- package/dist/repositoryRoot.js.map +1 -0
- package/dist/runtimeReader.d.ts +102 -0
- package/dist/runtimeReader.d.ts.map +1 -0
- package/dist/runtimeReader.js +408 -0
- package/dist/runtimeReader.js.map +1 -0
- package/dist/runtimeSigners.d.ts +37 -0
- package/dist/runtimeSigners.d.ts.map +1 -0
- package/dist/runtimeSigners.js +507 -0
- package/dist/runtimeSigners.js.map +1 -0
- package/dist/scannerSupervisor.d.ts +35 -0
- package/dist/scannerSupervisor.d.ts.map +1 -0
- package/dist/scannerSupervisor.js +2 -0
- package/dist/scannerSupervisor.js.map +1 -0
- package/dist/secretPatterns.d.ts +9 -9
- package/dist/secretPatterns.d.ts.map +1 -1
- package/dist/secretPatterns.js +27 -25
- package/dist/secretPatterns.js.map +1 -1
- package/dist/testing/hostAdapterConformance.d.ts +17 -0
- package/dist/testing/hostAdapterConformance.d.ts.map +1 -0
- package/dist/testing/hostAdapterConformance.js +477 -0
- package/dist/testing/hostAdapterConformance.js.map +1 -0
- package/dist/usageGuide.d.ts +1 -1
- package/dist/usageGuide.d.ts.map +1 -1
- package/dist/usageGuide.js +4 -4
- package/package.json +7 -2
- package/queries/bash.tags.scm +1 -1
- package/queries/groovy.tags.scm +1 -1
- package/scripts/vendor-grammars.ts +13 -13
- package/src/ambientPointer.ts +2 -1
- package/src/apiOrigin.ts +4 -0
- package/src/ast/astChunker.ts +39 -39
- package/src/ast/grammars.ts +16 -16
- package/src/codeScanner.ts +274 -149
- package/src/contextBudget.ts +2 -2
- package/src/gitEditDetector.ts +7 -7
- package/src/hookRuntime.ts +162 -34
- package/src/hookTimeouts.ts +6 -6
- package/src/hostAdapter.ts +468 -0
- package/src/hostBinary.ts +205 -0
- package/src/index.ts +20 -0
- package/src/instructions.ts +26 -26
- package/src/jitDeliveryAck.ts +2 -0
- package/src/projectIdentityFile.ts +100 -0
- package/src/projectSetupHandoff.ts +275 -0
- package/src/protectedPaths.ts +88 -0
- package/src/readiness.ts +516 -0
- package/src/repositoryFingerprint.ts +199 -0
- package/src/repositoryRoot.ts +261 -0
- package/src/runtimeReader.ts +495 -0
- package/src/runtimeSigners.ts +577 -0
- package/src/scannerSupervisor.ts +26 -0
- package/src/secretPatterns.ts +27 -25
- package/src/testing/hostAdapterConformance.ts +538 -0
- package/src/usageGuide.ts +4 -4
- package/test-fixtures/identity/runner.d.mts +12 -0
- package/test-fixtures/identity/runner.mjs +282 -0
- package/tests/fixtures/repository-fingerprint-v1.golden.json +834 -0
- package/tests/projectIdentity.test.ts +56 -0
- package/tests/readiness.test.ts +158 -0
- package/tests/repositoryFingerprint.test.ts +26 -0
- package/tsconfig.test.json +9 -0
- package/wasm/bash.tags.scm +1 -1
- package/wasm/groovy.tags.scm +1 -1
- package/wasm/javascript.tags.scm +2 -2
- package/wasm/solidity.tags.scm +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ambientPointer.d.ts","sourceRoot":"","sources":["../src/ambientPointer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAK1C,wFAAwF;AACxF,eAAO,MAAM,2BAA2B,
|
|
1
|
+
{"version":3,"file":"ambientPointer.d.ts","sourceRoot":"","sources":["../src/ambientPointer.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAK1C,wFAAwF;AACxF,eAAO,MAAM,2BAA2B,QAEnB,CAAC;AAEtB,wBAAgB,uBAAuB,CAAC,KAAK,SAAM,GAAG,MAAM,CAE3D"}
|
package/dist/ambientPointer.js
CHANGED
|
@@ -2,7 +2,8 @@ export const AMBIENT_ID_PREFIX_LENGTH = 8;
|
|
|
2
2
|
const MEMORY_UUID_SOURCE = '[0-9A-Fa-f]{8}-(?:[0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}';
|
|
3
3
|
const LEGACY_MEMORY_ID_SOURCE = `[0-9A-Za-z_-]{${AMBIENT_ID_PREFIX_LENGTH}}`;
|
|
4
4
|
/** Current full UUID pointers plus cached eight-character pointers from older hooks. */
|
|
5
|
-
export const AMBIENT_ITEM_POINTER_SOURCE =
|
|
5
|
+
export const AMBIENT_ITEM_POINTER_SOURCE = `\\u2014\\s*memory_get\\s+(${MEMORY_UUID_SOURCE}|${LEGACY_MEMORY_ID_SOURCE})` +
|
|
6
|
+
'(?![0-9A-Za-z_-])';
|
|
6
7
|
export function ambientItemPointerRegex(flags = 'g') {
|
|
7
8
|
return new RegExp(AMBIENT_ITEM_POINTER_SOURCE, flags);
|
|
8
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ambientPointer.js","sourceRoot":"","sources":["../src/ambientPointer.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAE1C,MAAM,kBAAkB,GAAG,sDAAsD,CAAC;AAClF,MAAM,uBAAuB,GAAG,iBAAiB,wBAAwB,GAAG,CAAC;AAE7E,wFAAwF;AACxF,MAAM,CAAC,MAAM,2BAA2B,GACtC,
|
|
1
|
+
{"version":3,"file":"ambientPointer.js","sourceRoot":"","sources":["../src/ambientPointer.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAE1C,MAAM,kBAAkB,GAAG,sDAAsD,CAAC;AAClF,MAAM,uBAAuB,GAAG,iBAAiB,wBAAwB,GAAG,CAAC;AAE7E,wFAAwF;AACxF,MAAM,CAAC,MAAM,2BAA2B,GACtC,6BAA6B,kBAAkB,IAAI,uBAAuB,GAAG;IAC7E,mBAAmB,CAAC;AAEtB,MAAM,UAAU,uBAAuB,CAAC,KAAK,GAAG,GAAG;IACjD,OAAO,IAAI,MAAM,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiOrigin.d.ts","sourceRoot":"","sources":["../src/apiOrigin.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAEtE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apiOrigin.js","sourceRoot":"","sources":["../src/apiOrigin.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,UAAU,SAAS,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG;IAC5D,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,qBAAqB,IAAI,0BAA0B,CAAC,CAAC,MAAM,CAAC;AACjF,CAAC"}
|
package/dist/ast/astChunker.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* logging of file contents, one pure entry point (`chunkWithAst`).
|
|
4
4
|
*
|
|
5
5
|
* WHY THIS EXISTS. The heuristic chunker matches a regex whose name pattern
|
|
6
|
-
* requires a leading `function`/`class`/`const` keyword
|
|
6
|
+
* requires a leading `function`/`class`/`const` keyword - a keyword a method's
|
|
7
7
|
* first line never has. So it produces method-shaped chunks with no
|
|
8
8
|
* `symbolName`: 1,512 methods in this repo, unnameable and therefore unusable
|
|
9
9
|
* as citation anchors. Measured over the same 1,037 TypeScript files, the
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
* THE NESTING RULE. Emitting both a whole class and each of its methods would
|
|
14
14
|
* duplicate every method body and double the embedding bill, so:
|
|
15
15
|
*
|
|
16
|
-
* - a STRUCTURAL definition
|
|
17
|
-
* (class, interface, enum, struct, trait, object, module, namespace)
|
|
16
|
+
* - a STRUCTURAL definition - one whose body is a container of other definitions
|
|
17
|
+
* (class, interface, enum, struct, trait, object, module, namespace) - emits a
|
|
18
18
|
* HEADER chunk from its own first line to the line before its first nested
|
|
19
19
|
* definition: the declaration plus the fields that precede the first method.
|
|
20
20
|
* Real contiguous source, never an elision;
|
|
21
21
|
* - every other definition is a LEAF and becomes one chunk over its FULL line
|
|
22
22
|
* range, whatever it happens to contain. A local arrow function is part of
|
|
23
23
|
* what the enclosing function IS, not a sibling of it, so definitions nested
|
|
24
|
-
* inside a leaf are not emitted separately
|
|
24
|
+
* inside a leaf are not emitted separately - the leaf's chunk already carries
|
|
25
25
|
* their source verbatim. See `STRUCTURAL_KINDS` for why that distinction is
|
|
26
26
|
* load-bearing rather than cosmetic;
|
|
27
27
|
* - every remaining uncovered line span becomes a `raw` chunk.
|
|
@@ -66,11 +66,11 @@ export interface AstChunk {
|
|
|
66
66
|
chunkType: 'function' | 'class' | 'module' | 'raw';
|
|
67
67
|
/**
|
|
68
68
|
* Bare symbol name, never qualified. Present on every chunk that came from a
|
|
69
|
-
* `definition.*` capture
|
|
69
|
+
* `definition.*` capture - INCLUDING the value-shaped kinds that map to
|
|
70
70
|
* `chunkType: 'raw'` (`variable`, `constant`, `field`, `property`), because the
|
|
71
71
|
* wire enum has no value-shaped member but the identity is real and
|
|
72
72
|
* `memory_file_index.symbol_name` indexes it either way. Absent only on the
|
|
73
|
-
* uncovered-span chunks, which have no capture behind them
|
|
73
|
+
* uncovered-span chunks, which have no capture behind them - those are exactly
|
|
74
74
|
* the chunks with no `symbolKind` either.
|
|
75
75
|
*/
|
|
76
76
|
symbolName?: string;
|
|
@@ -79,14 +79,14 @@ export interface AstChunk {
|
|
|
79
79
|
/** The definition's first line, trimmed, capped at 500 chars. */
|
|
80
80
|
signature?: string;
|
|
81
81
|
/**
|
|
82
|
-
* Name of the immediate STRUCTURAL parent
|
|
82
|
+
* Name of the immediate STRUCTURAL parent - whatever `STRUCTURAL_KINDS` admits
|
|
83
83
|
* for the language. Absent at module scope, and absent inside a leaf (nothing
|
|
84
84
|
* inside a leaf is emitted at all).
|
|
85
85
|
*
|
|
86
86
|
* In TS/JS that is `class`, `interface` and a module-scope `const`; NOT `enum`
|
|
87
87
|
* and NOT `namespace`, despite both being structural kinds. Enum members are
|
|
88
88
|
* never captured as definitions, and `namespace Outer {}` parses as
|
|
89
|
-
* `internal_module`, which typescript.tags.scm does not match
|
|
89
|
+
* `internal_module`, which typescript.tags.scm does not match - `Outer`
|
|
90
90
|
* produces no definition, so it can never be anybody's container. Do not widen
|
|
91
91
|
* this list from `STRUCTURAL_KINDS` alone; a kind is only reachable here if
|
|
92
92
|
* some tag query also captures a definition INSIDE it.
|
|
@@ -102,8 +102,8 @@ export type AstChunkResult = {
|
|
|
102
102
|
/**
|
|
103
103
|
* Definitions that reached no chunk. Two chunks over one line range would
|
|
104
104
|
* collide on `filePath:startLine-endLine`, the staleness key ProjectManager
|
|
105
|
-
* compares, so a second definition sharing a range
|
|
106
|
-
* function b() {}` on one line
|
|
105
|
+
* compares, so a second definition sharing a range - `function a() {}
|
|
106
|
+
* function b() {}` on one line - cannot be emitted, and neither can a
|
|
107
107
|
* container whose first nested definition opens on the container's own
|
|
108
108
|
* first line (`class A { m() {} }`). Two captures can also COLLAPSE onto one
|
|
109
109
|
* range while widening: `int f(int), g(int);` binds two declarators to one
|
|
@@ -121,7 +121,7 @@ export type AstChunkResult = {
|
|
|
121
121
|
* Parse ceiling, derived from Task 4's measurement rather than guessed: the
|
|
122
122
|
* largest source file in this repo is 415 KB (`src/agent/ContextAgent.ts`) and
|
|
123
123
|
* the slowest per-file parse across 1,061 files was 108.6 ms. 2 MiB is ~5x that
|
|
124
|
-
* largest real file, which bounds the worst case near half a second
|
|
124
|
+
* largest real file, which bounds the worst case near half a second - while
|
|
125
125
|
* still refusing the multi-megabyte generated blobs that `MAX_SCANNED_FILE_BYTES`
|
|
126
126
|
* (10 MB) otherwise lets through. Above the ceiling the caller degrades to the
|
|
127
127
|
* heuristic chunker, which is line-bounded and cheap.
|
|
@@ -132,7 +132,7 @@ export declare const MAX_AST_PARSE_BYTES: number;
|
|
|
132
132
|
*
|
|
133
133
|
* Async only because `loadGrammar` is; the grammar is cached per process, so
|
|
134
134
|
* after the first file of a given language there is no per-file async cost.
|
|
135
|
-
* Never throws
|
|
135
|
+
* Never throws - every failure is a named `unsupported` reason with a detail the
|
|
136
136
|
* caller can log before degrading.
|
|
137
137
|
*/
|
|
138
138
|
export declare function chunkWithAst(content: string, languageId: AstLanguageId, opts?: {
|
package/dist/ast/astChunker.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* logging of file contents, one pure entry point (`chunkWithAst`).
|
|
4
4
|
*
|
|
5
5
|
* WHY THIS EXISTS. The heuristic chunker matches a regex whose name pattern
|
|
6
|
-
* requires a leading `function`/`class`/`const` keyword
|
|
6
|
+
* requires a leading `function`/`class`/`const` keyword - a keyword a method's
|
|
7
7
|
* first line never has. So it produces method-shaped chunks with no
|
|
8
8
|
* `symbolName`: 1,512 methods in this repo, unnameable and therefore unusable
|
|
9
9
|
* as citation anchors. Measured over the same 1,037 TypeScript files, the
|
|
@@ -13,15 +13,15 @@
|
|
|
13
13
|
* THE NESTING RULE. Emitting both a whole class and each of its methods would
|
|
14
14
|
* duplicate every method body and double the embedding bill, so:
|
|
15
15
|
*
|
|
16
|
-
* - a STRUCTURAL definition
|
|
17
|
-
* (class, interface, enum, struct, trait, object, module, namespace)
|
|
16
|
+
* - a STRUCTURAL definition - one whose body is a container of other definitions
|
|
17
|
+
* (class, interface, enum, struct, trait, object, module, namespace) - emits a
|
|
18
18
|
* HEADER chunk from its own first line to the line before its first nested
|
|
19
19
|
* definition: the declaration plus the fields that precede the first method.
|
|
20
20
|
* Real contiguous source, never an elision;
|
|
21
21
|
* - every other definition is a LEAF and becomes one chunk over its FULL line
|
|
22
22
|
* range, whatever it happens to contain. A local arrow function is part of
|
|
23
23
|
* what the enclosing function IS, not a sibling of it, so definitions nested
|
|
24
|
-
* inside a leaf are not emitted separately
|
|
24
|
+
* inside a leaf are not emitted separately - the leaf's chunk already carries
|
|
25
25
|
* their source verbatim. See `STRUCTURAL_KINDS` for why that distinction is
|
|
26
26
|
* load-bearing rather than cosmetic;
|
|
27
27
|
* - every remaining uncovered line span becomes a `raw` chunk.
|
|
@@ -60,7 +60,7 @@ import { loadGrammar } from './grammars.js';
|
|
|
60
60
|
* Parse ceiling, derived from Task 4's measurement rather than guessed: the
|
|
61
61
|
* largest source file in this repo is 415 KB (`src/agent/ContextAgent.ts`) and
|
|
62
62
|
* the slowest per-file parse across 1,061 files was 108.6 ms. 2 MiB is ~5x that
|
|
63
|
-
* largest real file, which bounds the worst case near half a second
|
|
63
|
+
* largest real file, which bounds the worst case near half a second - while
|
|
64
64
|
* still refusing the multi-megabyte generated blobs that `MAX_SCANNED_FILE_BYTES`
|
|
65
65
|
* (10 MB) otherwise lets through. Above the ceiling the caller degrades to the
|
|
66
66
|
* heuristic chunker, which is line-bounded and cheap.
|
|
@@ -81,7 +81,7 @@ const MAX_SIGNATURE_CHARS = 500;
|
|
|
81
81
|
* Kinds absent here (`constant`, `field`, `property`, `variable`) fall to
|
|
82
82
|
* `'raw'`: the enum has no value-shaped member, and claiming a constant is a
|
|
83
83
|
* `class` or a `module` would be false where `'raw'` only says "no coarse class
|
|
84
|
-
* for this"
|
|
84
|
+
* for this" - the identity is still carried by `symbolName` + `symbolKind`.
|
|
85
85
|
*/
|
|
86
86
|
const CHUNK_TYPE_BY_KIND = {
|
|
87
87
|
function: 'function',
|
|
@@ -104,7 +104,7 @@ const CHUNK_TYPE_BY_KIND = {
|
|
|
104
104
|
* The distinction is load-bearing, not cosmetic. When every `definition.*`
|
|
105
105
|
* capture counted as a nested child, a function declaring one local arrow
|
|
106
106
|
* function collapsed to its first two lines: `ContextAgent.registerDocsTools`
|
|
107
|
-
* spans 513 lines and was recorded as 2. A wrong extent is worse than no extent
|
|
107
|
+
* spans 513 lines and was recorded as 2. A wrong extent is worse than no extent -
|
|
108
108
|
* it anchors citations confidently at the wrong place instead of failing to
|
|
109
109
|
* anchor them.
|
|
110
110
|
*
|
|
@@ -115,20 +115,20 @@ const CHUNK_TYPE_BY_KIND = {
|
|
|
115
115
|
* double the embedding bill.
|
|
116
116
|
*
|
|
117
117
|
* `constant` IS IN, and only because the tag queries anchor it to module scope.
|
|
118
|
-
* A module `const` is the ordinary home of a handler map or an evaluator table
|
|
119
|
-
* `export const EVALUATORS = { foo() {...}, bar: () => {...} }`
|
|
118
|
+
* A module `const` is the ordinary home of a handler map or an evaluator table -
|
|
119
|
+
* `export const EVALUATORS = { foo() {...}, bar: () => {...} }` - whose members
|
|
120
120
|
* are separately named definitions a reader looks up by name. As a leaf it
|
|
121
121
|
* suppressed all of them: 49 named symbols vanished from `src/` alone, with
|
|
122
122
|
* `droppedDefinitions` at 0, which is the silent-loss class that counter exists
|
|
123
123
|
* to prevent. A function-valued `const` is NOT affected: it binds
|
|
124
124
|
* `definition.function` on the same range and KIND_SPECIFICITY keeps that kind,
|
|
125
125
|
* so a closure and its local helpers stay one chunk. A `const` with no nested
|
|
126
|
-
* definition never splits either
|
|
127
|
-
* exists
|
|
126
|
+
* definition never splits either - `headerEndRow` is only set when a child
|
|
127
|
+
* exists - so the scalar case is byte-identical to the leaf behaviour.
|
|
128
128
|
*
|
|
129
129
|
* `type` stays out deliberately. C's `(type_definition declarator:
|
|
130
130
|
* (type_identifier) @name) @definition.type` matches `typedef struct {...} Foo;`,
|
|
131
|
-
* whose nested `struct_specifier` opens on the typedef's own first line
|
|
131
|
+
* whose nested `struct_specifier` opens on the typedef's own first line - as a
|
|
132
132
|
* container it would split to an empty header and be dropped entirely, so the
|
|
133
133
|
* typedef is the leaf and keeps the whole range.
|
|
134
134
|
*/
|
|
@@ -166,7 +166,7 @@ function parserFor(binding) {
|
|
|
166
166
|
*
|
|
167
167
|
* Async only because `loadGrammar` is; the grammar is cached per process, so
|
|
168
168
|
* after the first file of a given language there is no per-file async cost.
|
|
169
|
-
* Never throws
|
|
169
|
+
* Never throws - every failure is a named `unsupported` reason with a detail the
|
|
170
170
|
* caller can log before degrading.
|
|
171
171
|
*/
|
|
172
172
|
export async function chunkWithAst(content, languageId, opts) {
|
|
@@ -210,9 +210,9 @@ export async function chunkWithAst(content, languageId, opts) {
|
|
|
210
210
|
try {
|
|
211
211
|
const lines = content.split('\n');
|
|
212
212
|
// A trailing newline TERMINATES the last line, it does not open a new one,
|
|
213
|
-
// but `split` yields a phantom '' for it. Dropping it here
|
|
213
|
+
// but `split` yields a phantom '' for it. Dropping it here - before
|
|
214
214
|
// `lines.length` is read by the coverage array, `uncoveredSpans` or
|
|
215
|
-
// `sliceLines`
|
|
215
|
+
// `sliceLines` - is what keeps `endLine` equal to the file's last line
|
|
216
216
|
// number. Left in, the final raw chunk of every newline-terminated file (109
|
|
217
217
|
// of this repo's 268 `src/` TypeScript files) ran one line past the end, and
|
|
218
218
|
// `memory_file_index.end_line` feeds citation anchoring and the golden eval's
|
|
@@ -225,8 +225,8 @@ export async function chunkWithAst(content, languageId, opts) {
|
|
|
225
225
|
chunks: built.chunks,
|
|
226
226
|
errorNodes: countErrorNodes(tree),
|
|
227
227
|
parseMs,
|
|
228
|
-
// A definition can be lost at either stage
|
|
229
|
-
// definition's byte range here, or reaching no chunk in `buildChunks`
|
|
228
|
+
// A definition can be lost at either stage - collapsed onto another
|
|
229
|
+
// definition's byte range here, or reaching no chunk in `buildChunks` - and
|
|
230
230
|
// the caller logs one number, so both have to be in it.
|
|
231
231
|
droppedDefinitions: built.droppedDefinitions + collected.collapsedDefinitions,
|
|
232
232
|
};
|
|
@@ -245,7 +245,7 @@ export async function chunkWithAst(content, languageId, opts) {
|
|
|
245
245
|
* `STRUCTURAL_KINDS`, and a fourth table keyed on `definition.<kind>` drifts
|
|
246
246
|
* from the other three the moment a grammar is vendored: listing the strong
|
|
247
247
|
* kinds once already omitted `struct`, `object`, `trait` and `macro`, which
|
|
248
|
-
* scored 0 and LOST to `constant`
|
|
248
|
+
* scored 0 and LOST to `constant` - inverting the whole point of the table and
|
|
249
249
|
* able to demote a structural kind to a leaf. Deny-listing the four value-shaped
|
|
250
250
|
* kinds cannot fail that way: a kind nobody has thought of yet outranks a
|
|
251
251
|
* `constant` instead of losing to it, which is the safe direction.
|
|
@@ -263,7 +263,7 @@ const DEFAULT_KIND_SPECIFICITY = 3;
|
|
|
263
263
|
*
|
|
264
264
|
* `matches()` rather than `captures()`: a match is one pattern's captures, so
|
|
265
265
|
* the `@name` belonging to a definition is unambiguous. `captures()` returns a
|
|
266
|
-
* flat stream in which pairing is guesswork
|
|
266
|
+
* flat stream in which pairing is guesswork - and the composed QUERY_CHAIN
|
|
267
267
|
* concatenates several files' patterns, so guessing would mispair across
|
|
268
268
|
* grammars.
|
|
269
269
|
*/
|
|
@@ -339,7 +339,7 @@ function collectDefinitions(query, root) {
|
|
|
339
339
|
* (function_declarator declarator: (identifier) @name) @definition.function
|
|
340
340
|
*
|
|
341
341
|
* `function_declarator` ends at the closing paren of the parameter list, so
|
|
342
|
-
* naming it alone reproduces
|
|
342
|
+
* naming it alone reproduces - for two whole languages - the exact defect this
|
|
343
343
|
* module exists to fix: a named signature line plus an anonymous raw chunk
|
|
344
344
|
* holding the body.
|
|
345
345
|
*
|
|
@@ -352,10 +352,10 @@ function collectDefinitions(query, root) {
|
|
|
352
352
|
* owns the body (`function_definition`, `declaration`, `field_declaration`,
|
|
353
353
|
* through any `pointer_declarator` or `array_declarator` in between).
|
|
354
354
|
* 2. A DECLARATOR WRAPPER. `int &f()` parses as
|
|
355
|
-
* `(function_definition declarator: (reference_declarator (function_declarator
|
|
356
|
-
* and `int (*f(void))[4]` as
|
|
355
|
+
* `(function_definition declarator: (reference_declarator (function_declarator ...)))`
|
|
356
|
+
* and `int (*f(void))[4]` as `... (parenthesized_declarator (pointer_declarator ...))`.
|
|
357
357
|
* Neither `reference_declarator` nor `parenthesized_declarator` NAMES the
|
|
358
|
-
* declarator it wraps
|
|
358
|
+
* declarator it wraps - the child sits in an unnamed field - so rule 1 alone
|
|
359
359
|
* stopped dead at `function_declarator` and reproduced the very defect above
|
|
360
360
|
* for `T &operator[]`, `std::string &name()`, and every other
|
|
361
361
|
* reference-returning accessor in real C++. So also ascend when the parent is
|
|
@@ -364,7 +364,7 @@ function collectDefinitions(query, root) {
|
|
|
364
364
|
* Both forms keep the property that made rule 1 safe: neither can reach an
|
|
365
365
|
* unrelated ancestor. Rule 1 follows a field the grammar defines only within a
|
|
366
366
|
* declaration; rule 2 requires BOTH ends to be declarator nodes, and a
|
|
367
|
-
* `field_declaration_list` is not one
|
|
367
|
+
* `field_declaration_list` is not one - a method inside a class body therefore
|
|
368
368
|
* still stops at its own `function_definition` and a class is never swallowed.
|
|
369
369
|
* Grammars that already bind the whole definition (every JS/TS, Python, Go, Rust,
|
|
370
370
|
* Ruby pattern) fail both conditions on the first iteration, which makes this a
|
|
@@ -380,7 +380,7 @@ function widenToDefinition(node) {
|
|
|
380
380
|
return current;
|
|
381
381
|
// `childrenForFieldName`, not `childForFieldName`: `int a, f(int x);` binds
|
|
382
382
|
// two declarators to one declaration, and the singular accessor answers only
|
|
383
|
-
// the first
|
|
383
|
+
// the first - which would refuse to widen every declarator but one.
|
|
384
384
|
const boundToDeclaratorField = parent
|
|
385
385
|
.childrenForFieldName('declarator')
|
|
386
386
|
.some((child) => child.id === current.id);
|
|
@@ -395,7 +395,7 @@ function isDeclarator(node) {
|
|
|
395
395
|
}
|
|
396
396
|
/**
|
|
397
397
|
* True when `parent` is a declarator that wraps `child` without naming the field
|
|
398
|
-
*
|
|
398
|
+
* - `reference_declarator` (`&` / `&&`) and `parenthesized_declarator` (`( ... )`),
|
|
399
399
|
* whose grammar rules are a bare token sequence around the inner declarator.
|
|
400
400
|
*
|
|
401
401
|
* Both ends must be declarators, and the field must be UNNAMED: a declarator's
|
|
@@ -422,7 +422,7 @@ function fieldNameForChild(parent, child) {
|
|
|
422
422
|
}
|
|
423
423
|
function buildChunks(definitions, lines) {
|
|
424
424
|
// `headerEndRow[i]` is the 0-based row of definition `i`'s first nested
|
|
425
|
-
// definition
|
|
425
|
+
// definition - set only for STRUCTURAL definitions, since only they split.
|
|
426
426
|
// `suppressed[i]` marks a definition that lies inside a leaf and is therefore
|
|
427
427
|
// already carried, verbatim, by that leaf's own chunk.
|
|
428
428
|
const headerEndRow = new Map();
|
|
@@ -486,7 +486,7 @@ function buildChunks(definitions, lines) {
|
|
|
486
486
|
// starts on `headerEnd + 1`, so its header ends on the line before that:
|
|
487
487
|
// `headerEnd`. When the child opens on the container's own first line
|
|
488
488
|
// (`class A { m() {} }`) that range is empty, `emit` refuses it and the
|
|
489
|
-
// refusal is counted
|
|
489
|
+
// refusal is counted - emitting the line anyway would duplicate the child's
|
|
490
490
|
// source. Clamped to the last real line so a definition whose node runs to
|
|
491
491
|
// end-of-file cannot name a line that does not exist.
|
|
492
492
|
const headerEnd = headerEndRow.get(i);
|
|
@@ -507,7 +507,7 @@ function buildChunks(definitions, lines) {
|
|
|
507
507
|
// A definition that reaches no chunk reaches no index either, and a citation
|
|
508
508
|
// to it resolves as `unresolved_symbol`. It cannot be emitted without
|
|
509
509
|
// colliding on the staleness key, so it is counted and reported instead of
|
|
510
|
-
// vanishing
|
|
510
|
+
// vanishing - a silent no-op is the defect class, not the collision.
|
|
511
511
|
if (!emitted)
|
|
512
512
|
droppedDefinitions++;
|
|
513
513
|
}
|
|
@@ -549,13 +549,13 @@ function uncoveredSpans(covered, lineCount) {
|
|
|
549
549
|
}
|
|
550
550
|
/**
|
|
551
551
|
* Break an uncovered span on line boundaries so no chunk exceeds
|
|
552
|
-
* `MAX_RAW_SPAN_CHARS`. No overlap
|
|
552
|
+
* `MAX_RAW_SPAN_CHARS`. No overlap - overlap would re-embed the same lines - and
|
|
553
553
|
* no mid-line splitting: two chunks over one line range would collide on the
|
|
554
554
|
* `filePath:startLine-endLine` staleness key, so an over-long single line is
|
|
555
555
|
* left whole and the embedding layer truncates it with a warning
|
|
556
556
|
* (`EmbeddingService` caps each input at the 8191-token per-input limit).
|
|
557
557
|
*
|
|
558
|
-
* Whitespace-only spans yield nothing
|
|
558
|
+
* Whitespace-only spans yield nothing - `emit` drops them, and the blank lines
|
|
559
559
|
* between definitions are the one thing total coverage does not owe a chunk.
|
|
560
560
|
*/
|
|
561
561
|
function splitSpan(lines, [spanStart, spanEnd]) {
|
|
@@ -579,7 +579,7 @@ function splitSpan(lines, [spanStart, spanEnd]) {
|
|
|
579
579
|
* of inferring it from thin chunks.
|
|
580
580
|
*
|
|
581
581
|
* Short-circuits on a clean tree, and descends only into subtrees whose own
|
|
582
|
-
* `hasError` is true
|
|
582
|
+
* `hasError` is true - 97.6% of this repo's TypeScript files have no error at
|
|
583
583
|
* all, and they must not pay for a full tree walk.
|
|
584
584
|
*/
|
|
585
585
|
function countErrorNodes(tree) {
|
package/dist/ast/grammars.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Every failure mode is a named value (`wasm_missing`, `wasm_load_failed`,
|
|
6
6
|
* `tags_query_missing`, `query_compile_failed`, `not_covered`) rather than a
|
|
7
7
|
* null or a throw, because the consequence of a degraded install is not a crash
|
|
8
|
-
*
|
|
8
|
+
* - it is quietly worse chunks, forever, with nothing in the logs. A caller that
|
|
9
9
|
* gets `unavailable` can fall back to the heuristic chunker AND say why.
|
|
10
10
|
*
|
|
11
11
|
* Artifacts are vendored, not installed: `packages/shared/wasm/<id>.wasm` plus
|
|
@@ -39,7 +39,7 @@ export declare const AST_LANGUAGE_IDS: readonly AstLanguageId[];
|
|
|
39
39
|
export declare function grammarArtifactBasename(id: AstLanguageId): string;
|
|
40
40
|
/**
|
|
41
41
|
* Ordered tag-query files composing each grammar's EFFECTIVE query. THE source
|
|
42
|
-
* of truth
|
|
42
|
+
* of truth - `scripts/vendor-grammars.ts` imports this rather than keeping its
|
|
43
43
|
* own copy, because two chains that can drift is precisely the defect this
|
|
44
44
|
* layer exists to remove.
|
|
45
45
|
*
|
|
@@ -48,7 +48,7 @@ export declare function grammarArtifactBasename(id: AstLanguageId): string;
|
|
|
48
48
|
* `interface_declaration`, `abstract_class_declaration`);
|
|
49
49
|
* `function_declaration`, `class_declaration`, `method_definition` and arrow
|
|
50
50
|
* functions all live in javascript's query and are meant to be inherited.
|
|
51
|
-
* Nothing in the query engine resolves that
|
|
51
|
+
* Nothing in the query engine resolves that - composing the chain is the
|
|
52
52
|
* consumer's job.
|
|
53
53
|
*
|
|
54
54
|
* Measured cost of not composing it: 948 definitions across 1,037 TypeScript
|
|
@@ -82,7 +82,7 @@ export type GrammarLoad = {
|
|
|
82
82
|
* in parallel forks, so renaming `ruby.wasm` aside is visible to every other
|
|
83
83
|
* file for as long as it lasts, and any file that cold-loads Ruby inside that
|
|
84
84
|
* window caches a `wasm_missing` this checkout does not have. Copy from here
|
|
85
|
-
* into a temp directory and break the copy
|
|
85
|
+
* into a temp directory and break the copy - `loadGrammar` takes the directory.
|
|
86
86
|
*/
|
|
87
87
|
export declare const VENDORED_ARTIFACT_DIR: string;
|
|
88
88
|
/**
|
|
@@ -104,7 +104,7 @@ export declare function resolveAstLanguage(extension: string, language: string):
|
|
|
104
104
|
*/
|
|
105
105
|
export declare function loadGrammar(id: AstLanguageId, artifactDir?: string): Promise<GrammarLoad>;
|
|
106
106
|
/**
|
|
107
|
-
* Which grammars this process has instantiated
|
|
107
|
+
* Which grammars this process has instantiated - what is resident in wasm
|
|
108
108
|
* memory right now, not what is vendored or what was asked for.
|
|
109
109
|
*
|
|
110
110
|
* Exists because the cost is permanent and therefore worth being able to state:
|
|
@@ -117,13 +117,13 @@ export declare function loadedGrammarIds(artifactDir?: string): AstLanguageId[];
|
|
|
117
117
|
*
|
|
118
118
|
* Every check is a `statSync` plus a few hundred bytes of `.scm`: the grammar's
|
|
119
119
|
* `.wasm` is present and non-empty, and so is every tag-query file in its chain.
|
|
120
|
-
* Microseconds, and zero permanent memory
|
|
120
|
+
* Microseconds, and zero permanent memory - which is what makes it the right
|
|
121
121
|
* answer for a startup line (see `logAstCapabilityOnce`).
|
|
122
122
|
*
|
|
123
123
|
* It shares `resolveArtifacts` with the real loader, so it cannot report a
|
|
124
124
|
* grammar as vendored that `loadGrammar` would reject for a missing artifact.
|
|
125
125
|
* What it deliberately cannot see is the two failure modes that require the
|
|
126
|
-
* grammar in memory
|
|
126
|
+
* grammar in memory - `wasm_load_failed` and `query_compile_failed`. Those are
|
|
127
127
|
* reported by `astCapabilityReport` when a human asks, and warned once per
|
|
128
128
|
* language by the scan path on the first file that needs them
|
|
129
129
|
* (`grammar_unavailable` in codeScanner); paying ~75 MB up front to pre-answer
|
|
@@ -151,12 +151,12 @@ export declare function astArtifactReport(artifactDir?: string): {
|
|
|
151
151
|
* NOT free, and the cost is memory rather than only latency: measured on this
|
|
152
152
|
* checkout, ~690 ms and ~75 MB of RSS that is never given back. web-tree-sitter
|
|
153
153
|
* 0.26.11 exposes no `Language.delete` (see `attemptLoad`), so all 18 grammars
|
|
154
|
-
* stay resident for the life of the process
|
|
154
|
+
* stay resident for the life of the process - including the fifteen a given repo
|
|
155
155
|
* has no files for. Caching makes the second call free; it does not make the
|
|
156
156
|
* first one cheap.
|
|
157
157
|
*
|
|
158
158
|
* So: fine for a diagnostic a human asked for (`doctor`, a `--check` script,
|
|
159
|
-
* this suite). Wrong for a daemon's startup line
|
|
159
|
+
* this suite). Wrong for a daemon's startup line - that is `astArtifactReport`.
|
|
160
160
|
*/
|
|
161
161
|
export declare function astCapabilityReport(artifactDir?: string): Promise<{
|
|
162
162
|
available: AstLanguageId[];
|
package/dist/ast/grammars.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Every failure mode is a named value (`wasm_missing`, `wasm_load_failed`,
|
|
6
6
|
* `tags_query_missing`, `query_compile_failed`, `not_covered`) rather than a
|
|
7
7
|
* null or a throw, because the consequence of a degraded install is not a crash
|
|
8
|
-
*
|
|
8
|
+
* - it is quietly worse chunks, forever, with nothing in the logs. A caller that
|
|
9
9
|
* gets `unavailable` can fall back to the heuristic chunker AND say why.
|
|
10
10
|
*
|
|
11
11
|
* Artifacts are vendored, not installed: `packages/shared/wasm/<id>.wasm` plus
|
|
@@ -60,7 +60,7 @@ export const AST_LANGUAGE_IDS = AST_LANGUAGE_ID_LIST;
|
|
|
60
60
|
* Ids whose vendored artifact basename differs from the id.
|
|
61
61
|
*
|
|
62
62
|
* `tree-sitter-c-sharp` names its file with a hyphen while every consumer of
|
|
63
|
-
* this registry
|
|
63
|
+
* this registry - `languageForExtension`, chunk metadata, the wire - spells the
|
|
64
64
|
* language `csharp`. Mapping the two explicitly is cheaper than renaming a
|
|
65
65
|
* vendored artifact: the vendoring script, the committed files and the
|
|
66
66
|
* `--check` verifier all agree on `c-sharp`, and a rename would make this
|
|
@@ -75,7 +75,7 @@ export function grammarArtifactBasename(id) {
|
|
|
75
75
|
}
|
|
76
76
|
/**
|
|
77
77
|
* Ordered tag-query files composing each grammar's EFFECTIVE query. THE source
|
|
78
|
-
* of truth
|
|
78
|
+
* of truth - `scripts/vendor-grammars.ts` imports this rather than keeping its
|
|
79
79
|
* own copy, because two chains that can drift is precisely the defect this
|
|
80
80
|
* layer exists to remove.
|
|
81
81
|
*
|
|
@@ -84,7 +84,7 @@ export function grammarArtifactBasename(id) {
|
|
|
84
84
|
* `interface_declaration`, `abstract_class_declaration`);
|
|
85
85
|
* `function_declaration`, `class_declaration`, `method_definition` and arrow
|
|
86
86
|
* functions all live in javascript's query and are meant to be inherited.
|
|
87
|
-
* Nothing in the query engine resolves that
|
|
87
|
+
* Nothing in the query engine resolves that - composing the chain is the
|
|
88
88
|
* consumer's job.
|
|
89
89
|
*
|
|
90
90
|
* Measured cost of not composing it: 948 definitions across 1,037 TypeScript
|
|
@@ -119,7 +119,7 @@ export const QUERY_CHAIN = {
|
|
|
119
119
|
* Extensions whose grammar the language string alone gets WRONG.
|
|
120
120
|
*
|
|
121
121
|
* `.ts` and `.tsx` both report language `typescript` and need different
|
|
122
|
-
* grammars out of the same npm package
|
|
122
|
+
* grammars out of the same npm package - a `.tsx` file parsed by the typescript
|
|
123
123
|
* grammar errors on the first JSX element. This is the entire reason
|
|
124
124
|
* `resolveAstLanguage` takes an extension at all.
|
|
125
125
|
*/
|
|
@@ -165,7 +165,7 @@ const WASM_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'wasm
|
|
|
165
165
|
* in parallel forks, so renaming `ruby.wasm` aside is visible to every other
|
|
166
166
|
* file for as long as it lasts, and any file that cold-loads Ruby inside that
|
|
167
167
|
* window caches a `wasm_missing` this checkout does not have. Copy from here
|
|
168
|
-
* into a temp directory and break the copy
|
|
168
|
+
* into a temp directory and break the copy - `loadGrammar` takes the directory.
|
|
169
169
|
*/
|
|
170
170
|
export const VENDORED_ARTIFACT_DIR = WASM_DIR;
|
|
171
171
|
/**
|
|
@@ -184,7 +184,7 @@ export function resolveAstLanguage(extension, language) {
|
|
|
184
184
|
}
|
|
185
185
|
/**
|
|
186
186
|
* Accepts `.TSX`, `tsx`, or a whole path, and answers the lowercase dotted
|
|
187
|
-
* extension. Mirrors `languageForExtension`'s ordering
|
|
187
|
+
* extension. Mirrors `languageForExtension`'s ordering - `extname` first, so a
|
|
188
188
|
* dotfile carrying a real extension ('.eslintrc.js') is not swallowed whole.
|
|
189
189
|
*/
|
|
190
190
|
function normalizeExtension(raw) {
|
|
@@ -217,7 +217,7 @@ const loads = new Map();
|
|
|
217
217
|
/**
|
|
218
218
|
* Ids whose `Language` has actually been instantiated, same keying as `loads`.
|
|
219
219
|
*
|
|
220
|
-
*
|
|
220
|
+
* This is a permanent record rather than a cache index because entries cannot be removed:
|
|
221
221
|
* a loaded Language cannot be freed (see `attemptLoad`), so this set IS the
|
|
222
222
|
* permanent wasm memory this process is holding. `loadedGrammarIds` reads it,
|
|
223
223
|
* and the startup path is asserted against it.
|
|
@@ -244,7 +244,7 @@ export function loadGrammar(id, artifactDir = WASM_DIR) {
|
|
|
244
244
|
return pending;
|
|
245
245
|
}
|
|
246
246
|
/**
|
|
247
|
-
* Which grammars this process has instantiated
|
|
247
|
+
* Which grammars this process has instantiated - what is resident in wasm
|
|
248
248
|
* memory right now, not what is vendored or what was asked for.
|
|
249
249
|
*
|
|
250
250
|
* Exists because the cost is permanent and therefore worth being able to state:
|
|
@@ -319,7 +319,7 @@ async function attemptLoad(id, artifactDir) {
|
|
|
319
319
|
// A loaded Language cannot be freed: web-tree-sitter 0.26.11 exposes
|
|
320
320
|
// `delete()` on Tree and Query but NOT on Language. The failure results below
|
|
321
321
|
// are cached, so a grammar whose query is broken leaks its Language exactly
|
|
322
|
-
// once per process rather than once per file
|
|
322
|
+
// once per process rather than once per file - which is why the cache matters
|
|
323
323
|
// for more than latency. Trees are a different story and must be deleted per
|
|
324
324
|
// file by the chunker; the JS heap does not GC wasm memory.
|
|
325
325
|
let query;
|
|
@@ -338,7 +338,7 @@ async function attemptLoad(id, artifactDir) {
|
|
|
338
338
|
query.delete();
|
|
339
339
|
return {
|
|
340
340
|
unavailable: 'query_compile_failed',
|
|
341
|
-
detail: `${id} tag query [${QUERY_CHAIN[id].join(', ')}] compiled but captures no definition.*
|
|
341
|
+
detail: `${id} tag query [${QUERY_CHAIN[id].join(', ')}] compiled but captures no definition.* - it would name nothing`,
|
|
342
342
|
};
|
|
343
343
|
}
|
|
344
344
|
return { ok: { id, language, query } };
|
|
@@ -350,13 +350,13 @@ const describe = (err) => err instanceof Error ? err.message.slice(0, 200) || er
|
|
|
350
350
|
*
|
|
351
351
|
* Every check is a `statSync` plus a few hundred bytes of `.scm`: the grammar's
|
|
352
352
|
* `.wasm` is present and non-empty, and so is every tag-query file in its chain.
|
|
353
|
-
* Microseconds, and zero permanent memory
|
|
353
|
+
* Microseconds, and zero permanent memory - which is what makes it the right
|
|
354
354
|
* answer for a startup line (see `logAstCapabilityOnce`).
|
|
355
355
|
*
|
|
356
356
|
* It shares `resolveArtifacts` with the real loader, so it cannot report a
|
|
357
357
|
* grammar as vendored that `loadGrammar` would reject for a missing artifact.
|
|
358
358
|
* What it deliberately cannot see is the two failure modes that require the
|
|
359
|
-
* grammar in memory
|
|
359
|
+
* grammar in memory - `wasm_load_failed` and `query_compile_failed`. Those are
|
|
360
360
|
* reported by `astCapabilityReport` when a human asks, and warned once per
|
|
361
361
|
* language by the scan path on the first file that needs them
|
|
362
362
|
* (`grammar_unavailable` in codeScanner); paying ~75 MB up front to pre-answer
|
|
@@ -389,12 +389,12 @@ export function astArtifactReport(artifactDir = WASM_DIR) {
|
|
|
389
389
|
* NOT free, and the cost is memory rather than only latency: measured on this
|
|
390
390
|
* checkout, ~690 ms and ~75 MB of RSS that is never given back. web-tree-sitter
|
|
391
391
|
* 0.26.11 exposes no `Language.delete` (see `attemptLoad`), so all 18 grammars
|
|
392
|
-
* stay resident for the life of the process
|
|
392
|
+
* stay resident for the life of the process - including the fifteen a given repo
|
|
393
393
|
* has no files for. Caching makes the second call free; it does not make the
|
|
394
394
|
* first one cheap.
|
|
395
395
|
*
|
|
396
396
|
* So: fine for a diagnostic a human asked for (`doctor`, a `--check` script,
|
|
397
|
-
* this suite). Wrong for a daemon's startup line
|
|
397
|
+
* this suite). Wrong for a daemon's startup line - that is `astArtifactReport`.
|
|
398
398
|
*/
|
|
399
399
|
export async function astCapabilityReport(artifactDir = WASM_DIR) {
|
|
400
400
|
const available = [];
|