brainclaw 1.16.0 → 1.18.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 +22 -8
- package/dist/brainclaw-vscode.vsix +0 -0
- package/dist/cli/register-review.js +2 -2
- package/dist/commands/code-map.js +4 -1
- package/dist/commands/codev.js +61 -30
- package/dist/commands/doctor.js +14 -1
- package/dist/commands/harvest.js +241 -25
- package/dist/commands/inbox.js +10 -4
- package/dist/commands/loop.js +2 -2
- package/dist/commands/loops-handlers.js +82 -1
- package/dist/commands/mcp-catalog.js +12 -4
- package/dist/commands/mcp-read-handlers.js +90 -7
- package/dist/commands/mcp-schemas.generated.js +3 -0
- package/dist/commands/mcp-write-coordination.js +159 -40
- package/dist/commands/mcp.js +11 -2
- package/dist/core/agent-capability.js +7 -2
- package/dist/core/agent-files.js +53 -2
- package/dist/core/agent-integrations.js +1 -0
- package/dist/core/agentrun-reconciler.js +171 -7
- package/dist/core/agentruns.js +6 -1
- package/dist/core/code-map/aggregate.js +473 -0
- package/dist/core/code-map/backend.js +36 -10
- package/dist/core/code-map/freshness.js +36 -1
- package/dist/core/code-map/lang/c/imports.scm +12 -0
- package/dist/core/code-map/lang/c/index.js +150 -0
- package/dist/core/code-map/lang/c/tags.scm +68 -0
- package/dist/core/code-map/lang/cpp/imports.scm +14 -0
- package/dist/core/code-map/lang/cpp/index.js +149 -0
- package/dist/core/code-map/lang/cpp/tags.scm +87 -0
- package/dist/core/code-map/lang/csharp/imports.scm +20 -0
- package/dist/core/code-map/lang/csharp/index.js +224 -0
- package/dist/core/code-map/lang/csharp/tags.scm +63 -0
- package/dist/core/code-map/lang/go/imports.scm +13 -0
- package/dist/core/code-map/lang/go/index.js +139 -0
- package/dist/core/code-map/lang/go/tags.scm +36 -0
- package/dist/core/code-map/lang/providers.js +12 -1
- package/dist/core/code-map/lang/ruby/imports.scm +24 -0
- package/dist/core/code-map/lang/ruby/index.js +198 -0
- package/dist/core/code-map/lang/ruby/tags.scm +49 -0
- package/dist/core/code-map/lang/rust/imports.scm +44 -0
- package/dist/core/code-map/lang/rust/index.js +136 -0
- package/dist/core/code-map/lang/rust/tags.scm +47 -0
- package/dist/core/code-map/query.js +229 -80
- package/dist/core/code-map/types.js +18 -0
- package/dist/core/code-map/work-section.js +8 -7
- package/dist/core/codev-responses.js +16 -0
- package/dist/core/dispatcher.js +209 -29
- package/dist/core/execution-adapters.js +29 -3
- package/dist/core/ideation-loop-close.js +124 -0
- package/dist/core/loops/artifact-resolver.js +197 -0
- package/dist/core/loops/attempt-reservation.js +576 -0
- package/dist/core/loops/commit-intent.js +494 -0
- package/dist/core/loops/facade-schema.js +48 -0
- package/dist/core/loops/impl-bind.js +144 -0
- package/dist/core/loops/index.js +1 -1
- package/dist/core/loops/iteration-engine.js +29 -0
- package/dist/core/loops/lock.js +14 -0
- package/dist/core/loops/project-resolution.js +157 -0
- package/dist/core/loops/reconcile-turn.js +369 -0
- package/dist/core/loops/result-reducers.js +88 -0
- package/dist/core/loops/store.js +46 -7
- package/dist/core/loops/types.js +139 -11
- package/dist/core/loops/verbs.js +9 -3
- package/dist/core/loops/verify-command.js +209 -0
- package/dist/core/messaging.js +58 -5
- package/dist/core/review-loop-close.js +106 -34
- package/dist/core/review-loop-turn-dispatch.js +445 -0
- package/dist/core/runtime-signals.js +68 -0
- package/dist/core/schema.js +34 -0
- package/dist/core/worktree.js +240 -22
- package/dist/facts.js +10 -10
- package/dist/facts.json +9 -9
- package/dist/wasm/tree-sitter-c.wasm +0 -0
- package/dist/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/wasm/tree-sitter-cpp.wasm +0 -0
- package/dist/wasm/tree-sitter-go.wasm +0 -0
- package/dist/wasm/tree-sitter-ruby.wasm +0 -0
- package/dist/wasm/tree-sitter-rust.wasm +0 -0
- package/docs/cli.md +1 -1
- package/docs/code-map.md +22 -6
- package/docs/concepts/loop-engine.md +28 -2
- package/docs/concepts/observer-protocol.md +22 -0
- package/docs/integrations/codex.md +19 -3
- package/docs/mcp-schema-changelog.md +43 -1
- package/package.json +1 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Map langs batch 2 — CSharpProvider (provider #6).
|
|
3
|
+
*
|
|
4
|
+
* Owns `.cs` (runtime lang `csharp`). `extractDraft` delegates to the generic
|
|
5
|
+
* query-runtime; the curated `tags.scm`/`imports.scm` (this dir) drive extraction.
|
|
6
|
+
* All definition subtypes are fixed by the query (no def reclassification). C# is
|
|
7
|
+
* very Java-like, so this mirrors JavaProvider — but the import shaping is simpler:
|
|
8
|
+
* C# module specifiers are dotted names (qualified_name), NOT string literals, so
|
|
9
|
+
* there is nothing to quote-strip, and there is no wildcard using and no
|
|
10
|
+
* member-split static import. `refine()` carries ONLY what the structural query
|
|
11
|
+
* cannot express: the ALIAS binding of `using X = A.B;` (the module `A.B` is already
|
|
12
|
+
* captured; the alias `X` lives in a sibling `name_equals` node → lift it onto the
|
|
13
|
+
* module's imported names). `using static A.B.C;` needs no refine — the base query
|
|
14
|
+
* already captures the qualified type `A.B.C` as the module source.
|
|
15
|
+
*
|
|
16
|
+
* NO exports edges — C# has no export statement (visibility is modifiers;
|
|
17
|
+
* capabilities: T2 = imports). Identity is owned by the CORE finalizer — this
|
|
18
|
+
* provider mints NO ids. The grammar loads through the SHARED engine glue
|
|
19
|
+
* (`loadGrammarWasm`), never a fresh `web-tree-sitter` import (trp_8df65ab7).
|
|
20
|
+
*/
|
|
21
|
+
import crypto from 'node:crypto';
|
|
22
|
+
import fs from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import { fileURLToPath } from 'node:url';
|
|
25
|
+
import { loadGrammarWasm, grammarHashForWasm } from '../../wasm-loader.js';
|
|
26
|
+
import { extractWithQueries } from '../query-runtime.js';
|
|
27
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
/** The C# grammar .wasm: dist basename + node_modules devDep fallback spec. */
|
|
29
|
+
const CSHARP_WASM_BASENAME = 'tree-sitter-c_sharp.wasm';
|
|
30
|
+
const CSHARP_WASM_NODE_MODULES_SPEC = 'tree-sitter-wasms/out/tree-sitter-c_sharp.wasm';
|
|
31
|
+
const CSHARP_GRAMMAR_NAME = 'tree-sitter-c_sharp';
|
|
32
|
+
/** Resolve a vendored `.scm` next to this module (dist) or from the source tree. */
|
|
33
|
+
function readScm(basename) {
|
|
34
|
+
const local = path.join(HERE, basename);
|
|
35
|
+
if (fs.existsSync(local))
|
|
36
|
+
return fs.readFileSync(local, 'utf-8');
|
|
37
|
+
let dir = HERE;
|
|
38
|
+
for (let i = 0; i < 12; i++) {
|
|
39
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
40
|
+
const fromSrc = path.join(dir, 'src', 'core', 'code-map', 'lang', 'csharp', basename);
|
|
41
|
+
if (fs.existsSync(fromSrc))
|
|
42
|
+
return fs.readFileSync(fromSrc, 'utf-8');
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
const parent = path.dirname(dir);
|
|
46
|
+
if (parent === dir)
|
|
47
|
+
break;
|
|
48
|
+
dir = parent;
|
|
49
|
+
}
|
|
50
|
+
throw new Error(`code-map: could not locate query asset ${basename} (from ${HERE})`);
|
|
51
|
+
}
|
|
52
|
+
function sha256(s) {
|
|
53
|
+
return `sha256:${crypto.createHash('sha256').update(s, 'utf-8').digest('hex')}`;
|
|
54
|
+
}
|
|
55
|
+
const TAGS = readScm('tags.scm');
|
|
56
|
+
const IMPORTS = readScm('imports.scm');
|
|
57
|
+
const TAGS_HASH = sha256(TAGS);
|
|
58
|
+
const IMPORTS_HASH = sha256(IMPORTS);
|
|
59
|
+
const parser = {
|
|
60
|
+
grammarForLang: () => loadGrammarWasm(CSHARP_WASM_BASENAME, CSHARP_WASM_NODE_MODULES_SPEC),
|
|
61
|
+
grammarNameForLang: () => CSHARP_GRAMMAR_NAME,
|
|
62
|
+
grammarHashForLang: () => grammarHashForWasm(CSHARP_WASM_BASENAME, CSHARP_WASM_NODE_MODULES_SPEC),
|
|
63
|
+
};
|
|
64
|
+
const queries = {
|
|
65
|
+
tags: { name: 'tags', sourceForLang: () => TAGS, hashForLang: () => TAGS_HASH },
|
|
66
|
+
imports: { name: 'imports', sourceForLang: () => IMPORTS, hashForLang: () => IMPORTS_HASH },
|
|
67
|
+
// C# using directives are the import statement; C# has no export statement.
|
|
68
|
+
enclosingStatementNodeTypes: ['using_directive'],
|
|
69
|
+
// Every capture mirrors the hard-coded runtime convention and is validated by
|
|
70
|
+
// `assertCaptureMapConforms`. The namespaced csharp.struct/record/delegate are
|
|
71
|
+
// still definition.<subtype>.* captures (subtype = the namespaced value).
|
|
72
|
+
captureMap: [
|
|
73
|
+
{ capture: 'definition.namespace.node', field: 'node', subtype: 'namespace' },
|
|
74
|
+
{ capture: 'definition.namespace.name', field: 'name' },
|
|
75
|
+
{ capture: 'definition.class.node', field: 'node', subtype: 'class' },
|
|
76
|
+
{ capture: 'definition.class.name', field: 'name' },
|
|
77
|
+
{ capture: 'definition.interface.node', field: 'node', subtype: 'interface' },
|
|
78
|
+
{ capture: 'definition.interface.name', field: 'name' },
|
|
79
|
+
{ capture: 'definition.csharp.struct.node', field: 'node', subtype: 'csharp.struct' },
|
|
80
|
+
{ capture: 'definition.csharp.struct.name', field: 'name' },
|
|
81
|
+
{ capture: 'definition.enum.node', field: 'node', subtype: 'enum' },
|
|
82
|
+
{ capture: 'definition.enum.name', field: 'name' },
|
|
83
|
+
{ capture: 'definition.csharp.record.node', field: 'node', subtype: 'csharp.record' },
|
|
84
|
+
{ capture: 'definition.csharp.record.name', field: 'name' },
|
|
85
|
+
{ capture: 'definition.csharp.delegate.node', field: 'node', subtype: 'csharp.delegate' },
|
|
86
|
+
{ capture: 'definition.csharp.delegate.name', field: 'name' },
|
|
87
|
+
{ capture: 'definition.method.node', field: 'node', subtype: 'method' },
|
|
88
|
+
{ capture: 'definition.method.name', field: 'name' },
|
|
89
|
+
{ capture: 'definition.constructor.node', field: 'node', subtype: 'constructor' },
|
|
90
|
+
{ capture: 'definition.constructor.name', field: 'name' },
|
|
91
|
+
{ capture: 'definition.property.node', field: 'node', subtype: 'property' },
|
|
92
|
+
{ capture: 'definition.property.name', field: 'name' },
|
|
93
|
+
{ capture: 'definition.constant.node', field: 'node', subtype: 'constant' },
|
|
94
|
+
{ capture: 'definition.constant.name', field: 'name' },
|
|
95
|
+
{ capture: 'definition.field.node', field: 'node', subtype: 'field' },
|
|
96
|
+
{ capture: 'definition.field.name', field: 'name' },
|
|
97
|
+
{ capture: 'import.source', field: 'source' },
|
|
98
|
+
],
|
|
99
|
+
};
|
|
100
|
+
const vocabulary = {
|
|
101
|
+
nodeSubtypes: [
|
|
102
|
+
'namespace',
|
|
103
|
+
'class',
|
|
104
|
+
'interface',
|
|
105
|
+
'csharp.struct',
|
|
106
|
+
'enum',
|
|
107
|
+
'csharp.record',
|
|
108
|
+
'csharp.delegate',
|
|
109
|
+
'method',
|
|
110
|
+
'constructor',
|
|
111
|
+
'property',
|
|
112
|
+
'constant',
|
|
113
|
+
'field',
|
|
114
|
+
],
|
|
115
|
+
edgeKinds: ['contains', 'defines', 'imports'],
|
|
116
|
+
captureMap: queries.captureMap,
|
|
117
|
+
};
|
|
118
|
+
const capabilities = {
|
|
119
|
+
tiers: ['T1.definitions', 'T2.imports'],
|
|
120
|
+
proven: {
|
|
121
|
+
'T1.definitions': true,
|
|
122
|
+
'T2.imports': true,
|
|
123
|
+
'T3.import_resolution': false,
|
|
124
|
+
'T4.tests_for': false,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
/** A span key matching the runtime's `spanOf` (1-based start/end line+col). */
|
|
128
|
+
function spanKey(span) {
|
|
129
|
+
return `${span.start_line}:${span.start_col}:${span.end_line}:${span.end_col}`;
|
|
130
|
+
}
|
|
131
|
+
function spanKeyOfNode(node) {
|
|
132
|
+
return `${node.startPosition.row + 1}:${node.startPosition.column + 1}:${node.endPosition.row + 1}:${node.endPosition.column + 1}`;
|
|
133
|
+
}
|
|
134
|
+
/** Iterative named-node DFS collecting nodes whose type is in `types`. */
|
|
135
|
+
function collectByType(root, types) {
|
|
136
|
+
const found = [];
|
|
137
|
+
const stack = [root];
|
|
138
|
+
while (stack.length > 0) {
|
|
139
|
+
const n = stack.pop();
|
|
140
|
+
if (types.has(n.type))
|
|
141
|
+
found.push(n);
|
|
142
|
+
for (let i = 0; i < n.namedChildCount; i++) {
|
|
143
|
+
const c = n.namedChild(i);
|
|
144
|
+
if (c)
|
|
145
|
+
stack.push(c);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return found;
|
|
149
|
+
}
|
|
150
|
+
const USING_DIRECTIVE = new Set(['using_directive']);
|
|
151
|
+
/**
|
|
152
|
+
* Map each `using X = A.B;` directive's statement span → its alias binding name.
|
|
153
|
+
* The alias lives in a `name_equals` child (`(name_equals (identifier))`); plain
|
|
154
|
+
* and `using static` directives have none and are absent from the map.
|
|
155
|
+
*/
|
|
156
|
+
function aliasBySpan(tree) {
|
|
157
|
+
const out = new Map();
|
|
158
|
+
for (const dir of collectByType(tree.rootNode, USING_DIRECTIVE)) {
|
|
159
|
+
for (let i = 0; i < dir.namedChildCount; i++) {
|
|
160
|
+
const c = dir.namedChild(i);
|
|
161
|
+
if (c && c.type === 'name_equals') {
|
|
162
|
+
const alias = c.namedChild(0);
|
|
163
|
+
if (alias)
|
|
164
|
+
out.set(spanKeyOfNode(dir), alias.text);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
export class CSharpProvider {
|
|
172
|
+
id = 'csharp';
|
|
173
|
+
displayName = 'C#';
|
|
174
|
+
languages = ['csharp'];
|
|
175
|
+
extensions = ['.cs'];
|
|
176
|
+
priority = 0;
|
|
177
|
+
version = '0.1.0';
|
|
178
|
+
parser = parser;
|
|
179
|
+
queries = queries;
|
|
180
|
+
vocabulary = vocabulary;
|
|
181
|
+
capabilities = capabilities;
|
|
182
|
+
/** `.cs` → `csharp`. */
|
|
183
|
+
langForPath(_p) {
|
|
184
|
+
return 'csharp';
|
|
185
|
+
}
|
|
186
|
+
async extractDraft(input, _services) {
|
|
187
|
+
return extractWithQueries({
|
|
188
|
+
providerId: this.id,
|
|
189
|
+
lang: input.lang,
|
|
190
|
+
source: input.source,
|
|
191
|
+
sizeBytes: input.sizeBytes,
|
|
192
|
+
maxParseFileBytes: input.maxParseFileBytes,
|
|
193
|
+
maxQueryWaitMs: input.maxQueryWaitMs,
|
|
194
|
+
path: input.path,
|
|
195
|
+
grammarForLang: this.parser.grammarForLang,
|
|
196
|
+
tagsSource: TAGS,
|
|
197
|
+
tagsHash: TAGS_HASH,
|
|
198
|
+
importsSource: IMPORTS,
|
|
199
|
+
importsHash: IMPORTS_HASH,
|
|
200
|
+
enclosingStatementNodeTypes: queries.enclosingStatementNodeTypes,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Drafts-only refinement: lift each `using X = A.B;` alias binding (`X`) onto the
|
|
205
|
+
* corresponding module node's imported names. The module source `A.B` is already
|
|
206
|
+
* captured structurally; plain and `using static` directives are unchanged.
|
|
207
|
+
*/
|
|
208
|
+
refine(draft, _ctx) {
|
|
209
|
+
const tree = draft.attributes?.__tree;
|
|
210
|
+
if (!tree || draft.imports.length === 0)
|
|
211
|
+
return draft;
|
|
212
|
+
const aliases = aliasBySpan(tree);
|
|
213
|
+
if (aliases.size === 0)
|
|
214
|
+
return draft;
|
|
215
|
+
const imports = draft.imports.map((im) => {
|
|
216
|
+
const alias = aliases.get(spanKey(im.span));
|
|
217
|
+
return alias ? { ...im, importedNames: [alias] } : im;
|
|
218
|
+
});
|
|
219
|
+
return { ...draft, imports };
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/** Singleton instance for registry wiring. */
|
|
223
|
+
export const csharpProvider = new CSharpProvider();
|
|
224
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
; Code Map — C# definitions (tags.scm). Provider #6 (langs batch 2).
|
|
2
|
+
;
|
|
3
|
+
; Capture-name convention (query-runtime.ts is the contract):
|
|
4
|
+
; @definition.<subtype>.node = identity-span anchor (the whole declaration)
|
|
5
|
+
; @definition.<subtype>.name = the symbol name node
|
|
6
|
+
; Subtypes: namespace/class/interface/enum/method/constructor/property/field/
|
|
7
|
+
; constant are universal. C#-distinct kinds are namespaced (Codex/Java R1 precedent
|
|
8
|
+
; for record/annotation): a struct is a VALUE type first-class-distinct from a class
|
|
9
|
+
; (reference type) — devs choose between them deliberately — so struct →
|
|
10
|
+
; csharp.struct (NOT class like Go, where struct is the only aggregate); records →
|
|
11
|
+
; csharp.record; delegates (named function-type declarations) → csharp.delegate.
|
|
12
|
+
; enum members → constant. Constructors are a distinct grammar node
|
|
13
|
+
; (constructor_declaration → constructor, not method). Nested/inner types + their
|
|
14
|
+
; members are emitted by the same patterns; the finalizer emits only file-level
|
|
15
|
+
; contains/defines (no fabricated nesting edges).
|
|
16
|
+
|
|
17
|
+
; namespace Acme.Widgets { … } — name is a qualified_name or a bare identifier.
|
|
18
|
+
(namespace_declaration
|
|
19
|
+
name: [(qualified_name) (identifier)] @definition.namespace.name) @definition.namespace.node
|
|
20
|
+
|
|
21
|
+
; File-scoped namespace (C# 10): `namespace Acme.App;` — its own grammar node.
|
|
22
|
+
(file_scoped_namespace_declaration
|
|
23
|
+
name: [(qualified_name) (identifier)] @definition.namespace.name) @definition.namespace.node
|
|
24
|
+
|
|
25
|
+
(class_declaration
|
|
26
|
+
name: (identifier) @definition.class.name) @definition.class.node
|
|
27
|
+
|
|
28
|
+
(interface_declaration
|
|
29
|
+
name: (identifier) @definition.interface.name) @definition.interface.node
|
|
30
|
+
|
|
31
|
+
(struct_declaration
|
|
32
|
+
name: (identifier) @definition.csharp.struct.name) @definition.csharp.struct.node
|
|
33
|
+
|
|
34
|
+
(enum_declaration
|
|
35
|
+
name: (identifier) @definition.enum.name) @definition.enum.node
|
|
36
|
+
|
|
37
|
+
; `record`, `record class`, and `record struct` all parse as record_declaration.
|
|
38
|
+
(record_declaration
|
|
39
|
+
name: (identifier) @definition.csharp.record.name) @definition.csharp.record.node
|
|
40
|
+
|
|
41
|
+
; `delegate int Transformer(int x);` — a named function-type declaration.
|
|
42
|
+
(delegate_declaration
|
|
43
|
+
name: (identifier) @definition.csharp.delegate.name) @definition.csharp.delegate.node
|
|
44
|
+
|
|
45
|
+
(method_declaration
|
|
46
|
+
name: (identifier) @definition.method.name) @definition.method.node
|
|
47
|
+
|
|
48
|
+
(constructor_declaration
|
|
49
|
+
name: (identifier) @definition.constructor.name) @definition.constructor.node
|
|
50
|
+
|
|
51
|
+
(property_declaration
|
|
52
|
+
name: (identifier) @definition.property.name) @definition.property.node
|
|
53
|
+
|
|
54
|
+
; enum members map to constant: `enum Color { Red, Green }` → one per member.
|
|
55
|
+
(enum_member_declaration
|
|
56
|
+
name: (identifier) @definition.constant.name) @definition.constant.node
|
|
57
|
+
|
|
58
|
+
; `public int a, b;` yields one match per variable_declarator (all sharing the
|
|
59
|
+
; field_declaration identity span) — mirrors the Java field multi-declarator rule.
|
|
60
|
+
; The declarator's name is its first (unlabelled) identifier child.
|
|
61
|
+
(field_declaration
|
|
62
|
+
(variable_declaration
|
|
63
|
+
(variable_declarator (identifier) @definition.field.name))) @definition.field.node
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
; Code Map — Go imports (imports.scm). Provider #5 (langs batch 2).
|
|
2
|
+
;
|
|
3
|
+
; enclosingStatementNodeTypes = [import_declaration] (the import span/ordinal
|
|
4
|
+
; anchor). Go import paths are double-quoted string literals, so the captured
|
|
5
|
+
; @import.source text includes the surrounding quotes — the provider's refine()
|
|
6
|
+
; strips them to the bare module path. An import alias (`import f "fmt"`) is NOT
|
|
7
|
+
; lifted in v1: the module is still `fmt`, and the alias `f` is dropped (aliases
|
|
8
|
+
; are cosmetic; the real package path is what a resolver needs). One import_spec
|
|
9
|
+
; per imported package (Go groups them in an import_declaration but each path is
|
|
10
|
+
; its own spec → its own module node).
|
|
11
|
+
|
|
12
|
+
(import_spec
|
|
13
|
+
path: (interpreted_string_literal) @import.source)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Map langs batch 2 — GoProvider (provider #5).
|
|
3
|
+
*
|
|
4
|
+
* Owns `.go` (runtime lang `go`). `extractDraft` delegates to the generic
|
|
5
|
+
* query-runtime; the curated `tags.scm`/`imports.scm` (this dir) drive extraction.
|
|
6
|
+
* Definition subtypes are fixed by the query (struct→class, interface→interface,
|
|
7
|
+
* function/method/constant/variable/package universal). `refine()` carries only
|
|
8
|
+
* what the import query cannot express structurally: Go import paths are quoted
|
|
9
|
+
* string literals, so the captured @import.source is `"pkg/path"` — strip the
|
|
10
|
+
* surrounding quotes to the bare module path.
|
|
11
|
+
*
|
|
12
|
+
* NO exports edges — Go has no export statement (visibility is capitalization;
|
|
13
|
+
* capabilities: T2 = imports). Identity is owned by the CORE finalizer — this
|
|
14
|
+
* provider mints NO ids. The grammar loads through the SHARED engine glue
|
|
15
|
+
* (`loadGrammarWasm`), never a fresh `web-tree-sitter` import (trp_8df65ab7).
|
|
16
|
+
*/
|
|
17
|
+
import crypto from 'node:crypto';
|
|
18
|
+
import fs from 'node:fs';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import { fileURLToPath } from 'node:url';
|
|
21
|
+
import { loadGrammarWasm, grammarHashForWasm } from '../../wasm-loader.js';
|
|
22
|
+
import { extractWithQueries } from '../query-runtime.js';
|
|
23
|
+
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
const GO_WASM_BASENAME = 'tree-sitter-go.wasm';
|
|
25
|
+
const GO_WASM_NODE_MODULES_SPEC = 'tree-sitter-wasms/out/tree-sitter-go.wasm';
|
|
26
|
+
const GO_GRAMMAR_NAME = 'tree-sitter-go';
|
|
27
|
+
/** Resolve a vendored `.scm` next to this module (dist) or from the source tree. */
|
|
28
|
+
function readScm(basename) {
|
|
29
|
+
const local = path.join(HERE, basename);
|
|
30
|
+
if (fs.existsSync(local))
|
|
31
|
+
return fs.readFileSync(local, 'utf-8');
|
|
32
|
+
let dir = HERE;
|
|
33
|
+
for (let i = 0; i < 12; i++) {
|
|
34
|
+
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
35
|
+
const fromSrc = path.join(dir, 'src', 'core', 'code-map', 'lang', 'go', basename);
|
|
36
|
+
if (fs.existsSync(fromSrc))
|
|
37
|
+
return fs.readFileSync(fromSrc, 'utf-8');
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
const parent = path.dirname(dir);
|
|
41
|
+
if (parent === dir)
|
|
42
|
+
break;
|
|
43
|
+
dir = parent;
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`code-map: could not locate query asset ${basename} (from ${HERE})`);
|
|
46
|
+
}
|
|
47
|
+
function sha256(s) {
|
|
48
|
+
return `sha256:${crypto.createHash('sha256').update(s, 'utf-8').digest('hex')}`;
|
|
49
|
+
}
|
|
50
|
+
const TAGS = readScm('tags.scm');
|
|
51
|
+
const IMPORTS = readScm('imports.scm');
|
|
52
|
+
const TAGS_HASH = sha256(TAGS);
|
|
53
|
+
const IMPORTS_HASH = sha256(IMPORTS);
|
|
54
|
+
const parser = {
|
|
55
|
+
grammarForLang: () => loadGrammarWasm(GO_WASM_BASENAME, GO_WASM_NODE_MODULES_SPEC),
|
|
56
|
+
grammarNameForLang: () => GO_GRAMMAR_NAME,
|
|
57
|
+
grammarHashForLang: () => grammarHashForWasm(GO_WASM_BASENAME, GO_WASM_NODE_MODULES_SPEC),
|
|
58
|
+
};
|
|
59
|
+
const queries = {
|
|
60
|
+
tags: { name: 'tags', sourceForLang: () => TAGS, hashForLang: () => TAGS_HASH },
|
|
61
|
+
imports: { name: 'imports', sourceForLang: () => IMPORTS, hashForLang: () => IMPORTS_HASH },
|
|
62
|
+
enclosingStatementNodeTypes: ['import_declaration'],
|
|
63
|
+
captureMap: [
|
|
64
|
+
{ capture: 'definition.package.node', field: 'node', subtype: 'package' },
|
|
65
|
+
{ capture: 'definition.package.name', field: 'name' },
|
|
66
|
+
{ capture: 'definition.function.node', field: 'node', subtype: 'function' },
|
|
67
|
+
{ capture: 'definition.function.name', field: 'name' },
|
|
68
|
+
{ capture: 'definition.method.node', field: 'node', subtype: 'method' },
|
|
69
|
+
{ capture: 'definition.method.name', field: 'name' },
|
|
70
|
+
{ capture: 'definition.class.node', field: 'node', subtype: 'class' },
|
|
71
|
+
{ capture: 'definition.class.name', field: 'name' },
|
|
72
|
+
{ capture: 'definition.interface.node', field: 'node', subtype: 'interface' },
|
|
73
|
+
{ capture: 'definition.interface.name', field: 'name' },
|
|
74
|
+
{ capture: 'definition.constant.node', field: 'node', subtype: 'constant' },
|
|
75
|
+
{ capture: 'definition.constant.name', field: 'name' },
|
|
76
|
+
{ capture: 'definition.variable.node', field: 'node', subtype: 'variable' },
|
|
77
|
+
{ capture: 'definition.variable.name', field: 'name' },
|
|
78
|
+
{ capture: 'import.source', field: 'source' },
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
const vocabulary = {
|
|
82
|
+
nodeSubtypes: ['package', 'function', 'method', 'class', 'interface', 'constant', 'variable'],
|
|
83
|
+
edgeKinds: ['contains', 'defines', 'imports'],
|
|
84
|
+
captureMap: queries.captureMap,
|
|
85
|
+
};
|
|
86
|
+
const capabilities = {
|
|
87
|
+
tiers: ['T1.definitions', 'T2.imports'],
|
|
88
|
+
proven: {
|
|
89
|
+
'T1.definitions': true,
|
|
90
|
+
'T2.imports': true,
|
|
91
|
+
'T3.import_resolution': false,
|
|
92
|
+
'T4.tests_for': false,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
/** Strip the surrounding quotes/backticks from a Go string-literal import path. */
|
|
96
|
+
function stripQuotes(s) {
|
|
97
|
+
return s.replace(/^[`"]/, '').replace(/[`"]$/, '');
|
|
98
|
+
}
|
|
99
|
+
export class GoProvider {
|
|
100
|
+
id = 'go';
|
|
101
|
+
displayName = 'Go';
|
|
102
|
+
languages = ['go'];
|
|
103
|
+
extensions = ['.go'];
|
|
104
|
+
priority = 0;
|
|
105
|
+
version = '0.1.0';
|
|
106
|
+
parser = parser;
|
|
107
|
+
queries = queries;
|
|
108
|
+
vocabulary = vocabulary;
|
|
109
|
+
capabilities = capabilities;
|
|
110
|
+
langForPath(_p) {
|
|
111
|
+
return 'go';
|
|
112
|
+
}
|
|
113
|
+
async extractDraft(input, _services) {
|
|
114
|
+
return extractWithQueries({
|
|
115
|
+
providerId: this.id,
|
|
116
|
+
lang: input.lang,
|
|
117
|
+
source: input.source,
|
|
118
|
+
sizeBytes: input.sizeBytes,
|
|
119
|
+
maxParseFileBytes: input.maxParseFileBytes,
|
|
120
|
+
maxQueryWaitMs: input.maxQueryWaitMs,
|
|
121
|
+
path: input.path,
|
|
122
|
+
grammarForLang: this.parser.grammarForLang,
|
|
123
|
+
tagsSource: TAGS,
|
|
124
|
+
tagsHash: TAGS_HASH,
|
|
125
|
+
importsSource: IMPORTS,
|
|
126
|
+
importsHash: IMPORTS_HASH,
|
|
127
|
+
enclosingStatementNodeTypes: queries.enclosingStatementNodeTypes,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/** Drafts-only: strip the quotes from each import path (`"fmt"` → `fmt`). */
|
|
131
|
+
refine(draft, _ctx) {
|
|
132
|
+
if (draft.imports.length === 0)
|
|
133
|
+
return draft;
|
|
134
|
+
const imports = draft.imports.map((im) => ({ ...im, source: stripQuotes(im.source) }));
|
|
135
|
+
return { ...draft, imports };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
export const goProvider = new GoProvider();
|
|
139
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
; Code Map — Go definitions (tags.scm). Provider #5 (langs batch 2).
|
|
2
|
+
;
|
|
3
|
+
; Capture-name convention (query-runtime.ts is the contract):
|
|
4
|
+
; @definition.<subtype>.node = identity-span anchor (the declaration)
|
|
5
|
+
; @definition.<subtype>.name = the symbol name node
|
|
6
|
+
; Subtypes: function/method/interface/constant/variable/package are universal;
|
|
7
|
+
; a Go struct maps to `class` (the named aggregate devs search for like a class).
|
|
8
|
+
; Patterns are mutually exclusive by the `type:` child so a type_spec is captured
|
|
9
|
+
; once (struct→class, interface→interface); bare type aliases are intentionally
|
|
10
|
+
; not captured in v1 (low value, and a general type_spec pattern would double-match
|
|
11
|
+
; struct/interface with a different subtype → duplicate symbol).
|
|
12
|
+
|
|
13
|
+
(package_clause
|
|
14
|
+
(package_identifier) @definition.package.name) @definition.package.node
|
|
15
|
+
|
|
16
|
+
(function_declaration
|
|
17
|
+
name: (identifier) @definition.function.name) @definition.function.node
|
|
18
|
+
|
|
19
|
+
(method_declaration
|
|
20
|
+
name: (field_identifier) @definition.method.name) @definition.method.node
|
|
21
|
+
|
|
22
|
+
(type_spec
|
|
23
|
+
name: (type_identifier) @definition.class.name
|
|
24
|
+
type: (struct_type)) @definition.class.node
|
|
25
|
+
|
|
26
|
+
(type_spec
|
|
27
|
+
name: (type_identifier) @definition.interface.name
|
|
28
|
+
type: (interface_type)) @definition.interface.node
|
|
29
|
+
|
|
30
|
+
; `const ( A = 1; B = 2 )` and `const C = 3` both yield const_spec per name.
|
|
31
|
+
(const_spec
|
|
32
|
+
name: (identifier) @definition.constant.name) @definition.constant.node
|
|
33
|
+
|
|
34
|
+
; Package-level `var x = …` → variable (one per var_spec name).
|
|
35
|
+
(var_spec
|
|
36
|
+
name: (identifier) @definition.variable.name) @definition.variable.node
|
|
@@ -16,9 +16,20 @@ import { typeScriptProvider } from './typescript/index.js';
|
|
|
16
16
|
import { pythonProvider } from './python/index.js';
|
|
17
17
|
import { phpProvider } from './php/index.js';
|
|
18
18
|
import { javaProvider } from './java/index.js';
|
|
19
|
+
import { goProvider } from './go/index.js';
|
|
20
|
+
import { rustProvider } from './rust/index.js';
|
|
21
|
+
import { csharpProvider } from './csharp/index.js';
|
|
22
|
+
import { rubyProvider } from './ruby/index.js';
|
|
23
|
+
import { cppProvider } from './cpp/index.js';
|
|
24
|
+
import { cProvider } from './c/index.js';
|
|
19
25
|
/**
|
|
20
26
|
* The default registry, pre-loaded with the bundled providers. Add a new
|
|
21
27
|
* provider's singleton to this `createRegistry(...)` call to register it.
|
|
28
|
+
*
|
|
29
|
+
* Registration ORDER is the collision tiebreak (earliest wins, after `priority`).
|
|
30
|
+
* `cpp` is registered BEFORE `c` so the C++ provider (a superset that parses C
|
|
31
|
+
* fine) wins the shared `.h` extension — a C header parses correctly as C++, but
|
|
32
|
+
* a C++ header would not parse as C.
|
|
22
33
|
*/
|
|
23
|
-
export const defaultRegistry = createRegistry(typeScriptProvider, pythonProvider, phpProvider, javaProvider);
|
|
34
|
+
export const defaultRegistry = createRegistry(typeScriptProvider, pythonProvider, phpProvider, javaProvider, goProvider, rustProvider, csharpProvider, rubyProvider, cppProvider, cProvider);
|
|
24
35
|
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
; Code Map — Ruby imports (imports.scm). Provider #6 (langs batch 2).
|
|
2
|
+
;
|
|
3
|
+
; Ruby has NO static import statement — `require` / `require_relative` are METHOD
|
|
4
|
+
; CALLS. So the "import" is a (call) whose `method:` is the identifier `require` or
|
|
5
|
+
; `require_relative` and whose single string argument is the required module/path.
|
|
6
|
+
;
|
|
7
|
+
; enclosingStatementNodeTypes = ['call'] (the require call is the import span/ordinal
|
|
8
|
+
; anchor). The captured @import.source is the STRING literal node; its text includes
|
|
9
|
+
; the surrounding quotes (`'sinatra'` / `"json"`), which the query-runtime strips
|
|
10
|
+
; automatically (stripQuotes) — and the provider's refine() strips again defensively
|
|
11
|
+
; (idempotent), matching the Go provider's documented pattern. Best-effort T2: the
|
|
12
|
+
; module node `name` is the required string verbatim (`sinatra`, `json`, `./helpers`);
|
|
13
|
+
; there is no path resolution (T3 = none).
|
|
14
|
+
;
|
|
15
|
+
; The `#any-of?` predicate restricts the match to require-family calls (verified:
|
|
16
|
+
; web-tree-sitter 0.25.x applies text predicates inside `matches()`, so ordinary
|
|
17
|
+
; calls like `puts "x"` / `foo.bar('y')` are filtered out and never emit a module
|
|
18
|
+
; node). @_req is a predicate-only capture — the runtime ignores it (only
|
|
19
|
+
; @import.source drives an ImportDraft).
|
|
20
|
+
|
|
21
|
+
(call
|
|
22
|
+
method: (identifier) @_req
|
|
23
|
+
arguments: (argument_list (string) @import.source)
|
|
24
|
+
(#any-of? @_req "require" "require_relative"))
|