brainclaw 1.9.1 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -1
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli.js +18 -1
- package/dist/commands/code-map.js +129 -0
- package/dist/commands/codev.js +7 -0
- package/dist/commands/mcp.js +121 -0
- package/dist/commands/run-profile.js +3 -2
- package/dist/commands/switch.js +100 -89
- package/dist/core/agent-files.js +12 -0
- package/dist/core/code-map/backend.js +123 -0
- package/dist/core/code-map/core.js +81 -0
- package/dist/core/code-map/drafts.js +2 -0
- package/dist/core/code-map/extractor.js +29 -0
- package/dist/core/code-map/finalizer.js +191 -0
- package/dist/core/code-map/freshness.js +108 -0
- package/dist/core/code-map/ids.js +0 -0
- package/dist/core/code-map/importable.js +35 -0
- package/dist/core/code-map/indexes.js +197 -0
- package/dist/core/code-map/lang/java/imports.scm +17 -0
- package/dist/core/code-map/lang/java/index.js +254 -0
- package/dist/core/code-map/lang/java/tags.scm +48 -0
- package/dist/core/code-map/lang/php/imports.scm +21 -0
- package/dist/core/code-map/lang/php/index.js +251 -0
- package/dist/core/code-map/lang/php/tags.scm +44 -0
- package/dist/core/code-map/lang/provider.js +9 -0
- package/dist/core/code-map/lang/providers.js +24 -0
- package/dist/core/code-map/lang/python/imports.scm +90 -0
- package/dist/core/code-map/lang/python/index.js +364 -0
- package/dist/core/code-map/lang/python/tags.scm +81 -0
- package/dist/core/code-map/lang/query-runtime.js +374 -0
- package/dist/core/code-map/lang/registry.js +125 -0
- package/dist/core/code-map/lang/typescript/imports.scm +90 -0
- package/dist/core/code-map/lang/typescript/index.js +306 -0
- package/dist/core/code-map/lang/typescript/tags.js.scm +106 -0
- package/dist/core/code-map/lang/typescript/tags.scm +151 -0
- package/dist/core/code-map/lock.js +210 -0
- package/dist/core/code-map/materialized.js +51 -0
- package/dist/core/code-map/memory-reader.js +59 -0
- package/dist/core/code-map/paths.js +53 -0
- package/dist/core/code-map/query.js +568 -0
- package/dist/core/code-map/refresh.js +0 -0
- package/dist/core/code-map/resolve.js +177 -0
- package/dist/core/code-map/store.js +206 -0
- package/dist/core/code-map/types.js +288 -0
- package/dist/core/code-map/vocabulary.js +57 -0
- package/dist/core/code-map/wasm-loader.js +294 -0
- package/dist/core/code-map/work-section.js +206 -0
- package/dist/core/codev-rounds.js +4 -0
- package/dist/core/execution-adapters.js +11 -10
- package/dist/core/execution-profile.js +58 -0
- package/dist/core/facade-schema.js +9 -0
- package/dist/core/instruction-templates.js +2 -0
- package/dist/core/mcp-command-resolution.js +3 -1
- package/dist/core/store-resolution.js +41 -4
- package/dist/facts.js +9 -5
- package/dist/facts.json +8 -4
- package/dist/vendor/web-tree-sitter/tree-sitter.js +3980 -0
- package/dist/vendor/web-tree-sitter/tree-sitter.wasm +0 -0
- package/dist/wasm/tree-sitter-java.wasm +0 -0
- package/dist/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/wasm/tree-sitter-php.wasm +0 -0
- package/dist/wasm/tree-sitter-python.wasm +0 -0
- package/dist/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/wasm/tree-sitter.wasm +0 -0
- package/docs/cli.md +46 -8
- package/docs/code-map.md +198 -0
- package/docs/integrations/mcp.md +13 -6
- package/docs/mcp-schema-changelog.md +7 -3
- package/docs/quickstart.md +1 -1
- package/package.json +11 -6
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Map P1a — TypeScriptProvider (provider #1; spec §8).
|
|
3
|
+
*
|
|
4
|
+
* Owns `.js/.jsx/.ts/.tsx` (runtime langs javascript/typescript/tsx). `extractDraft`
|
|
5
|
+
* delegates to the generic query-runtime; `refine()` carries what tree-sitter
|
|
6
|
+
* queries CANNOT express:
|
|
7
|
+
* - React `component` (PascalCase name + a JSX-returning body) / `hook`
|
|
8
|
+
* (`/^use[A-Z0-9]/`) reclassification — needs a JSX-body walk (returnsJsx) on the
|
|
9
|
+
* in-memory source node.
|
|
10
|
+
* - `function` vs `variable` for lexical declarators: the query emits the
|
|
11
|
+
* structural `variable` subtype; a declarator whose value is a function/arrow is
|
|
12
|
+
* reclassified to `function` (then possibly component/hook), matching the legacy
|
|
13
|
+
* `classifySubtype`.
|
|
14
|
+
*
|
|
15
|
+
* Identity is owned by the CORE finalizer — this provider mints NO ids. The
|
|
16
|
+
* `.jsx → tsx` and `.js → javascript` resolution is explicit in `langForPath`.
|
|
17
|
+
*
|
|
18
|
+
* trp_5026812e: the shared `tags.scm` references TS-only node types and does NOT
|
|
19
|
+
* compile against the JAVASCRIPT grammar. This provider therefore serves a
|
|
20
|
+
* JS-compatible definition subset (`tags.js.scm`) for the `javascript` lang while
|
|
21
|
+
* using `tags.scm` for typescript/tsx. `imports.scm` compiles against all three.
|
|
22
|
+
*/
|
|
23
|
+
import crypto from 'node:crypto';
|
|
24
|
+
import fs from 'node:fs';
|
|
25
|
+
import path from 'node:path';
|
|
26
|
+
import { fileURLToPath } from 'node:url';
|
|
27
|
+
import { grammarHash, grammarName, loadGrammar } from '../../wasm-loader.js';
|
|
28
|
+
import { extractWithQueries } from '../query-runtime.js';
|
|
29
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
30
|
+
/** Resolve a vendored `.scm` next to this module (dist) or from the source tree. */
|
|
31
|
+
function readScm(basename) {
|
|
32
|
+
// Published / dist runtime: this module is dist/core/code-map/lang/typescript/
|
|
33
|
+
// index.js and the build copies the .scm assets alongside it
|
|
34
|
+
// (copy-code-map-wasm.mjs). Prefer that local copy.
|
|
35
|
+
const local = path.join(HERE, basename);
|
|
36
|
+
if (fs.existsSync(local))
|
|
37
|
+
return fs.readFileSync(local, 'utf-8');
|
|
38
|
+
// From-source / dist-test fallback: tsc emits to dist[-test]/... but does NOT
|
|
39
|
+
// copy .scm, so walk up to the repo root (the dir holding package.json) and read
|
|
40
|
+
// the curated asset from src/core/code-map/lang/typescript/.
|
|
41
|
+
let dir = HERE;
|
|
42
|
+
for (let i = 0; i < 12; i++) {
|
|
43
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
44
|
+
const fromSrc = path.join(dir, 'src', 'core', 'code-map', 'lang', 'typescript', basename);
|
|
45
|
+
if (fs.existsSync(fromSrc))
|
|
46
|
+
return fs.readFileSync(fromSrc, 'utf-8');
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
const parent = path.dirname(dir);
|
|
50
|
+
if (parent === dir)
|
|
51
|
+
break;
|
|
52
|
+
dir = parent;
|
|
53
|
+
}
|
|
54
|
+
throw new Error(`code-map: could not locate query asset ${basename} (from ${HERE})`);
|
|
55
|
+
}
|
|
56
|
+
function sha256(s) {
|
|
57
|
+
return `sha256:${crypto.createHash('sha256').update(s, 'utf-8').digest('hex')}`;
|
|
58
|
+
}
|
|
59
|
+
// Load the curated query assets once at module init. tags.scm = TS/TSX defs,
|
|
60
|
+
// tags.js.scm = JS-compatible def subset (trp_5026812e); imports.scm = all langs.
|
|
61
|
+
const TAGS_TS = readScm('tags.scm');
|
|
62
|
+
const TAGS_JS = readScm('tags.js.scm');
|
|
63
|
+
const IMPORTS = readScm('imports.scm');
|
|
64
|
+
const TAGS_TS_HASH = sha256(TAGS_TS);
|
|
65
|
+
const TAGS_JS_HASH = sha256(TAGS_JS);
|
|
66
|
+
const IMPORTS_HASH = sha256(IMPORTS);
|
|
67
|
+
/** The tags source + hash for a runtime lang (.js uses the JS subset). */
|
|
68
|
+
function tagsForLang(lang) {
|
|
69
|
+
if (lang === 'javascript')
|
|
70
|
+
return { source: TAGS_JS, hash: TAGS_JS_HASH };
|
|
71
|
+
return { source: TAGS_TS, hash: TAGS_TS_HASH };
|
|
72
|
+
}
|
|
73
|
+
const HOOK_RE = /^use[A-Z0-9]/;
|
|
74
|
+
const PASCAL_RE = /^[A-Z][A-Za-z0-9]*$/;
|
|
75
|
+
/** Walk to find the first descendant JSX node (mirrors legacy `returnsJsx`). */
|
|
76
|
+
function returnsJsx(node) {
|
|
77
|
+
const stack = [node];
|
|
78
|
+
let budget = 4000;
|
|
79
|
+
while (stack.length > 0 && budget-- > 0) {
|
|
80
|
+
const n = stack.pop();
|
|
81
|
+
const t = n.type;
|
|
82
|
+
if (t === 'jsx_element' || t === 'jsx_self_closing_element' || t === 'jsx_fragment')
|
|
83
|
+
return true;
|
|
84
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
85
|
+
const c = n.namedChild(i);
|
|
86
|
+
if (c)
|
|
87
|
+
stack.push(c);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
/** Mirror of legacy `classifySubtype` (extractor.ts). */
|
|
93
|
+
function classifySubtype(name, valueNode, isFunctionLike) {
|
|
94
|
+
if (HOOK_RE.test(name))
|
|
95
|
+
return 'hook';
|
|
96
|
+
if (isFunctionLike && PASCAL_RE.test(name) && valueNode && returnsJsx(valueNode))
|
|
97
|
+
return 'component';
|
|
98
|
+
return isFunctionLike ? 'function' : 'variable';
|
|
99
|
+
}
|
|
100
|
+
const parser = {
|
|
101
|
+
grammarForLang: (lang) => loadGrammar(lang),
|
|
102
|
+
grammarNameForLang: (lang) => grammarName(lang),
|
|
103
|
+
grammarHashForLang: (lang) => grammarHash(lang),
|
|
104
|
+
};
|
|
105
|
+
const queries = {
|
|
106
|
+
tags: {
|
|
107
|
+
name: 'tags',
|
|
108
|
+
sourceForLang: (lang) => tagsForLang(lang).source,
|
|
109
|
+
hashForLang: (lang) => tagsForLang(lang).hash,
|
|
110
|
+
},
|
|
111
|
+
imports: {
|
|
112
|
+
name: 'imports',
|
|
113
|
+
sourceForLang: () => IMPORTS,
|
|
114
|
+
hashForLang: () => IMPORTS_HASH,
|
|
115
|
+
},
|
|
116
|
+
// JS/TS import/export statement node types (cadrage §3 / Codex R1). Both are
|
|
117
|
+
// listed because local exports + re-exports (`export … from`) also resolve
|
|
118
|
+
// through the runtime's enclosingStatement walk. PROVIDER-LOCAL — the runtime
|
|
119
|
+
// gets this set per file, never from a registry. (Same set the old module-global
|
|
120
|
+
// carried for JS/TS, so output stays byte-identical.)
|
|
121
|
+
enclosingStatementNodeTypes: ['import_statement', 'export_statement'],
|
|
122
|
+
// P1b §3.4: the runtime drives capture→draft mapping off the HARD-CODED
|
|
123
|
+
// capture-name convention (query-runtime.ts) — that convention IS the contract.
|
|
124
|
+
// This captureMap is a declared MIRROR of it, validated against the convention
|
|
125
|
+
// by `assertCaptureMapConforms` (provider-oracle test). Every entry's `capture`
|
|
126
|
+
// MUST be a convention-recognized role; it cannot invent new capture roles.
|
|
127
|
+
captureMap: [
|
|
128
|
+
{ capture: 'definition.function.node', field: 'node', subtype: 'function' },
|
|
129
|
+
{ capture: 'definition.function.name', field: 'name' },
|
|
130
|
+
{ capture: 'definition.function.exported', field: 'exported', optional: true },
|
|
131
|
+
{ capture: 'definition.class.node', field: 'node', subtype: 'class' },
|
|
132
|
+
{ capture: 'definition.class.name', field: 'name' },
|
|
133
|
+
{ capture: 'definition.class.exported', field: 'exported', optional: true },
|
|
134
|
+
{ capture: 'definition.type.node', field: 'node', subtype: 'type' },
|
|
135
|
+
{ capture: 'definition.type.name', field: 'name' },
|
|
136
|
+
{ capture: 'definition.type.exported', field: 'exported', optional: true },
|
|
137
|
+
{ capture: 'definition.interface.node', field: 'node', subtype: 'interface' },
|
|
138
|
+
{ capture: 'definition.interface.name', field: 'name' },
|
|
139
|
+
{ capture: 'definition.interface.exported', field: 'exported', optional: true },
|
|
140
|
+
{ capture: 'definition.variable.node', field: 'node', subtype: 'variable' },
|
|
141
|
+
{ capture: 'definition.variable.name', field: 'name' },
|
|
142
|
+
{ capture: 'definition.variable.exported', field: 'exported', optional: true },
|
|
143
|
+
{ capture: 'import.source', field: 'source' },
|
|
144
|
+
{ capture: 'import.default.name', field: 'imported', optional: true },
|
|
145
|
+
{ capture: 'import.namespace.name', field: 'imported', optional: true },
|
|
146
|
+
{ capture: 'import.named.name', field: 'imported', optional: true },
|
|
147
|
+
{ capture: 'export.name', field: 'name', optional: true },
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
const vocabulary = {
|
|
151
|
+
nodeSubtypes: ['function', 'class', 'type', 'interface', 'variable', 'component', 'hook', 'export'],
|
|
152
|
+
edgeKinds: ['contains', 'defines', 'imports', 'exports'],
|
|
153
|
+
captureMap: queries.captureMap,
|
|
154
|
+
};
|
|
155
|
+
const capabilities = {
|
|
156
|
+
tiers: ['T1.definitions', 'T2.imports', 'T3.import_resolution'],
|
|
157
|
+
proven: {
|
|
158
|
+
'T1.definitions': true,
|
|
159
|
+
'T2.imports': true,
|
|
160
|
+
'T3.import_resolution': true, // P1c file-level: relative specifiers, intra-project
|
|
161
|
+
'T4.tests_for': false,
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
/** Extensions tried (in order) when resolving an extensionless relative specifier. */
|
|
165
|
+
const TS_RESOLVE_EXTS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs'];
|
|
166
|
+
/** JS-family extensions a written specifier may use for a TS source file (ESM `./x.js` → `x.ts`). */
|
|
167
|
+
const JS_LIKE_EXTS = new Set(['.js', '.jsx', '.mjs', '.cjs']);
|
|
168
|
+
/**
|
|
169
|
+
* P1c file-level resolution (relative specifiers only). Given `./x` / `../x`
|
|
170
|
+
* resolved against the importer dir, try in order: the exact path (if it carries
|
|
171
|
+
* an extension), the TS-source siblings of a JS-family extension (ESM convention:
|
|
172
|
+
* `./b.js` may mean `b.ts`/`b.tsx`), the extensionless candidate + each known
|
|
173
|
+
* extension, then `<candidate>/index.<ext>`. Return the FIRST that is an indexed
|
|
174
|
+
* file. Bare/external specifiers (`react`, `@scope/x`) → no resolution (no edge).
|
|
175
|
+
*/
|
|
176
|
+
function resolveTsImport(spec, fromPath, ctx) {
|
|
177
|
+
if (!spec.startsWith('./') && !spec.startsWith('../'))
|
|
178
|
+
return null; // external/bare → no edge
|
|
179
|
+
const base = path.posix.join(path.posix.dirname(fromPath), spec); // normalized project-relative
|
|
180
|
+
const ext = path.posix.extname(base);
|
|
181
|
+
const candidates = [];
|
|
182
|
+
if (ext) {
|
|
183
|
+
candidates.push(base);
|
|
184
|
+
if (JS_LIKE_EXTS.has(ext)) {
|
|
185
|
+
const noExt = base.slice(0, -ext.length);
|
|
186
|
+
candidates.push(`${noExt}.ts`, `${noExt}.tsx`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
for (const e of TS_RESOLVE_EXTS)
|
|
191
|
+
candidates.push(`${base}${e}`);
|
|
192
|
+
for (const e of TS_RESOLVE_EXTS)
|
|
193
|
+
candidates.push(`${base}/index${e}`);
|
|
194
|
+
}
|
|
195
|
+
for (const c of candidates) {
|
|
196
|
+
if (ctx.fileExists(c))
|
|
197
|
+
return c;
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
function isDefSourceNode(v) {
|
|
202
|
+
return (typeof v === 'object' &&
|
|
203
|
+
v !== null &&
|
|
204
|
+
'node' in v &&
|
|
205
|
+
'nameNode' in v &&
|
|
206
|
+
typeof v.node === 'object');
|
|
207
|
+
}
|
|
208
|
+
/** Resolve a declarator's `value` field from its name node (best-effort). */
|
|
209
|
+
function declaratorValue(nameNode) {
|
|
210
|
+
const declarator = nameNode.parent;
|
|
211
|
+
if (!declarator)
|
|
212
|
+
return null;
|
|
213
|
+
try {
|
|
214
|
+
return declarator.childForFieldName('value');
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
const FN_VALUE_TYPES = new Set(['arrow_function', 'function_expression', 'function']);
|
|
221
|
+
export class TypeScriptProvider {
|
|
222
|
+
id = 'js-ts';
|
|
223
|
+
displayName = 'JavaScript / TypeScript';
|
|
224
|
+
languages = ['javascript', 'typescript', 'tsx'];
|
|
225
|
+
extensions = ['.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs'];
|
|
226
|
+
priority = 0;
|
|
227
|
+
version = '0.1.0';
|
|
228
|
+
parser = parser;
|
|
229
|
+
queries = queries;
|
|
230
|
+
vocabulary = vocabulary;
|
|
231
|
+
capabilities = capabilities;
|
|
232
|
+
/** `.jsx → tsx`, `.js/.mjs/.cjs → javascript`, `.tsx → tsx`, `.ts → typescript`. */
|
|
233
|
+
langForPath(p) {
|
|
234
|
+
const ext = path.extname(p).toLowerCase();
|
|
235
|
+
switch (ext) {
|
|
236
|
+
case '.ts':
|
|
237
|
+
return 'typescript';
|
|
238
|
+
case '.tsx':
|
|
239
|
+
return 'tsx';
|
|
240
|
+
case '.jsx':
|
|
241
|
+
return 'tsx'; // tsx grammar handles jsx (mirrors legacy langForExtension)
|
|
242
|
+
case '.js':
|
|
243
|
+
case '.mjs':
|
|
244
|
+
case '.cjs':
|
|
245
|
+
return 'javascript';
|
|
246
|
+
default:
|
|
247
|
+
return 'typescript';
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async extractDraft(input, _services) {
|
|
251
|
+
const tags = tagsForLang(input.lang);
|
|
252
|
+
return extractWithQueries({
|
|
253
|
+
providerId: this.id,
|
|
254
|
+
lang: input.lang,
|
|
255
|
+
source: input.source,
|
|
256
|
+
sizeBytes: input.sizeBytes,
|
|
257
|
+
maxParseFileBytes: input.maxParseFileBytes,
|
|
258
|
+
maxQueryWaitMs: input.maxQueryWaitMs,
|
|
259
|
+
path: input.path,
|
|
260
|
+
grammarForLang: this.parser.grammarForLang,
|
|
261
|
+
tagsSource: tags.source,
|
|
262
|
+
tagsHash: tags.hash,
|
|
263
|
+
importsSource: IMPORTS,
|
|
264
|
+
importsHash: IMPORTS_HASH,
|
|
265
|
+
enclosingStatementNodeTypes: queries.enclosingStatementNodeTypes,
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Reclassify definition subtypes the structural query cannot: function/arrow
|
|
270
|
+
* declarators → function/component/hook; non-fn declarators with a `use*` name →
|
|
271
|
+
* hook. Mirrors the legacy `classifySubtype` decisions exactly. Drafts-only.
|
|
272
|
+
*/
|
|
273
|
+
refine(draft, _ctx) {
|
|
274
|
+
const definitions = draft.definitions.map((d) => {
|
|
275
|
+
// Only function-declaration + variable drafts are reclassified (classes,
|
|
276
|
+
// types, interfaces keep their fixed subtype — legacy never reclassifies them).
|
|
277
|
+
const src = isDefSourceNode(d.sourceNode) ? d.sourceNode : null;
|
|
278
|
+
if (d.subtype === 'function') {
|
|
279
|
+
// function declaration: classifySubtype(name, node, isFunctionLike=true).
|
|
280
|
+
const valueNode = src ? src.node : null;
|
|
281
|
+
const subtype = classifySubtype(d.name, valueNode, true);
|
|
282
|
+
return subtype === d.subtype ? d : { ...d, subtype };
|
|
283
|
+
}
|
|
284
|
+
if (d.subtype === 'variable') {
|
|
285
|
+
const value = src ? declaratorValue(src.nameNode) : null;
|
|
286
|
+
const isFnLike = !!value && FN_VALUE_TYPES.has(value.type);
|
|
287
|
+
const subtype = classifySubtype(d.name, value, isFnLike);
|
|
288
|
+
return subtype === d.subtype ? d : { ...d, subtype };
|
|
289
|
+
}
|
|
290
|
+
return d;
|
|
291
|
+
});
|
|
292
|
+
return { ...draft, definitions };
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* P1c file-level import resolution (intra-project, relative specifiers). Returns
|
|
296
|
+
* paths only — the core mints the `resolves_to` edge + target file id. Bare/
|
|
297
|
+
* external specifiers resolve to nothing (no edge). Confidence 1.0 (exact file).
|
|
298
|
+
*/
|
|
299
|
+
async resolveImport(req, ctx) {
|
|
300
|
+
const resolved = resolveTsImport(req.source, req.fromPath, ctx);
|
|
301
|
+
return resolved ? [{ source: req.source, resolvedPath: resolved, confidence: 1.0 }] : [];
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
/** Singleton instance for registry wiring. */
|
|
305
|
+
export const typeScriptProvider = new TypeScriptProvider();
|
|
306
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
; Brainclaw Code Map — JAVASCRIPT-grammar DEFINITIONS query (curated subset of tags.scm).
|
|
2
|
+
;
|
|
3
|
+
; The shared tags.scm references TypeScript-ONLY node types
|
|
4
|
+
; (type_alias_declaration, interface_declaration, type_identifier) which the
|
|
5
|
+
; tree-sitter JAVASCRIPT grammar rejects ("Bad node name 'type_identifier'").
|
|
6
|
+
; This file is the JS-compatible subset (trp_5026812e): it drops type/interface
|
|
7
|
+
; entirely (JS has none) and resolves a class name via `identifier` (the JS
|
|
8
|
+
; grammar names classes with `identifier`, not `type_identifier`).
|
|
9
|
+
;
|
|
10
|
+
; Capture convention + span semantics are IDENTICAL to tags.scm:
|
|
11
|
+
; @definition.<subtype>.node -> DefinitionDraft.span (enclosing declaration
|
|
12
|
+
; statement — every declarator in `const a=1,b=2`
|
|
13
|
+
; shares it)
|
|
14
|
+
; @definition.<subtype>.name -> DefinitionDraft.name
|
|
15
|
+
; @definition.<subtype>.exported -> presence marks DefinitionDraft.exported = true
|
|
16
|
+
;
|
|
17
|
+
; Subtypes captured here: function | class | variable. (component / hook
|
|
18
|
+
; reclassification happens in the provider's refine() pass.)
|
|
19
|
+
|
|
20
|
+
; ---------------------------------------------------------------------------
|
|
21
|
+
; function declarations (function foo() {}, function* gen() {})
|
|
22
|
+
; ---------------------------------------------------------------------------
|
|
23
|
+
(program
|
|
24
|
+
(function_declaration
|
|
25
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
26
|
+
|
|
27
|
+
(program
|
|
28
|
+
(generator_function_declaration
|
|
29
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
30
|
+
|
|
31
|
+
(program
|
|
32
|
+
(export_statement
|
|
33
|
+
(function_declaration
|
|
34
|
+
name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
|
|
35
|
+
|
|
36
|
+
(program
|
|
37
|
+
(export_statement
|
|
38
|
+
(generator_function_declaration
|
|
39
|
+
name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
|
|
40
|
+
|
|
41
|
+
; ---------------------------------------------------------------------------
|
|
42
|
+
; class declarations (class Foo {}) — JS names the class with `identifier`.
|
|
43
|
+
; ---------------------------------------------------------------------------
|
|
44
|
+
(program
|
|
45
|
+
(class_declaration
|
|
46
|
+
name: (identifier) @definition.class.name) @definition.class.node)
|
|
47
|
+
|
|
48
|
+
(program
|
|
49
|
+
(export_statement
|
|
50
|
+
(class_declaration
|
|
51
|
+
name: (identifier) @definition.class.name) @definition.class.node) @definition.class.exported)
|
|
52
|
+
|
|
53
|
+
; ---------------------------------------------------------------------------
|
|
54
|
+
; lexical / variable declarations (const a = 1, b = 2; let x; var y = () => {})
|
|
55
|
+
; One match per declarator (one per identifier name); the enclosing statement is
|
|
56
|
+
; the shared legacy identity span.
|
|
57
|
+
; ---------------------------------------------------------------------------
|
|
58
|
+
(program
|
|
59
|
+
(lexical_declaration
|
|
60
|
+
(variable_declarator
|
|
61
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
62
|
+
|
|
63
|
+
(program
|
|
64
|
+
(variable_declaration
|
|
65
|
+
(variable_declarator
|
|
66
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
67
|
+
|
|
68
|
+
(program
|
|
69
|
+
(export_statement
|
|
70
|
+
(lexical_declaration
|
|
71
|
+
(variable_declarator
|
|
72
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
|
|
73
|
+
|
|
74
|
+
(program
|
|
75
|
+
(export_statement
|
|
76
|
+
(variable_declaration
|
|
77
|
+
(variable_declarator
|
|
78
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
|
|
79
|
+
|
|
80
|
+
; ---------------------------------------------------------------------------
|
|
81
|
+
; ERROR-root recovery (legacy parity). See tags.scm for the rationale: when the
|
|
82
|
+
; file promotes to an `ERROR` root the declarations recover as direct children;
|
|
83
|
+
; the legacy extractor captured them via `root.namedChild(i)`. JS subset: no
|
|
84
|
+
; type/interface; class names resolve via `identifier`.
|
|
85
|
+
; ---------------------------------------------------------------------------
|
|
86
|
+
(ERROR
|
|
87
|
+
(function_declaration
|
|
88
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
89
|
+
|
|
90
|
+
(ERROR
|
|
91
|
+
(generator_function_declaration
|
|
92
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
93
|
+
|
|
94
|
+
(ERROR
|
|
95
|
+
(class_declaration
|
|
96
|
+
name: (identifier) @definition.class.name) @definition.class.node)
|
|
97
|
+
|
|
98
|
+
(ERROR
|
|
99
|
+
(lexical_declaration
|
|
100
|
+
(variable_declarator
|
|
101
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
102
|
+
|
|
103
|
+
(ERROR
|
|
104
|
+
(variable_declaration
|
|
105
|
+
(variable_declarator
|
|
106
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
; Brainclaw Code Map — TypeScript/TSX/JavaScript DEFINITIONS query (curated, vendored).
|
|
2
|
+
; See ./README.md for the capture-name convention and provenance.
|
|
3
|
+
;
|
|
4
|
+
; Emits one logical definition per top-level declaration. The query-runtime maps:
|
|
5
|
+
; @definition.<subtype>.node -> DefinitionDraft.span (the LEGACY IDENTITY span:
|
|
6
|
+
; the enclosing declaration statement, NOT the
|
|
7
|
+
; declarator/identifier — every declarator in
|
|
8
|
+
; `const a = 1, b = 2` shares this statement span)
|
|
9
|
+
; @definition.<subtype>.name -> DefinitionDraft.name (identifier text)
|
|
10
|
+
; @definition.<subtype>.exported -> presence marks DefinitionDraft.exported = true
|
|
11
|
+
;
|
|
12
|
+
; Subtypes captured here: function | class | type | interface | variable.
|
|
13
|
+
; (component / hook reclassification of function/variable subtypes happens in the
|
|
14
|
+
; provider's refine() pass via PascalCase + returnsJsx / /^use[A-Z0-9]/ — queries
|
|
15
|
+
; cannot perform JSX-body inspection, so this asset emits the structural subtype only.)
|
|
16
|
+
;
|
|
17
|
+
; Scope = TOP-LEVEL declarations only (P1a parity: no methods, no nested defs). Each
|
|
18
|
+
; pattern is anchored to a child of the `program` root, either directly or inside an
|
|
19
|
+
; `export_statement`. The unexported and exported forms are listed as sibling
|
|
20
|
+
; alternatives so an exported declaration carries the @definition.*.exported marker.
|
|
21
|
+
|
|
22
|
+
; ---------------------------------------------------------------------------
|
|
23
|
+
; function declarations (function foo() {}, function* gen() {})
|
|
24
|
+
; ---------------------------------------------------------------------------
|
|
25
|
+
(program
|
|
26
|
+
(function_declaration
|
|
27
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
28
|
+
|
|
29
|
+
(program
|
|
30
|
+
(generator_function_declaration
|
|
31
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
32
|
+
|
|
33
|
+
(program
|
|
34
|
+
(export_statement
|
|
35
|
+
(function_declaration
|
|
36
|
+
name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
|
|
37
|
+
|
|
38
|
+
(program
|
|
39
|
+
(export_statement
|
|
40
|
+
(generator_function_declaration
|
|
41
|
+
name: (identifier) @definition.function.name) @definition.function.node) @definition.function.exported)
|
|
42
|
+
|
|
43
|
+
; ---------------------------------------------------------------------------
|
|
44
|
+
; class declarations (class Foo {})
|
|
45
|
+
; ---------------------------------------------------------------------------
|
|
46
|
+
(program
|
|
47
|
+
(class_declaration
|
|
48
|
+
name: (type_identifier) @definition.class.name) @definition.class.node)
|
|
49
|
+
|
|
50
|
+
(program
|
|
51
|
+
(export_statement
|
|
52
|
+
(class_declaration
|
|
53
|
+
name: (type_identifier) @definition.class.name) @definition.class.node) @definition.class.exported)
|
|
54
|
+
|
|
55
|
+
; ---------------------------------------------------------------------------
|
|
56
|
+
; type aliases (type Foo = ...)
|
|
57
|
+
; ---------------------------------------------------------------------------
|
|
58
|
+
(program
|
|
59
|
+
(type_alias_declaration
|
|
60
|
+
name: (type_identifier) @definition.type.name) @definition.type.node)
|
|
61
|
+
|
|
62
|
+
(program
|
|
63
|
+
(export_statement
|
|
64
|
+
(type_alias_declaration
|
|
65
|
+
name: (type_identifier) @definition.type.name) @definition.type.node) @definition.type.exported)
|
|
66
|
+
|
|
67
|
+
; ---------------------------------------------------------------------------
|
|
68
|
+
; interfaces (interface Foo {})
|
|
69
|
+
; ---------------------------------------------------------------------------
|
|
70
|
+
(program
|
|
71
|
+
(interface_declaration
|
|
72
|
+
name: (type_identifier) @definition.interface.name) @definition.interface.node)
|
|
73
|
+
|
|
74
|
+
(program
|
|
75
|
+
(export_statement
|
|
76
|
+
(interface_declaration
|
|
77
|
+
name: (type_identifier) @definition.interface.name) @definition.interface.node) @definition.interface.exported)
|
|
78
|
+
|
|
79
|
+
; ---------------------------------------------------------------------------
|
|
80
|
+
; lexical / variable declarations (const a = 1, b = 2; let x; var y = () => {})
|
|
81
|
+
;
|
|
82
|
+
; The @definition.variable.node capture is the ENCLOSING statement (lexical_declaration
|
|
83
|
+
; / variable_declaration), so every declarator in a multi-declarator statement shares
|
|
84
|
+
; the same legacy identity span. One match is produced per declarator (one per
|
|
85
|
+
; identifier name); the runtime de-dupes node-handle reuse via the per-declarator name.
|
|
86
|
+
; Only simple `identifier` declarator names are captured (parity: object/array
|
|
87
|
+
; destructuring patterns are not emitted as symbols by the legacy extractor).
|
|
88
|
+
; ---------------------------------------------------------------------------
|
|
89
|
+
(program
|
|
90
|
+
(lexical_declaration
|
|
91
|
+
(variable_declarator
|
|
92
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
93
|
+
|
|
94
|
+
(program
|
|
95
|
+
(variable_declaration
|
|
96
|
+
(variable_declarator
|
|
97
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
98
|
+
|
|
99
|
+
(program
|
|
100
|
+
(export_statement
|
|
101
|
+
(lexical_declaration
|
|
102
|
+
(variable_declarator
|
|
103
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
|
|
104
|
+
|
|
105
|
+
(program
|
|
106
|
+
(export_statement
|
|
107
|
+
(variable_declaration
|
|
108
|
+
(variable_declarator
|
|
109
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node) @definition.variable.exported)
|
|
110
|
+
|
|
111
|
+
; ---------------------------------------------------------------------------
|
|
112
|
+
; ERROR-root recovery (legacy parity).
|
|
113
|
+
;
|
|
114
|
+
; When tree-sitter cannot parse a file cleanly it may promote the WHOLE file to
|
|
115
|
+
; an `ERROR` root rather than `program`, while still recovering the individual
|
|
116
|
+
; top-level declarations as direct children of that ERROR node. The legacy
|
|
117
|
+
; extractor walked `root.namedChild(i)` regardless of the root's type, so it
|
|
118
|
+
; captured those declarations; an anchor on `(program ...)` alone silently drops
|
|
119
|
+
; EVERY symbol in such a file. These sibling patterns mirror the `(program ...)`
|
|
120
|
+
; forms under an `(ERROR ...)` root so content parity holds for files that only
|
|
121
|
+
; parse under error recovery (e.g. test files the TS grammar trips on).
|
|
122
|
+
; ---------------------------------------------------------------------------
|
|
123
|
+
(ERROR
|
|
124
|
+
(function_declaration
|
|
125
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
126
|
+
|
|
127
|
+
(ERROR
|
|
128
|
+
(generator_function_declaration
|
|
129
|
+
name: (identifier) @definition.function.name) @definition.function.node)
|
|
130
|
+
|
|
131
|
+
(ERROR
|
|
132
|
+
(class_declaration
|
|
133
|
+
name: (type_identifier) @definition.class.name) @definition.class.node)
|
|
134
|
+
|
|
135
|
+
(ERROR
|
|
136
|
+
(type_alias_declaration
|
|
137
|
+
name: (type_identifier) @definition.type.name) @definition.type.node)
|
|
138
|
+
|
|
139
|
+
(ERROR
|
|
140
|
+
(interface_declaration
|
|
141
|
+
name: (type_identifier) @definition.interface.name) @definition.interface.node)
|
|
142
|
+
|
|
143
|
+
(ERROR
|
|
144
|
+
(lexical_declaration
|
|
145
|
+
(variable_declarator
|
|
146
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|
|
147
|
+
|
|
148
|
+
(ERROR
|
|
149
|
+
(variable_declaration
|
|
150
|
+
(variable_declarator
|
|
151
|
+
name: (identifier) @definition.variable.name)) @definition.variable.node)
|