@nanonets/graft 0.9.1 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -45
- package/dist/ask/fuse.d.ts.map +1 -1
- package/dist/ask/fuse.js +32 -14
- package/dist/ask/fuse.js.map +1 -1
- package/dist/claude/hooks.d.ts +13 -0
- package/dist/claude/hooks.d.ts.map +1 -1
- package/dist/claude/hooks.js +26 -2
- package/dist/claude/hooks.js.map +1 -1
- package/dist/claude/init.d.ts.map +1 -1
- package/dist/claude/init.js +6 -3
- package/dist/claude/init.js.map +1 -1
- package/dist/cli.js +93 -39
- package/dist/cli.js.map +1 -1
- package/dist/engine.d.ts +6 -2
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +4 -1
- package/dist/engine.js.map +1 -1
- package/dist/graph/bindings.d.ts.map +1 -1
- package/dist/graph/bindings.js +80 -0
- package/dist/graph/bindings.js.map +1 -1
- package/dist/graph/build.d.ts +5 -0
- package/dist/graph/build.d.ts.map +1 -1
- package/dist/graph/build.js +21 -2
- package/dist/graph/build.js.map +1 -1
- package/dist/graph/check.d.ts +1 -1
- package/dist/graph/check.d.ts.map +1 -1
- package/dist/graph/check.js +13 -3
- package/dist/graph/check.js.map +1 -1
- package/dist/graph/extract.d.ts +6 -1
- package/dist/graph/extract.d.ts.map +1 -1
- package/dist/graph/extract.js +192 -10
- package/dist/graph/extract.js.map +1 -1
- package/dist/graph/generic.d.ts +25 -0
- package/dist/graph/generic.d.ts.map +1 -0
- package/dist/graph/generic.js +341 -0
- package/dist/graph/generic.js.map +1 -0
- package/dist/graph/invariants.d.ts +32 -0
- package/dist/graph/invariants.d.ts.map +1 -0
- package/dist/graph/invariants.js +49 -0
- package/dist/graph/invariants.js.map +1 -0
- package/dist/graph/lsp/client.d.ts +43 -0
- package/dist/graph/lsp/client.d.ts.map +1 -0
- package/dist/graph/lsp/client.js +179 -0
- package/dist/graph/lsp/client.js.map +1 -0
- package/dist/graph/lsp/enrich.d.ts +11 -0
- package/dist/graph/lsp/enrich.d.ts.map +1 -0
- package/dist/graph/lsp/enrich.js +155 -0
- package/dist/graph/lsp/enrich.js.map +1 -0
- package/dist/graph/lsp/registry.d.ts +15 -0
- package/dist/graph/lsp/registry.d.ts.map +1 -0
- package/dist/graph/lsp/registry.js +46 -0
- package/dist/graph/lsp/registry.js.map +1 -0
- package/dist/graph/queries/c.scm +13 -0
- package/dist/graph/queries/c_sharp.scm +19 -0
- package/dist/graph/queries/cpp.scm +23 -0
- package/dist/graph/queries/elixir.scm +54 -0
- package/dist/graph/queries/java.scm +20 -0
- package/dist/graph/queries/kotlin.scm +43 -0
- package/dist/graph/queries/php.scm +40 -0
- package/dist/graph/queries/ruby.scm +65 -0
- package/dist/graph/queries/rust.scm +41 -0
- package/dist/graph/queries/scala.scm +66 -0
- package/dist/graph/queries/solidity.scm +43 -0
- package/dist/graph/queries/swift.scm +51 -0
- package/dist/graph/resolve.d.ts.map +1 -1
- package/dist/graph/resolve.js +124 -18
- package/dist/graph/resolve.js.map +1 -1
- package/dist/graph/root.d.ts +11 -0
- package/dist/graph/root.d.ts.map +1 -0
- package/dist/graph/root.js +40 -0
- package/dist/graph/root.js.map +1 -0
- package/dist/graph/source-files.d.ts.map +1 -1
- package/dist/graph/source-files.js +5 -1
- package/dist/graph/source-files.js.map +1 -1
- package/dist/graph/types.d.ts +14 -7
- package/dist/graph/types.d.ts.map +1 -1
- package/dist/graph/types.js +2 -2
- package/dist/graph/workspace-cli.d.ts +1 -1
- package/dist/graph/workspace-cli.d.ts.map +1 -1
- package/dist/graph/workspace-cli.js +2 -2
- package/dist/graph/workspace-cli.js.map +1 -1
- package/dist/graph/workspace.d.ts +2 -2
- package/dist/graph/workspace.d.ts.map +1 -1
- package/dist/graph/workspace.js +2 -2
- package/dist/graph/workspace.js.map +1 -1
- package/dist/hosts/codex-hooks.d.ts +3 -3
- package/dist/hosts/codex-hooks.d.ts.map +1 -1
- package/dist/hosts/codex-hooks.js +27 -21
- package/dist/hosts/codex-hooks.js.map +1 -1
- package/dist/mcp/tools.js +6 -6
- package/dist/mcp/tools.js.map +1 -1
- package/package.json +15 -2
- package/scripts/build-viewer.mjs +17 -1
- package/scripts/graph-quality.mjs +117 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface LspPosition {
|
|
2
|
+
line: number;
|
|
3
|
+
character: number;
|
|
4
|
+
}
|
|
5
|
+
export interface LspRange {
|
|
6
|
+
start: LspPosition;
|
|
7
|
+
end: LspPosition;
|
|
8
|
+
}
|
|
9
|
+
export interface CallHierarchyItem {
|
|
10
|
+
name: string;
|
|
11
|
+
kind: number;
|
|
12
|
+
uri: string;
|
|
13
|
+
range: LspRange;
|
|
14
|
+
selectionRange: LspRange;
|
|
15
|
+
}
|
|
16
|
+
export declare class LspClient {
|
|
17
|
+
private readonly root;
|
|
18
|
+
private readonly languageId;
|
|
19
|
+
private readonly callTimeoutMs;
|
|
20
|
+
private proc;
|
|
21
|
+
private conn;
|
|
22
|
+
private opened;
|
|
23
|
+
private ready;
|
|
24
|
+
private spawnFailed;
|
|
25
|
+
constructor(command: string, args: string[], root: string, languageId: string, callTimeoutMs?: number);
|
|
26
|
+
/** Safe to write to the server's stdin right now? */
|
|
27
|
+
private canWrite;
|
|
28
|
+
/** A request with a timeout so a wedged server can't hang the whole build. */
|
|
29
|
+
private call;
|
|
30
|
+
initialize(): Promise<boolean>;
|
|
31
|
+
/** Open a document (idempotent). Servers resolve cross-file refs from disk, but
|
|
32
|
+
* the LSP spec wants the queried document opened first. */
|
|
33
|
+
didOpen(abs: string): void;
|
|
34
|
+
/** Poll one probe position until call-hierarchy returns something — servers
|
|
35
|
+
* like rust-analyzer/clangd index AFTER `initialized` and answer empty until
|
|
36
|
+
* ready. Returns true once ready (or false at the cap). */
|
|
37
|
+
waitUntilReady(abs: string, pos: LspPosition, maxMs?: number): Promise<boolean>;
|
|
38
|
+
prepareCallHierarchy(abs: string, pos: LspPosition): Promise<CallHierarchyItem[]>;
|
|
39
|
+
/** The callees of an item — returns each outgoing call's `to` target. */
|
|
40
|
+
outgoingCalls(item: CallHierarchyItem): Promise<CallHierarchyItem[]>;
|
|
41
|
+
dispose(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/graph/lsp/client.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,WAAW;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAChE,MAAM,WAAW,QAAQ;IAAG,KAAK,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,WAAW,CAAA;CAAE;AAClE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,QAAQ,CAAC;IAChB,cAAc,EAAE,QAAQ,CAAC;CAC1B;AAID,qBAAa,SAAS;IAUlB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAXhC,OAAO,CAAC,IAAI,CAAiC;IAC7C,OAAO,CAAC,IAAI,CAAoB;IAChC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,WAAW,CAAS;gBAG1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACG,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,EAClB,aAAa,SAAQ;IAkCxC,qDAAqD;IACrD,OAAO,CAAC,QAAQ;IAIhB,8EAA8E;IAC9E,OAAO,CAAC,IAAI;IAYN,UAAU,IAAI,OAAO,CAAC,OAAO,CAAC;IA6BpC;+DAC2D;IAC3D,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAY1B;;+DAE2D;IACrD,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,SAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAW9E,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IASvF,yEAAyE;IACnE,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAMpE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A minimal LSP client for the opt-in `--lsp` enrichment pass — just enough to
|
|
3
|
+
* pull compiler-grade call edges out of a language server: spawn it over stdio,
|
|
4
|
+
* initialize, open documents, and run the call-hierarchy requests. Built on
|
|
5
|
+
* `vscode-jsonrpc` (we don't hand-roll the framing). Everything is best-effort:
|
|
6
|
+
* a server that is missing, slow, or errors degrades to "no enrichment", never a
|
|
7
|
+
* crash — the AST graph stands on its own.
|
|
8
|
+
*/
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
|
+
import { pathToFileURL } from "node:url";
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { createMessageConnection, StreamMessageReader, StreamMessageWriter, } from "vscode-jsonrpc/node.js";
|
|
13
|
+
const uriOf = (abs) => pathToFileURL(abs).toString();
|
|
14
|
+
export class LspClient {
|
|
15
|
+
root;
|
|
16
|
+
languageId;
|
|
17
|
+
callTimeoutMs;
|
|
18
|
+
proc;
|
|
19
|
+
conn;
|
|
20
|
+
opened = new Set();
|
|
21
|
+
ready = false;
|
|
22
|
+
spawnFailed = false;
|
|
23
|
+
constructor(command, args, root, languageId, callTimeoutMs = 15000) {
|
|
24
|
+
this.root = root;
|
|
25
|
+
this.languageId = languageId;
|
|
26
|
+
this.callTimeoutMs = callTimeoutMs;
|
|
27
|
+
this.proc = spawn(command, args, { cwd: root, stdio: ["pipe", "pipe", "pipe"] });
|
|
28
|
+
// ENOENT (bad path) OR an immediate exit (e.g. a rustup shim whose component
|
|
29
|
+
// isn't installed) must fail fast, not hang a request for the full timeout.
|
|
30
|
+
this.proc.on("error", () => { this.spawnFailed = true; });
|
|
31
|
+
// An immediate exit (shim without its component, crash on startup) must fail
|
|
32
|
+
// fast so initialize bails instead of waiting out the timeout; once we've
|
|
33
|
+
// marked !ready, in-flight queries no-op. Firing during dispose is harmless.
|
|
34
|
+
this.proc.on("exit", () => { this.spawnFailed = true; this.ready = false; });
|
|
35
|
+
this.proc.stderr.resume(); // drain; servers are chatty on stderr
|
|
36
|
+
// Swallow write-after-destroy (EPIPE / ERR_STREAM_DESTROYED) when the server
|
|
37
|
+
// closes its stdin during/after shutdown — otherwise it surfaces as an
|
|
38
|
+
// unhandled stream error and taints the process exit code.
|
|
39
|
+
this.proc.stdin.on("error", () => { });
|
|
40
|
+
this.conn = createMessageConnection(new StreamMessageReader(this.proc.stdout), new StreamMessageWriter(this.proc.stdin));
|
|
41
|
+
// Answer the reverse-RPC requests every server makes during startup so it
|
|
42
|
+
// doesn't block waiting on us; we take defaults for all of them.
|
|
43
|
+
this.conn.onRequest("workspace/configuration", (p) => (p.items ?? []).map(() => ({})));
|
|
44
|
+
this.conn.onRequest("client/registerCapability", () => null);
|
|
45
|
+
this.conn.onRequest("window/workDoneProgress/create", () => null);
|
|
46
|
+
this.conn.onRequest("workspace/applyEdit", () => ({ applied: false }));
|
|
47
|
+
this.conn.onNotification(() => { }); // swallow all notifications (diagnostics, progress, logs)
|
|
48
|
+
// The connection/streams can error or close asynchronously (server exits,
|
|
49
|
+
// stdin destroyed) — absorb both so a late write never becomes an unhandled
|
|
50
|
+
// exception that taints the build's exit code.
|
|
51
|
+
this.conn.onError(() => { this.ready = false; });
|
|
52
|
+
this.conn.onClose(() => { this.ready = false; });
|
|
53
|
+
this.conn.listen();
|
|
54
|
+
}
|
|
55
|
+
/** Safe to write to the server's stdin right now? */
|
|
56
|
+
canWrite() {
|
|
57
|
+
return this.ready && this.proc.stdin.writable && !this.proc.stdin.destroyed;
|
|
58
|
+
}
|
|
59
|
+
/** A request with a timeout so a wedged server can't hang the whole build. */
|
|
60
|
+
call(method, params) {
|
|
61
|
+
if (!this.canWrite())
|
|
62
|
+
return Promise.resolve(null);
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
let done = false;
|
|
65
|
+
const t = setTimeout(() => { if (!done) {
|
|
66
|
+
done = true;
|
|
67
|
+
resolve(null);
|
|
68
|
+
} }, this.callTimeoutMs);
|
|
69
|
+
this.conn.sendRequest(method, params).then((r) => { if (!done) {
|
|
70
|
+
done = true;
|
|
71
|
+
clearTimeout(t);
|
|
72
|
+
resolve(r);
|
|
73
|
+
} }, () => { if (!done) {
|
|
74
|
+
done = true;
|
|
75
|
+
clearTimeout(t);
|
|
76
|
+
resolve(null);
|
|
77
|
+
} });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async initialize() {
|
|
81
|
+
// Let a synchronous spawn failure (ENOENT) surface before we wait on a
|
|
82
|
+
// response that will never come.
|
|
83
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
84
|
+
if (this.spawnFailed || this.proc.pid === undefined)
|
|
85
|
+
return false;
|
|
86
|
+
const rootUri = uriOf(this.root);
|
|
87
|
+
// Cold-workspace load (rust-analyzer/clangd index the project) can take a
|
|
88
|
+
// while — give initialize a generous timeout, separate from per-request.
|
|
89
|
+
const init = await new Promise((resolve) => {
|
|
90
|
+
const t = setTimeout(() => resolve(null), 120000);
|
|
91
|
+
this.conn.sendRequest("initialize", {
|
|
92
|
+
processId: process.pid,
|
|
93
|
+
rootUri,
|
|
94
|
+
workspaceFolders: [{ uri: rootUri, name: "root" }],
|
|
95
|
+
capabilities: {
|
|
96
|
+
textDocument: {
|
|
97
|
+
callHierarchy: { dynamicRegistration: false },
|
|
98
|
+
synchronization: { dynamicRegistration: false },
|
|
99
|
+
},
|
|
100
|
+
workspace: { workspaceFolders: true, configuration: true },
|
|
101
|
+
},
|
|
102
|
+
}).then((r) => { clearTimeout(t); resolve(r); }, () => { clearTimeout(t); resolve(null); });
|
|
103
|
+
});
|
|
104
|
+
if (!init)
|
|
105
|
+
return false;
|
|
106
|
+
this.conn.sendNotification("initialized", {});
|
|
107
|
+
this.ready = true;
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
/** Open a document (idempotent). Servers resolve cross-file refs from disk, but
|
|
111
|
+
* the LSP spec wants the queried document opened first. */
|
|
112
|
+
didOpen(abs) {
|
|
113
|
+
if (!this.canWrite() || this.opened.has(abs))
|
|
114
|
+
return;
|
|
115
|
+
let text = "";
|
|
116
|
+
try {
|
|
117
|
+
text = readFileSync(abs, "utf8");
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.opened.add(abs);
|
|
123
|
+
try {
|
|
124
|
+
this.conn.sendNotification("textDocument/didOpen", {
|
|
125
|
+
textDocument: { uri: uriOf(abs), languageId: this.languageId, version: 1, text },
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch { /* stream closed mid-write */ }
|
|
129
|
+
}
|
|
130
|
+
/** Poll one probe position until call-hierarchy returns something — servers
|
|
131
|
+
* like rust-analyzer/clangd index AFTER `initialized` and answer empty until
|
|
132
|
+
* ready. Returns true once ready (or false at the cap). */
|
|
133
|
+
async waitUntilReady(abs, pos, maxMs = 90000) {
|
|
134
|
+
this.didOpen(abs);
|
|
135
|
+
const deadline = Date.now() + maxMs;
|
|
136
|
+
while (Date.now() < deadline) {
|
|
137
|
+
const items = await this.prepareCallHierarchy(abs, pos);
|
|
138
|
+
if (items.length)
|
|
139
|
+
return true;
|
|
140
|
+
await new Promise((r) => setTimeout(r, 2000));
|
|
141
|
+
}
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
144
|
+
async prepareCallHierarchy(abs, pos) {
|
|
145
|
+
if (!this.ready)
|
|
146
|
+
return [];
|
|
147
|
+
const r = await this.call("textDocument/prepareCallHierarchy", {
|
|
148
|
+
textDocument: { uri: uriOf(abs) },
|
|
149
|
+
position: pos,
|
|
150
|
+
});
|
|
151
|
+
return r ?? [];
|
|
152
|
+
}
|
|
153
|
+
/** The callees of an item — returns each outgoing call's `to` target. */
|
|
154
|
+
async outgoingCalls(item) {
|
|
155
|
+
if (!this.ready)
|
|
156
|
+
return [];
|
|
157
|
+
const r = await this.call("callHierarchy/outgoingCalls", { item });
|
|
158
|
+
return (r ?? []).map((c) => c.to).filter(Boolean);
|
|
159
|
+
}
|
|
160
|
+
async dispose() {
|
|
161
|
+
// Skip the graceful LSP shutdown/exit handshake: writing `exit` to a server
|
|
162
|
+
// that has already closed its stdin throws ERR_STREAM_DESTROYED and taints
|
|
163
|
+
// the exit code. The graph is already built; just tear the process down.
|
|
164
|
+
this.ready = false;
|
|
165
|
+
try {
|
|
166
|
+
this.conn.dispose();
|
|
167
|
+
}
|
|
168
|
+
catch { /* ignore */ }
|
|
169
|
+
try {
|
|
170
|
+
this.proc.stdin.destroy();
|
|
171
|
+
}
|
|
172
|
+
catch { /* ignore */ }
|
|
173
|
+
try {
|
|
174
|
+
this.proc.kill("SIGKILL");
|
|
175
|
+
}
|
|
176
|
+
catch { /* ignore */ }
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/graph/lsp/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { GraphV1 } from "../types.js";
|
|
2
|
+
export interface LspEnrichResult {
|
|
3
|
+
added: number;
|
|
4
|
+
queried: number;
|
|
5
|
+
server: string | null;
|
|
6
|
+
}
|
|
7
|
+
export declare function enrichWithLsp(graph: GraphV1, root: string, opts?: {
|
|
8
|
+
onProgress?: (done: number, total: number) => void;
|
|
9
|
+
maxNodes?: number;
|
|
10
|
+
}): Promise<LspEnrichResult>;
|
|
11
|
+
//# sourceMappingURL=enrich.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrich.d.ts","sourceRoot":"","sources":["../../../src/graph/lsp/enrich.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,OAAO,EAAkB,MAAM,aAAa,CAAC;AAe3D,MAAM,WAAW,eAAe;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AAE1F,wBAAsB,aAAa,CACjC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACnF,OAAO,CAAC,eAAe,CAAC,CAqG1B"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opt-in LSP enrichment (`graft build --lsp`): add compiler-grade call edges the
|
|
3
|
+
* AST resolver couldn't — chiefly member calls (`obj.foo()`) whose receiver type
|
|
4
|
+
* graft can't infer, and every call in the generic breadth tier (which has no
|
|
5
|
+
* receiver typing at all). For each function/method node we ask the language
|
|
6
|
+
* server for its outgoing calls (call hierarchy) and map each callee's definition
|
|
7
|
+
* back to a graft node, adding a `calls` edge stamped `lsp_resolved`. Precision is
|
|
8
|
+
* the server's (compiler-grade), so this closes the edge-recall gap WITHOUT the
|
|
9
|
+
* name-guessing that halved precision (see resolve.ts). Best-effort: no server /
|
|
10
|
+
* a timeout / an error → the graph is returned unchanged.
|
|
11
|
+
*/
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { relPosix } from "../../util/paths.js";
|
|
16
|
+
import { languageLabelOf } from "../extract.js";
|
|
17
|
+
import { genericLangOf } from "../generic.js";
|
|
18
|
+
import { LspClient } from "./client.js";
|
|
19
|
+
import { pickServer } from "./registry.js";
|
|
20
|
+
const CALLABLE = new Set(["function", "method"]);
|
|
21
|
+
const DEFN = new Set(["function", "method", "class", "struct", "interface", "type", "enum"]);
|
|
22
|
+
const langOf = (path) => genericLangOf(path)?.name ?? languageLabelOf(path);
|
|
23
|
+
const parseSpan = (s) => {
|
|
24
|
+
const m = /^L(\d+)-L(\d+)$/.exec(s);
|
|
25
|
+
return m ? [Number(m[1]), Number(m[2])] : null;
|
|
26
|
+
};
|
|
27
|
+
export async function enrichWithLsp(graph, root, opts = {}) {
|
|
28
|
+
const languagesPresent = new Set();
|
|
29
|
+
for (const n of graph.nodes) {
|
|
30
|
+
const l = langOf(n.path);
|
|
31
|
+
if (l)
|
|
32
|
+
languagesPresent.add(l);
|
|
33
|
+
}
|
|
34
|
+
const server = pickServer(languagesPresent);
|
|
35
|
+
if (!server)
|
|
36
|
+
return { added: 0, queried: 0, server: null };
|
|
37
|
+
// Canonicalize the root: servers (rust-analyzer/clangd) report callee URIs
|
|
38
|
+
// against the REAL path, so under a symlinked checkout (macOS /tmp →
|
|
39
|
+
// /private/tmp, common in CI) an un-resolved root would fail the in-repo test
|
|
40
|
+
// for every callee and silently zero out enrichment.
|
|
41
|
+
const realRoot = (() => { try {
|
|
42
|
+
return realpathSync(root);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return root;
|
|
46
|
+
} })();
|
|
47
|
+
root = realRoot;
|
|
48
|
+
// Index nodes by file for both source selection and callee→node mapping.
|
|
49
|
+
const byId = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
50
|
+
const spansByFile = new Map();
|
|
51
|
+
for (const n of graph.nodes) {
|
|
52
|
+
if (n.kind === "file" || !DEFN.has(n.kind))
|
|
53
|
+
continue;
|
|
54
|
+
const sp = parseSpan(n.span);
|
|
55
|
+
if (!sp)
|
|
56
|
+
continue;
|
|
57
|
+
const list = spansByFile.get(n.path) ?? [];
|
|
58
|
+
list.push({ node: n, from: sp[0], to: sp[1] });
|
|
59
|
+
spansByFile.set(n.path, list);
|
|
60
|
+
}
|
|
61
|
+
// The definition node covering a 1-indexed line in a file: innermost (smallest span).
|
|
62
|
+
const nodeAt = (rel, line) => {
|
|
63
|
+
const cands = (spansByFile.get(rel) ?? []).filter((s) => s.from <= line && line <= s.to);
|
|
64
|
+
if (!cands.length)
|
|
65
|
+
return null;
|
|
66
|
+
return cands.sort((a, b) => (a.to - a.from) - (b.to - b.from))[0].node;
|
|
67
|
+
};
|
|
68
|
+
// Source nodes to query: callable nodes in files this server handles.
|
|
69
|
+
const serverLangs = new Set(server.languages);
|
|
70
|
+
let sources = graph.nodes.filter((n) => CALLABLE.has(n.kind) && serverLangs.has(langOf(n.path) ?? ""));
|
|
71
|
+
if (opts.maxNodes && sources.length > opts.maxNodes)
|
|
72
|
+
sources = sources.slice(0, opts.maxNodes);
|
|
73
|
+
const client = new LspClient(server.command, server.args, root, server.languageId);
|
|
74
|
+
if (!(await client.initialize())) {
|
|
75
|
+
await client.dispose();
|
|
76
|
+
return { added: 0, queried: 0, server: server.command };
|
|
77
|
+
}
|
|
78
|
+
const existing = new Set(graph.edges.map((e) => `${e.source}\0${e.relation}\0${e.target}`));
|
|
79
|
+
const fileLines = new Map();
|
|
80
|
+
const linesOf = (rel) => {
|
|
81
|
+
if (!fileLines.has(rel)) {
|
|
82
|
+
try {
|
|
83
|
+
fileLines.set(rel, readFileSync(join(root, rel), "utf8").split("\n"));
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
fileLines.set(rel, []);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return fileLines.get(rel);
|
|
90
|
+
};
|
|
91
|
+
// The name-token position of a definition (0-indexed), scanning its first few
|
|
92
|
+
// lines for the name — call hierarchy needs a position ON the symbol.
|
|
93
|
+
const namePos = (src) => {
|
|
94
|
+
const sp = parseSpan(src.span);
|
|
95
|
+
if (!sp)
|
|
96
|
+
return null;
|
|
97
|
+
const lines = linesOf(src.path);
|
|
98
|
+
for (let ln = sp[0] - 1; ln < Math.min(sp[0] + 2, lines.length); ln++) {
|
|
99
|
+
const c = (lines[ln] ?? "").indexOf(src.name);
|
|
100
|
+
if (c >= 0)
|
|
101
|
+
return { line: ln, character: c };
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
};
|
|
105
|
+
// Wait for the server to finish indexing (it answers call-hierarchy empty
|
|
106
|
+
// until ready). Warm up on the first source node that has a findable position.
|
|
107
|
+
const warm = sources.find((s) => namePos(s));
|
|
108
|
+
if (warm) {
|
|
109
|
+
const wp = namePos(warm);
|
|
110
|
+
if (!(await client.waitUntilReady(join(root, warm.path), wp))) {
|
|
111
|
+
await client.dispose();
|
|
112
|
+
return { added: 0, queried: 0, server: server.command }; // never became ready
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
let added = 0, queried = 0;
|
|
116
|
+
for (const src of sources) {
|
|
117
|
+
const abs = join(root, src.path);
|
|
118
|
+
client.didOpen(abs);
|
|
119
|
+
const pos = namePos(src);
|
|
120
|
+
if (!pos)
|
|
121
|
+
continue;
|
|
122
|
+
const items = await client.prepareCallHierarchy(abs, pos);
|
|
123
|
+
if (!items.length)
|
|
124
|
+
continue;
|
|
125
|
+
queried++;
|
|
126
|
+
opts.onProgress?.(queried, sources.length);
|
|
127
|
+
const callees = await client.outgoingCalls(items[0]);
|
|
128
|
+
for (const callee of callees) {
|
|
129
|
+
let calleeAbs;
|
|
130
|
+
try {
|
|
131
|
+
calleeAbs = fileURLToPath(callee.uri);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
const rel = relPosix(root, calleeAbs);
|
|
137
|
+
// In-repo iff the repo-relative path doesn't escape the root. (A raw
|
|
138
|
+
// `startsWith(root)` is separator-unsafe: root=/a/foo matches /a/foo-bar.)
|
|
139
|
+
if (rel.startsWith("..") || rel.startsWith("/"))
|
|
140
|
+
continue; // external/dependency
|
|
141
|
+
const target = nodeAt(rel, (callee.selectionRange?.start.line ?? callee.range.start.line) + 1);
|
|
142
|
+
if (!target || target.id === src.id)
|
|
143
|
+
continue;
|
|
144
|
+
const key = `${src.id}\0calls\0${target.id}`;
|
|
145
|
+
if (existing.has(key))
|
|
146
|
+
continue;
|
|
147
|
+
existing.add(key);
|
|
148
|
+
graph.edges.push({ source: src.id, target: target.id, relation: "calls", confidence: "lsp_resolved" });
|
|
149
|
+
added++;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
await client.dispose();
|
|
153
|
+
return { added, queried, server: server.command };
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=enrich.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enrich.js","sourceRoot":"","sources":["../../../src/graph/lsp/enrich.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface LspServer {
|
|
2
|
+
/** graft language names (as produced by languageLabelOf/genericLangOf) this serves. */
|
|
3
|
+
languages: string[];
|
|
4
|
+
command: string;
|
|
5
|
+
args: string[];
|
|
6
|
+
/** the LSP `languageId` to tag opened documents with. */
|
|
7
|
+
languageId: string;
|
|
8
|
+
}
|
|
9
|
+
/** First-match-wins; ordering is priority. Extend by adding a row. */
|
|
10
|
+
export declare const LSP_SERVERS: readonly LspServer[];
|
|
11
|
+
/** Pick the highest-priority installed server that covers at least one of the
|
|
12
|
+
* languages present in the repo, with `command` resolved to an absolute path.
|
|
13
|
+
* Returns null if none is installed. */
|
|
14
|
+
export declare function pickServer(languagesPresent: Set<string>): LspServer | null;
|
|
15
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/graph/lsp/registry.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,uFAAuF;IACvF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,sEAAsE;AACtE,eAAO,MAAM,WAAW,EAAE,SAAS,SAAS,EAM3C,CAAC;AAeF;;wCAEwC;AACxC,wBAAgB,UAAU,CAAC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,SAAS,GAAG,IAAI,CAO1E"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LSP server registry — maps graft language names to a language server command.
|
|
3
|
+
* Only servers whose binary is actually on PATH are eligible; a missing binary
|
|
4
|
+
* simply means that language gets no LSP enrichment (the AST graph stands alone).
|
|
5
|
+
*/
|
|
6
|
+
import { execSync } from "node:child_process";
|
|
7
|
+
/** First-match-wins; ordering is priority. Extend by adding a row. */
|
|
8
|
+
export const LSP_SERVERS = [
|
|
9
|
+
{ languages: ["rust"], command: "rust-analyzer", args: [], languageId: "rust" },
|
|
10
|
+
{ languages: ["cpp", "c"], command: "clangd", args: ["--background-index"], languageId: "cpp" },
|
|
11
|
+
{ languages: ["go"], command: "gopls", args: [], languageId: "go" },
|
|
12
|
+
{ languages: ["python"], command: "pyright-langserver", args: ["--stdio"], languageId: "python" },
|
|
13
|
+
{ languages: ["typescript", "javascript", "tsx"], command: "typescript-language-server", args: ["--stdio"], languageId: "typescript" },
|
|
14
|
+
];
|
|
15
|
+
const resolved = new Map();
|
|
16
|
+
/** Resolve a command to its ABSOLUTE path via the login shell's PATH. `spawn`
|
|
17
|
+
* resolves against `process.env.PATH`, which often omits `~/.cargo/bin`,
|
|
18
|
+
* `~/go/bin`, etc. where these servers live — so `command -v` can find a server
|
|
19
|
+
* that `spawn(cmd)` then can't. Spawning the absolute path avoids that mismatch. */
|
|
20
|
+
function resolveCommand(cmd) {
|
|
21
|
+
if (resolved.has(cmd))
|
|
22
|
+
return resolved.get(cmd);
|
|
23
|
+
let abs = null;
|
|
24
|
+
try {
|
|
25
|
+
abs = execSync(`command -v ${cmd}`, { encoding: "utf8" }).trim() || null;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
abs = null;
|
|
29
|
+
}
|
|
30
|
+
resolved.set(cmd, abs);
|
|
31
|
+
return abs;
|
|
32
|
+
}
|
|
33
|
+
/** Pick the highest-priority installed server that covers at least one of the
|
|
34
|
+
* languages present in the repo, with `command` resolved to an absolute path.
|
|
35
|
+
* Returns null if none is installed. */
|
|
36
|
+
export function pickServer(languagesPresent) {
|
|
37
|
+
for (const s of LSP_SERVERS) {
|
|
38
|
+
if (!s.languages.some((l) => languagesPresent.has(l)))
|
|
39
|
+
continue;
|
|
40
|
+
const abs = resolveCommand(s.command);
|
|
41
|
+
if (abs)
|
|
42
|
+
return { ...s, command: abs };
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/graph/lsp/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAW9C,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE;IAC/E,EAAE,SAAS,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,oBAAoB,CAAC,EAAE,UAAU,EAAE,KAAK,EAAE;IAC/F,EAAE,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE;IACnE,EAAE,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,oBAAoB,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE;IACjG,EAAE,SAAS,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,4BAA4B,EAAE,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE;CACvI,CAAC;AAEF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAyB,CAAC;AAClD;;;oFAGoF;AACpF,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IACjD,IAAI,GAAG,GAAkB,IAAI,CAAC;IAC9B,IAAI,CAAC;QAAC,GAAG,GAAG,QAAQ,CAAC,cAAc,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,GAAG,GAAG,IAAI,CAAC;IAAC,CAAC;IACvG,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACvB,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;wCAEwC;AACxC,MAAM,UAAU,UAAU,CAAC,gBAA6B;IACtD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAAE,SAAS;QAChE,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,GAAG;YAAE,OAAO,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;IACzC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
(struct_specifier name: (type_identifier) @name body:(_)) @definition.class
|
|
2
|
+
|
|
3
|
+
(declaration type: (union_specifier name: (type_identifier) @name)) @definition.class
|
|
4
|
+
|
|
5
|
+
(function_declarator declarator: (identifier) @name) @definition.function
|
|
6
|
+
|
|
7
|
+
(type_definition declarator: (type_identifier) @name) @definition.type
|
|
8
|
+
|
|
9
|
+
(enum_specifier name: (type_identifier) @name) @definition.type
|
|
10
|
+
|
|
11
|
+
; graft: call sites (upstream c tags.scm is definition-only)
|
|
12
|
+
(call_expression
|
|
13
|
+
function: (identifier) @name) @reference.call
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
; C# tags — minimal, matched to the tree-sitter-wasms c_sharp grammar node types.
|
|
2
|
+
; (Upstream tree-sitter-c-sharp tags.scm references node types the bundled wasm
|
|
3
|
+
; grammar version lacks — "Bad node name 'type'" — so graft ships this instead.)
|
|
4
|
+
|
|
5
|
+
(class_declaration name: (identifier) @name) @definition.class
|
|
6
|
+
(interface_declaration name: (identifier) @name) @definition.interface
|
|
7
|
+
(struct_declaration (identifier) @name) @definition.struct
|
|
8
|
+
(enum_declaration name: (identifier) @name) @definition.enum
|
|
9
|
+
(record_declaration (identifier) @name) @definition.class
|
|
10
|
+
(method_declaration name: (identifier) @name) @definition.method
|
|
11
|
+
(constructor_declaration (identifier) @name) @definition.method
|
|
12
|
+
(property_declaration name: (identifier) @name) @definition.variable
|
|
13
|
+
(namespace_declaration name: (identifier) @name) @definition.module
|
|
14
|
+
|
|
15
|
+
(invocation_expression
|
|
16
|
+
function: [
|
|
17
|
+
(identifier) @name
|
|
18
|
+
(member_access_expression name: (identifier) @name)
|
|
19
|
+
]) @reference.call
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
(struct_specifier name: (type_identifier) @name body:(_)) @definition.class
|
|
2
|
+
|
|
3
|
+
(declaration type: (union_specifier name: (type_identifier) @name)) @definition.class
|
|
4
|
+
|
|
5
|
+
(function_declarator declarator: (identifier) @name) @definition.function
|
|
6
|
+
|
|
7
|
+
(function_declarator declarator: (field_identifier) @name) @definition.function
|
|
8
|
+
|
|
9
|
+
(function_declarator declarator: (qualified_identifier scope: (namespace_identifier) @local.scope name: (identifier) @name)) @definition.method
|
|
10
|
+
|
|
11
|
+
(type_definition declarator: (type_identifier) @name) @definition.type
|
|
12
|
+
|
|
13
|
+
(enum_specifier name: (type_identifier) @name) @definition.type
|
|
14
|
+
|
|
15
|
+
(class_specifier name: (type_identifier) @name) @definition.class
|
|
16
|
+
|
|
17
|
+
; graft: call sites (upstream cpp tags.scm is definition-only)
|
|
18
|
+
(call_expression
|
|
19
|
+
function: [
|
|
20
|
+
(identifier) @name
|
|
21
|
+
(field_expression field: (field_identifier) @name)
|
|
22
|
+
(qualified_identifier name: (identifier) @name)
|
|
23
|
+
]) @reference.call
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
; Definitions
|
|
2
|
+
|
|
3
|
+
; * modules and protocols
|
|
4
|
+
(call
|
|
5
|
+
target: (identifier) @ignore
|
|
6
|
+
(arguments (alias) @name)
|
|
7
|
+
(#any-of? @ignore "defmodule" "defprotocol")) @definition.module
|
|
8
|
+
|
|
9
|
+
; * functions/macros
|
|
10
|
+
(call
|
|
11
|
+
target: (identifier) @ignore
|
|
12
|
+
(arguments
|
|
13
|
+
[
|
|
14
|
+
; zero-arity functions with no parentheses
|
|
15
|
+
(identifier) @name
|
|
16
|
+
; regular function clause
|
|
17
|
+
(call target: (identifier) @name)
|
|
18
|
+
; function clause with a guard clause
|
|
19
|
+
(binary_operator
|
|
20
|
+
left: (call target: (identifier) @name)
|
|
21
|
+
operator: "when")
|
|
22
|
+
])
|
|
23
|
+
(#any-of? @ignore "def" "defp" "defdelegate" "defguard" "defguardp" "defmacro" "defmacrop" "defn" "defnp")) @definition.function
|
|
24
|
+
|
|
25
|
+
; References
|
|
26
|
+
|
|
27
|
+
; ignore calls to kernel/special-forms keywords
|
|
28
|
+
(call
|
|
29
|
+
target: (identifier) @ignore
|
|
30
|
+
(#any-of? @ignore "def" "defp" "defdelegate" "defguard" "defguardp" "defmacro" "defmacrop" "defn" "defnp" "defmodule" "defprotocol" "defimpl" "defstruct" "defexception" "defoverridable" "alias" "case" "cond" "else" "for" "if" "import" "quote" "raise" "receive" "require" "reraise" "super" "throw" "try" "unless" "unquote" "unquote_splicing" "use" "with"))
|
|
31
|
+
|
|
32
|
+
; ignore module attributes
|
|
33
|
+
(unary_operator
|
|
34
|
+
operator: "@"
|
|
35
|
+
operand: (call
|
|
36
|
+
target: (identifier) @ignore))
|
|
37
|
+
|
|
38
|
+
; * function call
|
|
39
|
+
(call
|
|
40
|
+
target: [
|
|
41
|
+
; local
|
|
42
|
+
(identifier) @name
|
|
43
|
+
; remote
|
|
44
|
+
(dot
|
|
45
|
+
right: (identifier) @name)
|
|
46
|
+
]) @reference.call
|
|
47
|
+
|
|
48
|
+
; * pipe into function call
|
|
49
|
+
(binary_operator
|
|
50
|
+
operator: "|>"
|
|
51
|
+
right: (identifier) @name) @reference.call
|
|
52
|
+
|
|
53
|
+
; * modules
|
|
54
|
+
(alias) @name @reference.module
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
(class_declaration
|
|
2
|
+
name: (identifier) @name) @definition.class
|
|
3
|
+
|
|
4
|
+
(method_declaration
|
|
5
|
+
name: (identifier) @name) @definition.method
|
|
6
|
+
|
|
7
|
+
(method_invocation
|
|
8
|
+
name: (identifier) @name
|
|
9
|
+
arguments: (argument_list) @reference.call)
|
|
10
|
+
|
|
11
|
+
(interface_declaration
|
|
12
|
+
name: (identifier) @name) @definition.interface
|
|
13
|
+
|
|
14
|
+
(type_list
|
|
15
|
+
(type_identifier) @name) @reference.implementation
|
|
16
|
+
|
|
17
|
+
(object_creation_expression
|
|
18
|
+
type: (type_identifier) @name) @reference.class
|
|
19
|
+
|
|
20
|
+
(superclass (type_identifier) @name) @reference.class
|