@mrclrchtr/supi-code-intelligence 4.10.0 → 5.0.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 +2 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-core/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/README.md +80 -5
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +7 -6
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +10 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +206 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +78 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-collection.ts +114 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-evidence.ts +372 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-host.ts +14 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-pull.ts +62 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +491 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-request.ts +9 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +71 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-waiters.ts +206 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +365 -297
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-state.ts +52 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-document-sync.ts +185 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-file-state.ts +25 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +467 -115
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +161 -33
- package/node_modules/@mrclrchtr/supi-lsp/src/config/capabilities.ts +10 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/defaults.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +45 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +38 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +79 -9
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +13 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +300 -24
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +464 -96
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-refactor-provider.ts +130 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +45 -329
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/refactor-planning.ts +57 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-edit-normalizer.ts +320 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +207 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/readiness.ts +72 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +151 -26
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostic-surface.ts +40 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +50 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +136 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +49 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +102 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +17 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/api.ts +9 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +53 -13
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/request-control.ts +47 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-code-runtime/src/types.ts +13 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config.ts +2 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +19 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +3 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/LICENSE +21 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/README.md +258 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/babel.cjs +257 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/dist/jiti.cjs +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-cli.mjs +34 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-hooks.mjs +124 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-native.mjs +121 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.d.mts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-register.mjs +4 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti-static.mjs +23 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.cjs +30 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.cts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.d.mts +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/jiti.mjs +29 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/lib/types.d.ts +420 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/jiti/package.json +146 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +6 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +0 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +16 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +65 -87
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +47 -95
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-timing.ts +147 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client-lifecycle.ts +39 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +561 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-message-size.ts +24 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +452 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +12 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/imports.ts +4 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +5 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +33 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/blocking-test-bootstrap.mjs +34 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/bootstrap.mjs +8 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store-helpers.ts +23 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +400 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/request-control.ts +48 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-parser-helpers.ts +24 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime-query-helpers.ts +43 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +421 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +116 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +201 -0
- package/package.json +5 -5
- package/src/analysis/health/diagnostics.ts +236 -24
- package/src/analysis/health/recovery.ts +6 -2
- package/src/analysis/provider.ts +58 -0
- package/src/analysis/readiness.ts +30 -9
- package/src/analysis/refactor/apply.ts +45 -1
- package/src/analysis/refactor/mutation-authority.ts +143 -0
- package/src/analysis/relations/callees.ts +9 -1
- package/src/analysis/relations/types.ts +5 -2
- package/src/analysis/search/ast-scan-timing.ts +9 -2
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/analysis/search/deadline.ts +2 -2
- package/src/analysis/search/pattern-analysis.ts +46 -32
- package/src/analysis/search/pattern.ts +12 -2
- package/src/analysis/target/anchored.ts +20 -11
- package/src/analysis/target/file.ts +18 -11
- package/src/analysis/target/identity.ts +19 -3
- package/src/analysis/target/symbol.ts +36 -15
- package/src/api.ts +4 -0
- package/src/diagnostics/evidence.ts +51 -0
- package/src/session/capability-adapter.ts +12 -3
- package/src/session/find-workflow.ts +17 -7
- package/src/session/graph/collect.ts +18 -2
- package/src/session/graph-workflow.ts +19 -12
- package/src/session/health-refresh.ts +148 -0
- package/src/session/health-types.ts +37 -15
- package/src/session/health-workflow.ts +37 -39
- package/src/session/inspect/collect.ts +20 -3
- package/src/session/inspect-workflow.ts +10 -5
- package/src/session/orientation/collect.ts +10 -1
- package/src/session/orientation/context-facts.ts +3 -1
- package/src/session/orientation/context-sections.ts +20 -7
- package/src/session/orientation/gather.ts +17 -11
- package/src/session/orientation-types.ts +2 -1
- package/src/session/orientation-workflow.ts +15 -8
- package/src/session/refactor-plans.ts +2 -0
- package/src/session/refactor-workflow.ts +59 -14
- package/src/session/session.ts +4 -1
- package/src/session/target-workflow.ts +54 -23
- package/src/session/workflow-control.ts +7 -3
- package/src/substrate/lsp/lifecycle.ts +26 -46
- package/src/substrate/lsp/maintenance.ts +199 -25
- package/src/substrate/lsp/state.ts +2 -2
- package/src/substrate/workspace-provider-host.ts +25 -3
- package/src/tool/find/execute.ts +7 -1
- package/src/tool/find/render.ts +20 -3
- package/src/tool/find/tui.ts +23 -21
- package/src/tool/graph/execute.ts +23 -3
- package/src/tool/graph/tui.ts +59 -46
- package/src/tool/health/execute.ts +7 -2
- package/src/tool/health/markdown.ts +56 -14
- package/src/tool/health/refresh-status.ts +105 -0
- package/src/tool/health/tui.ts +95 -98
- package/src/tool/infra/workflow-control.ts +8 -0
- package/src/tool/inspect/execute.ts +7 -1
- package/src/tool/inspect/tui.ts +26 -18
- package/src/tool/orientation/execute.ts +21 -3
- package/src/tool/orientation/tui.ts +51 -35
- package/src/tool/refactor-apply/execute.ts +3 -0
- package/src/tool/refactor-apply/tui.ts +43 -25
- package/src/tool/refactor-plan/execute.ts +4 -0
- package/src/tool/refactor-plan/tui.ts +33 -20
- package/src/tool/register.ts +127 -22
- package/src/tool/resolve/execute.ts +18 -1
- package/src/tool/resolve/tui.ts +42 -24
- package/src/tool/result/display.ts +107 -0
- package/src/tool/result/errors.ts +20 -17
- package/src/tool/result/find.ts +52 -8
- package/src/tool/result/graph.ts +44 -1
- package/src/tool/result/health.ts +53 -1
- package/src/tool/result/inspect.ts +113 -1
- package/src/tool/result/orientation.ts +66 -14
- package/src/tool/result/refactor.ts +36 -4
- package/src/tool/result/resolve.ts +44 -7
- package/src/tool/result/types.ts +20 -0
- package/src/types/execution.ts +18 -5
- package/src/types/index.ts +8 -1
- package/src/ui/status-command.ts +5 -3
- package/src/ui/status-overlay.ts +4 -0
- package/src/ui/tui/common.ts +108 -10
- package/src/ui/tui/display.ts +48 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime.ts +0 -351
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
// Tree-sitter runtime — parser management, parse, and query services.
|
|
2
|
-
|
|
3
|
-
import { createHash } from "node:crypto";
|
|
4
|
-
import * as fs from "node:fs";
|
|
5
|
-
import * as path from "node:path";
|
|
6
|
-
import { startDebugTimer } from "@mrclrchtr/supi-core/debug";
|
|
7
|
-
import { resolveToolPath } from "@mrclrchtr/supi-core/path";
|
|
8
|
-
import type { Language, Parser, Tree } from "web-tree-sitter";
|
|
9
|
-
import { nodeToRange } from "../coordinates.ts";
|
|
10
|
-
import { detectGrammar, resolveGrammarWasmPath } from "../language.ts";
|
|
11
|
-
import type { GrammarId, QueryCapture, TreeSitterResult } from "../types.ts";
|
|
12
|
-
|
|
13
|
-
interface ParserEntry {
|
|
14
|
-
parser: Parser;
|
|
15
|
-
language: Language;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Session-scoped Tree-sitter runtime.
|
|
20
|
-
*
|
|
21
|
-
* A runtime owns the expensive `web-tree-sitter` initialization and parser
|
|
22
|
-
* instances for one pi working directory. Call `dispose()` when the session is
|
|
23
|
-
* torn down so WASM parser resources are released.
|
|
24
|
-
*/
|
|
25
|
-
export class TreeSitterRuntime {
|
|
26
|
-
private parserModule: typeof import("web-tree-sitter") | undefined;
|
|
27
|
-
private parsers = new Map<GrammarId, ParserEntry>();
|
|
28
|
-
private parserPromises = new Map<GrammarId, Promise<ParserEntry>>();
|
|
29
|
-
private initPromise: Promise<typeof import("web-tree-sitter")> | undefined;
|
|
30
|
-
private initializing = false;
|
|
31
|
-
private disposed = false;
|
|
32
|
-
|
|
33
|
-
/** Create a runtime that resolves relative file paths from `cwd`. */
|
|
34
|
-
constructor(private cwd: string) {}
|
|
35
|
-
|
|
36
|
-
/** Ensure web-tree-sitter Parser is initialized. */
|
|
37
|
-
private async ensureParserInit(): Promise<typeof import("web-tree-sitter")> {
|
|
38
|
-
this.assertActive();
|
|
39
|
-
if (this.parserModule) return this.parserModule;
|
|
40
|
-
if (this.initializing && this.initPromise) return this.initPromise;
|
|
41
|
-
|
|
42
|
-
this.initializing = true;
|
|
43
|
-
this.initPromise = (async () => {
|
|
44
|
-
const mod = await import("web-tree-sitter");
|
|
45
|
-
await mod.Parser.init();
|
|
46
|
-
this.assertActive();
|
|
47
|
-
this.parserModule = mod;
|
|
48
|
-
return mod;
|
|
49
|
-
})();
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
return await this.initPromise;
|
|
53
|
-
} catch (err: unknown) {
|
|
54
|
-
// Allow retry on next call
|
|
55
|
-
this.initPromise = undefined;
|
|
56
|
-
this.initializing = false;
|
|
57
|
-
throw new Error("Failed to initialize web-tree-sitter", { cause: err });
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Get or create a parser entry for a grammar.
|
|
63
|
-
*
|
|
64
|
-
* Concurrent first-use calls for the same grammar share one initialization
|
|
65
|
-
* promise. Failed initialization is not cached, so a later request can retry.
|
|
66
|
-
*/
|
|
67
|
-
async ensureGrammarParser(grammarId: GrammarId): Promise<ParserEntry> {
|
|
68
|
-
this.assertActive();
|
|
69
|
-
const existing = this.parsers.get(grammarId);
|
|
70
|
-
if (existing) return existing;
|
|
71
|
-
|
|
72
|
-
const pending = this.parserPromises.get(grammarId);
|
|
73
|
-
if (pending) return pending;
|
|
74
|
-
|
|
75
|
-
const promise = this.createGrammarParser(grammarId);
|
|
76
|
-
this.parserPromises.set(grammarId, promise);
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
return await promise;
|
|
80
|
-
} finally {
|
|
81
|
-
if (this.parserPromises.get(grammarId) === promise) {
|
|
82
|
-
this.parserPromises.delete(grammarId);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
private async createGrammarParser(grammarId: GrammarId): Promise<ParserEntry> {
|
|
88
|
-
const mod = await this.ensureParserInit();
|
|
89
|
-
const wasmPath = resolveGrammarWasmPath(grammarId);
|
|
90
|
-
|
|
91
|
-
const language = await mod.Language.load(wasmPath);
|
|
92
|
-
const parser = new mod.Parser();
|
|
93
|
-
try {
|
|
94
|
-
parser.setLanguage(language);
|
|
95
|
-
} catch (err) {
|
|
96
|
-
parser.delete();
|
|
97
|
-
throw err;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (this.disposed) {
|
|
101
|
-
parser.delete();
|
|
102
|
-
throw new Error("Tree-sitter runtime has been disposed");
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const entry = { parser, language };
|
|
106
|
-
this.parsers.set(grammarId, entry);
|
|
107
|
-
return entry;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/** Read and parse a file. Returns structured result. */
|
|
111
|
-
async parseFile(filePath: string): Promise<
|
|
112
|
-
TreeSitterResult<{
|
|
113
|
-
tree: Tree;
|
|
114
|
-
source: string;
|
|
115
|
-
resolvedPath: string;
|
|
116
|
-
grammarId: GrammarId;
|
|
117
|
-
}>
|
|
118
|
-
> {
|
|
119
|
-
const resolvedPath = resolveToolPath(this.cwd, filePath);
|
|
120
|
-
|
|
121
|
-
// Check language support first
|
|
122
|
-
const grammarId = detectGrammar(filePath);
|
|
123
|
-
if (!grammarId) {
|
|
124
|
-
return {
|
|
125
|
-
kind: "unsupported-language",
|
|
126
|
-
file: filePath,
|
|
127
|
-
message: `No Tree-sitter grammar configured for ${path.extname(filePath) || "this file type"}`,
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const timer = startDebugTimer();
|
|
132
|
-
const parserState = this.parsers.has(grammarId)
|
|
133
|
-
? "reused"
|
|
134
|
-
: this.parserPromises.has(grammarId)
|
|
135
|
-
? "initializing"
|
|
136
|
-
: "cold";
|
|
137
|
-
|
|
138
|
-
// Read the file
|
|
139
|
-
let source: string;
|
|
140
|
-
try {
|
|
141
|
-
source = fs.readFileSync(resolvedPath, "utf-8");
|
|
142
|
-
} catch (err: unknown) {
|
|
143
|
-
finishStructuralTiming(timer, {
|
|
144
|
-
operation: "parse",
|
|
145
|
-
grammar: grammarId,
|
|
146
|
-
parserState,
|
|
147
|
-
outcome: "file-access-error",
|
|
148
|
-
finalPhase: "file-read",
|
|
149
|
-
});
|
|
150
|
-
const message = err instanceof Error ? err.message : "File could not be read";
|
|
151
|
-
return {
|
|
152
|
-
kind: "file-access-error",
|
|
153
|
-
file: filePath,
|
|
154
|
-
message,
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
timer.mark("file-read");
|
|
158
|
-
|
|
159
|
-
if (timer.enabled) {
|
|
160
|
-
try {
|
|
161
|
-
createHash("sha256").update(source).digest();
|
|
162
|
-
} catch {
|
|
163
|
-
// Timing-only hashing must not change structural behavior.
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
timer.mark("content-hash");
|
|
167
|
-
|
|
168
|
-
let parserReady = false;
|
|
169
|
-
try {
|
|
170
|
-
const entry = await this.ensureGrammarParser(grammarId);
|
|
171
|
-
timer.mark("parser-setup");
|
|
172
|
-
parserReady = true;
|
|
173
|
-
const tree = entry.parser.parse(source);
|
|
174
|
-
finishStructuralTiming(timer, {
|
|
175
|
-
operation: "parse",
|
|
176
|
-
grammar: grammarId,
|
|
177
|
-
parserState,
|
|
178
|
-
outcome: "completed",
|
|
179
|
-
finalPhase: "parse",
|
|
180
|
-
});
|
|
181
|
-
return {
|
|
182
|
-
kind: "success",
|
|
183
|
-
data: { tree: tree as Tree, source, resolvedPath, grammarId },
|
|
184
|
-
};
|
|
185
|
-
} catch (err: unknown) {
|
|
186
|
-
finishStructuralTiming(timer, {
|
|
187
|
-
operation: "parse",
|
|
188
|
-
grammar: grammarId,
|
|
189
|
-
parserState,
|
|
190
|
-
outcome: "runtime-error",
|
|
191
|
-
finalPhase: parserReady ? "parse" : "parser-setup",
|
|
192
|
-
});
|
|
193
|
-
return { kind: "runtime-error", message: formatError(err, "Parser initialization failed") };
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** Execute a Tree-sitter query against a file. */
|
|
198
|
-
async queryFile(
|
|
199
|
-
filePath: string,
|
|
200
|
-
queryString: string,
|
|
201
|
-
): Promise<TreeSitterResult<QueryCapture[]>> {
|
|
202
|
-
if (!queryString || queryString.trim().length === 0) {
|
|
203
|
-
return { kind: "validation-error", message: "query is required and must be non-empty" };
|
|
204
|
-
}
|
|
205
|
-
if (queryString.length > MAX_QUERY_LENGTH) {
|
|
206
|
-
return {
|
|
207
|
-
kind: "validation-error",
|
|
208
|
-
message: `query exceeds maximum length of ${MAX_QUERY_LENGTH} characters`,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const parseResult = await this.parseFile(filePath);
|
|
213
|
-
if (parseResult.kind !== "success") return parseResult;
|
|
214
|
-
|
|
215
|
-
const { grammarId, tree, source } = parseResult.data;
|
|
216
|
-
const timer = startDebugTimer();
|
|
217
|
-
let compiled = false;
|
|
218
|
-
|
|
219
|
-
try {
|
|
220
|
-
const entry = await this.ensureGrammarParser(grammarId);
|
|
221
|
-
const mod = await this.ensureParserInit();
|
|
222
|
-
let query: InstanceType<typeof mod.Query>;
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
query = new mod.Query(entry.language, queryString);
|
|
226
|
-
compiled = true;
|
|
227
|
-
timer.mark("query-compilation");
|
|
228
|
-
} catch (err: unknown) {
|
|
229
|
-
finishStructuralTiming(timer, {
|
|
230
|
-
operation: "query",
|
|
231
|
-
grammar: grammarId,
|
|
232
|
-
outcome: "validation-error",
|
|
233
|
-
captureCount: 0,
|
|
234
|
-
finalPhase: "query-compilation",
|
|
235
|
-
});
|
|
236
|
-
return { kind: "validation-error", message: `Invalid query: ${formatError(err)}` };
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
try {
|
|
240
|
-
const matches = query.matches(tree.rootNode);
|
|
241
|
-
const captures: QueryCapture[] = [];
|
|
242
|
-
for (const match of matches) {
|
|
243
|
-
for (const { name, node } of match.captures) {
|
|
244
|
-
captures.push({
|
|
245
|
-
name,
|
|
246
|
-
nodeType: node.type,
|
|
247
|
-
range: nodeToRange(node, source),
|
|
248
|
-
text: node.text,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
finishStructuralTiming(timer, {
|
|
253
|
-
operation: "query",
|
|
254
|
-
grammar: grammarId,
|
|
255
|
-
outcome: "completed",
|
|
256
|
-
captureCount: captures.length,
|
|
257
|
-
finalPhase: "query-execution",
|
|
258
|
-
});
|
|
259
|
-
return { kind: "success", data: captures };
|
|
260
|
-
} finally {
|
|
261
|
-
query.delete();
|
|
262
|
-
}
|
|
263
|
-
} catch (err: unknown) {
|
|
264
|
-
finishStructuralTiming(timer, {
|
|
265
|
-
operation: "query",
|
|
266
|
-
grammar: grammarId,
|
|
267
|
-
outcome: "runtime-error",
|
|
268
|
-
captureCount: 0,
|
|
269
|
-
finalPhase: compiled ? "query-execution" : "query-compilation",
|
|
270
|
-
});
|
|
271
|
-
return { kind: "runtime-error", message: formatError(err, "Query execution failed") };
|
|
272
|
-
} finally {
|
|
273
|
-
tree.delete();
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
/** Get the grammar ID for a file, or undefined if unsupported. */
|
|
278
|
-
getGrammarId(filePath: string): GrammarId | undefined {
|
|
279
|
-
return detectGrammar(filePath);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
/** Resolve a file path from cwd. */
|
|
283
|
-
resolvePath(filePath: string): string {
|
|
284
|
-
return resolveToolPath(this.cwd, filePath);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
/** Dispose all held parser resources. */
|
|
288
|
-
dispose(): void {
|
|
289
|
-
this.disposed = true;
|
|
290
|
-
for (const [, entry] of this.parsers) {
|
|
291
|
-
entry.parser.delete();
|
|
292
|
-
}
|
|
293
|
-
this.parsers.clear();
|
|
294
|
-
this.parserPromises.clear();
|
|
295
|
-
this.parserModule = undefined;
|
|
296
|
-
this.initPromise = undefined;
|
|
297
|
-
this.initializing = false;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
private assertActive(): void {
|
|
301
|
-
if (this.disposed) {
|
|
302
|
-
throw new Error("Tree-sitter runtime has been disposed");
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/** Max query string length to prevent ReDoS via overly complex Tree-sitter patterns. */
|
|
308
|
-
const MAX_QUERY_LENGTH = 10_000;
|
|
309
|
-
|
|
310
|
-
type StructuralTimer = ReturnType<typeof startDebugTimer>;
|
|
311
|
-
type ParserState = "cold" | "initializing" | "reused";
|
|
312
|
-
|
|
313
|
-
type StructuralTimingObservation =
|
|
314
|
-
| {
|
|
315
|
-
readonly operation: "parse";
|
|
316
|
-
readonly grammar: GrammarId;
|
|
317
|
-
readonly parserState: ParserState;
|
|
318
|
-
readonly outcome: "completed" | "file-access-error" | "runtime-error";
|
|
319
|
-
readonly finalPhase: "file-read" | "parse" | "parser-setup";
|
|
320
|
-
}
|
|
321
|
-
| {
|
|
322
|
-
readonly operation: "query";
|
|
323
|
-
readonly grammar: GrammarId;
|
|
324
|
-
readonly outcome: "completed" | "runtime-error" | "validation-error";
|
|
325
|
-
readonly captureCount: number;
|
|
326
|
-
readonly finalPhase: "query-compilation" | "query-execution";
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
function finishStructuralTiming(
|
|
330
|
-
timer: StructuralTimer,
|
|
331
|
-
observation: StructuralTimingObservation,
|
|
332
|
-
): void {
|
|
333
|
-
const { finalPhase, ...data } = observation;
|
|
334
|
-
timer.finish(
|
|
335
|
-
() => ({
|
|
336
|
-
source: "tree-sitter",
|
|
337
|
-
level: "debug",
|
|
338
|
-
category: `structural.${data.operation}.timing`,
|
|
339
|
-
message: `Tree-sitter ${data.operation} ${data.outcome}`,
|
|
340
|
-
data: { ...data },
|
|
341
|
-
}),
|
|
342
|
-
finalPhase,
|
|
343
|
-
);
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/** Format errors with their cause chain's first message for user-facing tool output. */
|
|
347
|
-
function formatError(err: unknown, fallback = "Operation failed"): string {
|
|
348
|
-
if (!(err instanceof Error)) return String(err || fallback);
|
|
349
|
-
if (err.cause instanceof Error) return `${err.message}: ${err.cause.message}`;
|
|
350
|
-
return err.message || fallback;
|
|
351
|
-
}
|