@mrclrchtr/supi-tree-sitter 0.1.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 +97 -0
- package/package.json +67 -0
- package/resources/.gitkeep +0 -0
- package/resources/grammars/bash/tree-sitter-bash.wasm +0 -0
- package/resources/grammars/bash/tree-sitter-bash.wasm.json +7 -0
- package/resources/grammars/c/tree-sitter-c.wasm +0 -0
- package/resources/grammars/c/tree-sitter-c.wasm.json +7 -0
- package/resources/grammars/cpp/tree-sitter-cpp.wasm +0 -0
- package/resources/grammars/cpp/tree-sitter-cpp.wasm.json +7 -0
- package/resources/grammars/go/tree-sitter-go.wasm +0 -0
- package/resources/grammars/go/tree-sitter-go.wasm.json +7 -0
- package/resources/grammars/html/tree-sitter-html.wasm +0 -0
- package/resources/grammars/html/tree-sitter-html.wasm.json +7 -0
- package/resources/grammars/java/tree-sitter-java.wasm +0 -0
- package/resources/grammars/java/tree-sitter-java.wasm.json +7 -0
- package/resources/grammars/javascript/tree-sitter-javascript.wasm +0 -0
- package/resources/grammars/javascript/tree-sitter-javascript.wasm.json +7 -0
- package/resources/grammars/kotlin/tree-sitter-kotlin.wasm +0 -0
- package/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +12 -0
- package/resources/grammars/python/tree-sitter-python.wasm +0 -0
- package/resources/grammars/python/tree-sitter-python.wasm.json +7 -0
- package/resources/grammars/r/tree-sitter-r.wasm +0 -0
- package/resources/grammars/r/tree-sitter-r.wasm.json +7 -0
- package/resources/grammars/ruby/tree-sitter-ruby.wasm +0 -0
- package/resources/grammars/ruby/tree-sitter-ruby.wasm.json +7 -0
- package/resources/grammars/rust/tree-sitter-rust.wasm +0 -0
- package/resources/grammars/rust/tree-sitter-rust.wasm.json +7 -0
- package/resources/grammars/sql/tree-sitter-sql.wasm +0 -0
- package/resources/grammars/sql/tree-sitter-sql.wasm.json +19 -0
- package/resources/grammars/tsx/tree-sitter-tsx.wasm +0 -0
- package/resources/grammars/tsx/tree-sitter-tsx.wasm.json +7 -0
- package/resources/grammars/typescript/tree-sitter-typescript.wasm +0 -0
- package/resources/grammars/typescript/tree-sitter-typescript.wasm.json +7 -0
- package/scripts/generate-kotlin-wasm.mjs +126 -0
- package/scripts/generate-sql-wasm.mjs +144 -0
- package/scripts/vendor-wasm.mjs +151 -0
- package/src/callees.ts +343 -0
- package/src/coordinates.ts +108 -0
- package/src/exports.ts +315 -0
- package/src/formatting.ts +104 -0
- package/src/imports.ts +42 -0
- package/src/index.ts +16 -0
- package/src/language.ts +116 -0
- package/src/node-at.ts +96 -0
- package/src/outline.ts +287 -0
- package/src/runtime.ts +237 -0
- package/src/session.ts +112 -0
- package/src/structure.ts +7 -0
- package/src/syntax-node.ts +13 -0
- package/src/tree-sitter.ts +306 -0
- package/src/types.ts +146 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// Tree-sitter extension entry point — registers the `tree_sitter` tool with pi.
|
|
2
|
+
|
|
3
|
+
import { StringEnum } from "@earendil-works/pi-ai";
|
|
4
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
5
|
+
import { Type } from "typebox";
|
|
6
|
+
import {
|
|
7
|
+
formatNonSuccess,
|
|
8
|
+
formatOutlineItemsCapped,
|
|
9
|
+
MAX_ITEMS,
|
|
10
|
+
truncate,
|
|
11
|
+
truncatedNotice,
|
|
12
|
+
truncateText,
|
|
13
|
+
validationError,
|
|
14
|
+
} from "./formatting.ts";
|
|
15
|
+
import { detectGrammar, isJsTsGrammar } from "./language.ts";
|
|
16
|
+
import { collectOutline } from "./outline.ts";
|
|
17
|
+
import { TreeSitterRuntime } from "./runtime.ts";
|
|
18
|
+
import { extractExports, extractImports, lookupCalleesAt, lookupNodeAt } from "./structure.ts";
|
|
19
|
+
|
|
20
|
+
const TreeSitterActionEnum = StringEnum([
|
|
21
|
+
"outline",
|
|
22
|
+
"imports",
|
|
23
|
+
"exports",
|
|
24
|
+
"node_at",
|
|
25
|
+
"query",
|
|
26
|
+
"callees",
|
|
27
|
+
] as const);
|
|
28
|
+
|
|
29
|
+
const toolDescription = `Tree-sitter tool — provides structural AST analysis for supported files.
|
|
30
|
+
|
|
31
|
+
Actions:
|
|
32
|
+
- outline: Extract structural declarations (functions, classes, interfaces, etc.). JavaScript/TypeScript only.
|
|
33
|
+
- imports: List import statements with module specifiers. JavaScript/TypeScript only.
|
|
34
|
+
- exports: List export declarations, re-exports, and export assignments with names and kinds. JavaScript/TypeScript only.
|
|
35
|
+
- node_at: Find the syntax node at a position. Params: file, line, character
|
|
36
|
+
- query: Run a Tree-sitter query. Params: file, query
|
|
37
|
+
- callees: Find outgoing function/method calls from a position. Params: file, line, character. Supported for most grammars.
|
|
38
|
+
|
|
39
|
+
Coordinates are 1-based (line, character), compatible with the lsp tool convention.
|
|
40
|
+
Character is a UTF-16 code-unit column.
|
|
41
|
+
Relative file paths resolve from the session working directory.
|
|
42
|
+
|
|
43
|
+
Supported extensions: .ts, .tsx, .js, .jsx, .mts, .cts, .mjs, .cjs, .py, .pyi, .rs, .go, .mod, .c, .h, .cpp, .hpp, .cc, .cxx, .hxx, .c++, .h++, .java, .kt, .kts, .rb, .sh, .bash, .zsh, .html, .htm, .xhtml, .r, .sql`;
|
|
44
|
+
|
|
45
|
+
const promptGuidelines = [
|
|
46
|
+
"Use tree_sitter for structural syntax-tree analysis: extracting declarations, imports, exports, node-at-position lookup, and custom queries.",
|
|
47
|
+
"Prefer tree_sitter when you need AST node types, exact source ranges, or parser-level structure that semantic language-server tooling does not expose.",
|
|
48
|
+
"tree_sitter is a standalone structural analysis tool; use semantic language-server features separately when they are available for hover, definitions, references, or diagnostics.",
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const promptSnippet = `Use the tree_sitter tool for structural code analysis — outline, imports, exports, node-at-position lookup, and custom queries.`;
|
|
52
|
+
|
|
53
|
+
export default function treeSitterExtension(pi: ExtensionAPI) {
|
|
54
|
+
let runtime: TreeSitterRuntime | undefined;
|
|
55
|
+
|
|
56
|
+
pi.on("session_start", (_event, ctx) => {
|
|
57
|
+
runtime?.dispose();
|
|
58
|
+
runtime = new TreeSitterRuntime(ctx.cwd);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
pi.on("session_shutdown", () => {
|
|
62
|
+
runtime?.dispose();
|
|
63
|
+
runtime = undefined;
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
pi.registerTool({
|
|
67
|
+
name: "tree_sitter",
|
|
68
|
+
label: "Tree-sitter",
|
|
69
|
+
description: toolDescription,
|
|
70
|
+
promptGuidelines,
|
|
71
|
+
promptSnippet,
|
|
72
|
+
parameters: Type.Object({
|
|
73
|
+
action: TreeSitterActionEnum,
|
|
74
|
+
file: Type.Optional(Type.String({ description: "File path (relative or absolute)" })),
|
|
75
|
+
line: Type.Optional(Type.Number({ description: "1-based line number" })),
|
|
76
|
+
character: Type.Optional(Type.Number({ description: "1-based column number (UTF-16)" })),
|
|
77
|
+
query: Type.Optional(Type.String({ description: "Tree-sitter query string" })),
|
|
78
|
+
}),
|
|
79
|
+
// biome-ignore lint/complexity/useMaxParams: pi ToolDefinition.execute signature
|
|
80
|
+
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
81
|
+
if (!runtime) {
|
|
82
|
+
return {
|
|
83
|
+
content: [
|
|
84
|
+
{ type: "text", text: "Tree-sitter not initialized. Start a new session first." },
|
|
85
|
+
],
|
|
86
|
+
details: {},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const text = await executeToolAction(runtime, params);
|
|
91
|
+
return {
|
|
92
|
+
content: [{ type: "text", text }],
|
|
93
|
+
details: {},
|
|
94
|
+
};
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
type TreeSitterAction = "outline" | "imports" | "exports" | "node_at" | "query" | "callees";
|
|
100
|
+
|
|
101
|
+
type ToolParams = {
|
|
102
|
+
action?: string;
|
|
103
|
+
file?: string;
|
|
104
|
+
line?: number;
|
|
105
|
+
character?: number;
|
|
106
|
+
query?: string;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
async function executeToolAction(runtime: TreeSitterRuntime, params: ToolParams): Promise<string> {
|
|
110
|
+
if (!params.action) {
|
|
111
|
+
return validationError(
|
|
112
|
+
"`action` is required. Supported: outline, imports, exports, node_at, query, callees.",
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const action = toSupportedAction(params.action);
|
|
117
|
+
if (!action) {
|
|
118
|
+
return validationError(
|
|
119
|
+
`Unknown action: ${params.action}. Supported: outline, imports, exports, node_at, query, callees`,
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!params.file) {
|
|
124
|
+
return validationError("`file` is required for all actions.");
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (action === "outline") return handleOutline(runtime, params.file);
|
|
128
|
+
if (action === "imports") return handleImports(runtime, params.file);
|
|
129
|
+
if (action === "exports") return handleExports(runtime, params.file);
|
|
130
|
+
if (action === "node_at") return handleNodeAt(runtime, params);
|
|
131
|
+
if (action === "callees") return handleCallees(runtime, params);
|
|
132
|
+
return handleQuery(runtime, params);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
async function handleOutline(runtime: TreeSitterRuntime, file: string): Promise<string> {
|
|
136
|
+
const parseResult = await runtime.parseFile(file);
|
|
137
|
+
if (parseResult.kind !== "success") return formatNonSuccess(parseResult);
|
|
138
|
+
if (!isJsTsGrammar(parseResult.data.grammarId)) {
|
|
139
|
+
return `Unsupported language: outline is only supported for JavaScript and TypeScript files`;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const { tree, source } = parseResult.data;
|
|
143
|
+
let items: ReturnType<typeof collectOutline>;
|
|
144
|
+
try {
|
|
145
|
+
items = collectOutline(tree.rootNode, source);
|
|
146
|
+
} finally {
|
|
147
|
+
tree.delete();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (items.length === 0) return `No structural declarations found in ${file}`;
|
|
151
|
+
|
|
152
|
+
const lines = [`## Outline: ${file}`, ""];
|
|
153
|
+
const { omitted } = formatOutlineItemsCapped(items, lines, MAX_ITEMS);
|
|
154
|
+
if (omitted) lines.push("", truncatedNotice(omitted, "outline items"));
|
|
155
|
+
return lines.join("\n");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function handleImports(runtime: TreeSitterRuntime, file: string): Promise<string> {
|
|
159
|
+
const grammarId = detectGrammar(file);
|
|
160
|
+
if (grammarId && !isJsTsGrammar(grammarId)) {
|
|
161
|
+
return `Unsupported language: imports is only supported for JavaScript and TypeScript files`;
|
|
162
|
+
}
|
|
163
|
+
const result = await extractImports(runtime, file);
|
|
164
|
+
if (result.kind !== "success") return formatNonSuccess(result);
|
|
165
|
+
|
|
166
|
+
const { data: imports } = result;
|
|
167
|
+
if (imports.length === 0) return `No imports found in ${file}`;
|
|
168
|
+
|
|
169
|
+
const { included, truncated } = truncate(imports, MAX_ITEMS);
|
|
170
|
+
const lines = [`## Imports: ${file}`, ""];
|
|
171
|
+
for (const imp of included) {
|
|
172
|
+
const r = imp.range;
|
|
173
|
+
lines.push(`- "${imp.moduleSpecifier}" (L${r.startLine}:${r.startCharacter})`);
|
|
174
|
+
}
|
|
175
|
+
if (truncated) lines.push("", truncatedNotice(truncated, "imports"));
|
|
176
|
+
return lines.join("\n");
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async function handleExports(runtime: TreeSitterRuntime, file: string): Promise<string> {
|
|
180
|
+
const grammarId = detectGrammar(file);
|
|
181
|
+
if (grammarId && !isJsTsGrammar(grammarId)) {
|
|
182
|
+
return `Unsupported language: exports is only supported for JavaScript and TypeScript files`;
|
|
183
|
+
}
|
|
184
|
+
const result = await extractExports(runtime, file);
|
|
185
|
+
if (result.kind !== "success") return formatNonSuccess(result);
|
|
186
|
+
|
|
187
|
+
const { data: exports } = result;
|
|
188
|
+
if (exports.length === 0) return `No exports found in ${file}`;
|
|
189
|
+
|
|
190
|
+
const { included, truncated } = truncate(exports, MAX_ITEMS);
|
|
191
|
+
const lines = [`## Exports: ${file}`, ""];
|
|
192
|
+
for (const exp of included) {
|
|
193
|
+
const r = exp.range;
|
|
194
|
+
const from = exp.moduleSpecifier ? ` from "${exp.moduleSpecifier}"` : "";
|
|
195
|
+
lines.push(`- ${exp.kind}: ${exp.name}${from} (L${r.startLine}:${r.startCharacter})`);
|
|
196
|
+
}
|
|
197
|
+
if (truncated) lines.push("", truncatedNotice(truncated, "exports"));
|
|
198
|
+
return lines.join("\n");
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
async function handleNodeAt(runtime: TreeSitterRuntime, params: ToolParams): Promise<string> {
|
|
202
|
+
if (!Number.isInteger(params.line) || (params.line as number) < 1) {
|
|
203
|
+
return validationError("`line` must be a positive 1-based integer for node_at action.");
|
|
204
|
+
}
|
|
205
|
+
if (!Number.isInteger(params.character) || (params.character as number) < 1) {
|
|
206
|
+
return validationError("`character` must be a positive 1-based integer for node_at action.");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const file = params.file;
|
|
210
|
+
const line = params.line as number;
|
|
211
|
+
const character = params.character as number;
|
|
212
|
+
const result = await lookupNodeAt(runtime, file as string, line, character);
|
|
213
|
+
if (result.kind !== "success") return formatNonSuccess(result);
|
|
214
|
+
|
|
215
|
+
const { data } = result;
|
|
216
|
+
const lines = [
|
|
217
|
+
`## Node at ${file}:${line}:${character}`,
|
|
218
|
+
"",
|
|
219
|
+
`**Type:** ${data.type}`,
|
|
220
|
+
`**Range:** L${data.range.startLine}:${data.range.startCharacter} — L${data.range.endLine}:${data.range.endCharacter}`,
|
|
221
|
+
`**Text:** ${truncateText(data.text, 200)}`,
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
if (data.ancestry.length > 0) {
|
|
225
|
+
lines.push("", "**Ancestry:**");
|
|
226
|
+
const { included, truncated } = truncate(data.ancestry, MAX_ITEMS);
|
|
227
|
+
for (const ancestor of included) {
|
|
228
|
+
lines.push(
|
|
229
|
+
`- ${ancestor.type} (L${ancestor.range.startLine}:${ancestor.range.startCharacter}-L${ancestor.range.endLine}:${ancestor.range.endCharacter})`,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
if (truncated) lines.push("", truncatedNotice(truncated, "ancestry entries"));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return lines.join("\n");
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
async function handleQuery(runtime: TreeSitterRuntime, params: ToolParams): Promise<string> {
|
|
239
|
+
if (!params.query || params.query.trim().length === 0) {
|
|
240
|
+
return validationError("`query` is required and must be non-empty.");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const file = params.file as string;
|
|
244
|
+
const result = await runtime.queryFile(file, params.query);
|
|
245
|
+
if (result.kind !== "success") return formatNonSuccess(result);
|
|
246
|
+
|
|
247
|
+
const { data: captures } = result;
|
|
248
|
+
if (captures.length === 0) return `No matches for query in ${file}`;
|
|
249
|
+
|
|
250
|
+
const { included, truncated } = truncate(captures, MAX_ITEMS);
|
|
251
|
+
const lines = [`## Query results: ${file}`, ""];
|
|
252
|
+
for (const capture of included) {
|
|
253
|
+
const r = capture.range;
|
|
254
|
+
lines.push(
|
|
255
|
+
`- ${capture.name}: ${capture.nodeType} (L${r.startLine}:${r.startCharacter}-L${r.endLine}:${r.endCharacter})`,
|
|
256
|
+
);
|
|
257
|
+
lines.push(` \`${truncateText(capture.text, 120)}\``);
|
|
258
|
+
}
|
|
259
|
+
if (truncated) lines.push("", truncatedNotice(truncated, "captures"));
|
|
260
|
+
return lines.join("\n");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function toSupportedAction(action: string): TreeSitterAction | undefined {
|
|
264
|
+
if (["outline", "imports", "exports", "node_at", "query", "callees"].includes(action)) {
|
|
265
|
+
return action as TreeSitterAction;
|
|
266
|
+
}
|
|
267
|
+
return undefined;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function handleCallees(runtime: TreeSitterRuntime, params: ToolParams): Promise<string> {
|
|
271
|
+
if (!Number.isInteger(params.line) || (params.line as number) < 1) {
|
|
272
|
+
return validationError("`line` must be a positive 1-based integer for callees action.");
|
|
273
|
+
}
|
|
274
|
+
if (!Number.isInteger(params.character) || (params.character as number) < 1) {
|
|
275
|
+
return validationError("`character` must be a positive 1-based integer for callees action.");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const file = params.file as string;
|
|
279
|
+
const line = params.line as number;
|
|
280
|
+
const character = params.character as number;
|
|
281
|
+
|
|
282
|
+
const result = await lookupCalleesAt(runtime, file, line, character);
|
|
283
|
+
if (result.kind !== "success") return formatNonSuccess(result);
|
|
284
|
+
|
|
285
|
+
const { enclosingScope, callees } = result.data;
|
|
286
|
+
if (callees.length === 0) {
|
|
287
|
+
return `No outgoing calls found in \`${enclosingScope.name}\` at ${file}:${line}:${character}`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const lines: string[] = [];
|
|
291
|
+
lines.push(`## Callees: ${file}:${line}:${character}`);
|
|
292
|
+
lines.push("");
|
|
293
|
+
lines.push(
|
|
294
|
+
`**${callees.length} outgoing call${callees.length > 1 ? "s" : ""}** from \`${enclosingScope.name}\` at L${enclosingScope.range.startLine}-L${enclosingScope.range.endLine}`,
|
|
295
|
+
);
|
|
296
|
+
lines.push("");
|
|
297
|
+
|
|
298
|
+
for (const c of callees.slice(0, MAX_ITEMS)) {
|
|
299
|
+
lines.push(`- \`${c.name}\` (L${c.range.startLine})`);
|
|
300
|
+
}
|
|
301
|
+
if (callees.length > MAX_ITEMS) {
|
|
302
|
+
lines.push("", truncatedNotice(callees.length - MAX_ITEMS, "callees"));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return lines.join("\n");
|
|
306
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Public types for @mrclrchtr/supi-tree-sitter
|
|
2
|
+
|
|
3
|
+
/** 1-based source range compatible with LSP position convention. */
|
|
4
|
+
export interface SourceRange {
|
|
5
|
+
startLine: number;
|
|
6
|
+
startCharacter: number;
|
|
7
|
+
endLine: number;
|
|
8
|
+
endCharacter: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Discriminated result union for all service operations. */
|
|
12
|
+
export type TreeSitterResult<T> =
|
|
13
|
+
| { kind: "success"; data: T }
|
|
14
|
+
| { kind: "unsupported-language"; file: string; message: string }
|
|
15
|
+
| { kind: "file-access-error"; file: string; message: string }
|
|
16
|
+
| { kind: "validation-error"; message: string }
|
|
17
|
+
| { kind: "runtime-error"; message: string };
|
|
18
|
+
|
|
19
|
+
/** Structural outline item. */
|
|
20
|
+
export interface OutlineItem {
|
|
21
|
+
name: string;
|
|
22
|
+
kind: string;
|
|
23
|
+
range: SourceRange;
|
|
24
|
+
children?: OutlineItem[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Import record. */
|
|
28
|
+
export interface ImportRecord {
|
|
29
|
+
moduleSpecifier: string;
|
|
30
|
+
range: SourceRange;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Export record. */
|
|
34
|
+
export interface ExportRecord {
|
|
35
|
+
name: string;
|
|
36
|
+
kind: string;
|
|
37
|
+
range: SourceRange;
|
|
38
|
+
moduleSpecifier?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Node-at-position result. */
|
|
42
|
+
export interface NodeAtResult {
|
|
43
|
+
type: string;
|
|
44
|
+
range: SourceRange;
|
|
45
|
+
text: string;
|
|
46
|
+
ancestry: Array<{ type: string; range: SourceRange }>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Result from structural callee extraction. */
|
|
50
|
+
export interface CalleesAtResult {
|
|
51
|
+
enclosingScope: {
|
|
52
|
+
name: string;
|
|
53
|
+
range: SourceRange;
|
|
54
|
+
};
|
|
55
|
+
callees: Array<{
|
|
56
|
+
name: string;
|
|
57
|
+
range: SourceRange;
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Query capture result. */
|
|
62
|
+
export interface QueryCapture {
|
|
63
|
+
name: string;
|
|
64
|
+
nodeType: string;
|
|
65
|
+
range: SourceRange;
|
|
66
|
+
text: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Session-level Tree-sitter service. */
|
|
70
|
+
export interface TreeSitterSession {
|
|
71
|
+
/** Validate that a supported file can be read and parsed; does not expose the raw tree. */
|
|
72
|
+
canParse(file: string): Promise<TreeSitterResult<{ file: string; language: string }>>;
|
|
73
|
+
/** Run a Tree-sitter query and return all captures. */
|
|
74
|
+
query(file: string, queryString: string): Promise<TreeSitterResult<QueryCapture[]>>;
|
|
75
|
+
/** Extract top-level declarations plus supported class/interface/enum members. */
|
|
76
|
+
outline(file: string): Promise<TreeSitterResult<OutlineItem[]>>;
|
|
77
|
+
/** Extract static ES import declarations. */
|
|
78
|
+
imports(file: string): Promise<TreeSitterResult<ImportRecord[]>>;
|
|
79
|
+
/** Extract exported declarations, named exports, re-exports, and TS export assignments. */
|
|
80
|
+
exports(file: string): Promise<TreeSitterResult<ExportRecord[]>>;
|
|
81
|
+
/** Return the smallest syntax node at a 1-based UTF-16 position. */
|
|
82
|
+
nodeAt(file: string, line: number, character: number): Promise<TreeSitterResult<NodeAtResult>>;
|
|
83
|
+
/** Extract structural outgoing calls from the enclosing scope at a position. */
|
|
84
|
+
calleesAt(
|
|
85
|
+
file: string,
|
|
86
|
+
line: number,
|
|
87
|
+
character: number,
|
|
88
|
+
): Promise<TreeSitterResult<CalleesAtResult>>;
|
|
89
|
+
/** Release parser and grammar resources owned by this session. */
|
|
90
|
+
dispose(): void;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Supported grammar identifiers. */
|
|
94
|
+
export type GrammarId =
|
|
95
|
+
| "javascript"
|
|
96
|
+
| "typescript"
|
|
97
|
+
| "tsx"
|
|
98
|
+
| "python"
|
|
99
|
+
| "rust"
|
|
100
|
+
| "go"
|
|
101
|
+
| "c"
|
|
102
|
+
| "cpp"
|
|
103
|
+
| "java"
|
|
104
|
+
| "kotlin"
|
|
105
|
+
| "ruby"
|
|
106
|
+
| "bash"
|
|
107
|
+
| "html"
|
|
108
|
+
| "r"
|
|
109
|
+
| "sql";
|
|
110
|
+
|
|
111
|
+
/** Supported file extension. */
|
|
112
|
+
export type SupportedExtension =
|
|
113
|
+
| ".ts"
|
|
114
|
+
| ".tsx"
|
|
115
|
+
| ".js"
|
|
116
|
+
| ".jsx"
|
|
117
|
+
| ".mts"
|
|
118
|
+
| ".cts"
|
|
119
|
+
| ".mjs"
|
|
120
|
+
| ".cjs"
|
|
121
|
+
| ".py"
|
|
122
|
+
| ".pyi"
|
|
123
|
+
| ".rs"
|
|
124
|
+
| ".go"
|
|
125
|
+
| ".mod"
|
|
126
|
+
| ".c"
|
|
127
|
+
| ".h"
|
|
128
|
+
| ".cpp"
|
|
129
|
+
| ".hpp"
|
|
130
|
+
| ".cc"
|
|
131
|
+
| ".cxx"
|
|
132
|
+
| ".hxx"
|
|
133
|
+
| ".c++"
|
|
134
|
+
| ".h++"
|
|
135
|
+
| ".java"
|
|
136
|
+
| ".kt"
|
|
137
|
+
| ".kts"
|
|
138
|
+
| ".rb"
|
|
139
|
+
| ".sh"
|
|
140
|
+
| ".bash"
|
|
141
|
+
| ".zsh"
|
|
142
|
+
| ".html"
|
|
143
|
+
| ".htm"
|
|
144
|
+
| ".xhtml"
|
|
145
|
+
| ".r"
|
|
146
|
+
| ".sql";
|