@mrclrchtr/supi-tree-sitter 6.0.1 → 6.2.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 +6 -18
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +5 -0
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
- package/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
- package/package.json +3 -5
- package/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +1 -1
- package/resources/grammars/sql/tree-sitter-sql.wasm.json +1 -1
- package/src/api.ts +1 -11
- package/src/coordinates.ts +19 -0
- package/src/language.ts +5 -23
- package/src/operation-support.ts +3 -21
- package/src/provider/tree-sitter-provider.ts +5 -9
- package/src/session/runtime-controller.ts +10 -20
- package/src/session/session.ts +7 -1
- package/src/session/structural-worker-client.ts +9 -5
- package/src/session/structural-worker-protocol.ts +134 -9
- package/src/tool/call-name.ts +96 -0
- package/src/tool/call-sites.ts +11 -12
- package/src/tool/callees.ts +39 -56
- package/src/tool/exports.ts +9 -7
- package/src/tool/js-binding-pattern.ts +26 -0
- package/src/tool/node-at.ts +2 -21
- package/src/tool/outline-html-sql.ts +144 -12
- package/src/tool/outline.ts +50 -37
- package/src/tool/scope.ts +138 -0
- package/src/types.ts +0 -7
- package/src/worker/parsed-file-store.ts +1 -14
- package/src/worker/runtime.ts +0 -10
- package/src/worker/service.ts +6 -8
- package/src/worker/worker-main.ts +34 -10
- package/scripts/generate-kotlin-wasm.mjs +0 -132
- package/scripts/generate-sql-wasm.mjs +0 -158
- package/scripts/vendor-wasm.mjs +0 -167
- package/src/index.ts +0 -42
- package/src/session/runtime-registration.ts +0 -37
- package/src/session/service-registry.ts +0 -30
- package/src/tool/structure.ts +0 -8
package/README.md
CHANGED
|
@@ -25,7 +25,6 @@ npm install @mrclrchtr/supi-tree-sitter
|
|
|
25
25
|
|
|
26
26
|
This package provides the parser-backed structural substrate consumed by `@mrclrchtr/supi-code-intelligence`:
|
|
27
27
|
|
|
28
|
-
- a shared session-scoped Tree-sitter service for structural analysis
|
|
29
28
|
- an owned parsing session API for direct library consumers
|
|
30
29
|
- a `StructuralProvider` adapter published through `./provider/tree-sitter-provider`
|
|
31
30
|
- a long-lived owned Structural Worker that keeps Pi responsive during parser-backed work
|
|
@@ -59,18 +58,20 @@ Outline collection supports every listed family. HTML outlines contain elements
|
|
|
59
58
|
`@mrclrchtr/supi-tree-sitter` is the **structural substrate** in SuPi's
|
|
60
59
|
code-understanding stack. It depends on `@mrclrchtr/supi-core` and
|
|
61
60
|
`@mrclrchtr/supi-code-runtime` for shared contracts, and provides structural
|
|
62
|
-
analysis via a
|
|
63
|
-
|
|
61
|
+
analysis via a lifecycle controller that publishes its capabilities into
|
|
62
|
+
the shared workspace runtime.
|
|
64
63
|
|
|
65
64
|
```text
|
|
66
65
|
supi-code-runtime ← shared contracts + workspace runtime
|
|
67
66
|
↑
|
|
68
|
-
supi-tree-sitter ← one owned Structural Worker +
|
|
67
|
+
supi-tree-sitter ← one owned Structural Worker + runtime capabilities
|
|
69
68
|
```
|
|
70
69
|
|
|
71
70
|
## Package surfaces
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
There is no package-root export. Use one of these explicit subpaths:
|
|
73
|
+
|
|
74
|
+
- `@mrclrchtr/supi-tree-sitter/api` — reusable parsing session factory, lifecycle controller, language helpers, and shared result types
|
|
74
75
|
- `@mrclrchtr/supi-tree-sitter/provider/tree-sitter-provider` — shared StructuralProvider adapter
|
|
75
76
|
|
|
76
77
|
This is a **library-only** package. Public tool registration and pi event handlers belong to `@mrclrchtr/supi-code-intelligence`.
|
|
@@ -89,17 +90,6 @@ const callees = await session.calleesAt("src/index.ts", 42, 10);
|
|
|
89
90
|
await session.dispose();
|
|
90
91
|
```
|
|
91
92
|
|
|
92
|
-
Shared session-scoped service example:
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
import { getSessionTreeSitterService } from "@mrclrchtr/supi-tree-sitter/api";
|
|
96
|
-
|
|
97
|
-
const state = getSessionTreeSitterService("/project");
|
|
98
|
-
if (state.kind === "ready") {
|
|
99
|
-
const outline = await state.service.outline("src/index.ts");
|
|
100
|
-
}
|
|
101
|
-
```
|
|
102
|
-
|
|
103
93
|
## Structural performance baseline
|
|
104
94
|
|
|
105
95
|
Run the stable outline fixture on the same machine and dependency versions:
|
|
@@ -117,7 +107,6 @@ All structural service operations accept optional `CodeRequestControl`. The pare
|
|
|
117
107
|
## Source
|
|
118
108
|
|
|
119
109
|
- `src/api.ts` — public library entrypoint
|
|
120
|
-
- `src/index.ts` — re-export surface
|
|
121
110
|
- `src/worker/bootstrap.mjs` — package-owned Worker bootstrap and direct `jiti` loader
|
|
122
111
|
- `src/worker/runtime.ts` — Worker-only parser and query runtime
|
|
123
112
|
- `src/worker/parsed-file-store.ts` — Worker-only parsed-file and compiled-query reuse
|
|
@@ -125,6 +114,5 @@ All structural service operations accept optional `CodeRequestControl`. The pare
|
|
|
125
114
|
- `src/session/runtime-controller.ts` — generation-fenced shared Worker lifecycle
|
|
126
115
|
- `src/session/session.ts` — asynchronous Worker-proxy service and owned session API
|
|
127
116
|
- `src/operation-support.ts` — authoritative operation-specific extension support
|
|
128
|
-
- `src/session/service-registry.ts` — shared session-scoped structural service registry
|
|
129
117
|
- `src/provider/tree-sitter-provider.ts` — `StructuralProvider` adapter consumed by `@mrclrchtr/supi-code-intelligence`
|
|
130
118
|
- `src/tool/outline.ts`, `src/tool/outline-*.ts`, `src/tool/imports.ts`, `src/tool/exports.ts`, `src/tool/node-at.ts`, `src/tool/callees.ts`, `src/tool/call-sites.ts` — Worker-internal structural analyses
|
|
@@ -75,9 +75,14 @@ export interface SemanticProvider {
|
|
|
75
75
|
filePath: string,
|
|
76
76
|
control?: CodeRequestControl,
|
|
77
77
|
): Promise<CodeQueryResult<DocumentCodeSymbol[]>>;
|
|
78
|
+
/**
|
|
79
|
+
* Collect workspace symbols from routes that can contribute within the
|
|
80
|
+
* optional canonical path scopes.
|
|
81
|
+
*/
|
|
78
82
|
workspaceSymbols(
|
|
79
83
|
query: string,
|
|
80
84
|
control?: CodeRequestControl,
|
|
85
|
+
scopes?: readonly string[],
|
|
81
86
|
): Promise<CodeQueryResult<CodeSymbol[]>>;
|
|
82
87
|
|
|
83
88
|
/** Optional definition capability with explicit completed-empty semantics. */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Maximum UTF-16 code-unit length of one debug identity string. */
|
|
2
|
+
export const MAX_DEBUG_IDENTITY_STRING = 512;
|
|
3
|
+
|
|
4
|
+
/** Marker appended to a truncated debug identity string. */
|
|
5
|
+
export const DEBUG_IDENTITY_TRUNCATION_MARKER = "…";
|
|
6
|
+
|
|
7
|
+
/** Bound one debug identity string, including its truncation marker. */
|
|
8
|
+
export function truncateDebugIdentity(value: string): string {
|
|
9
|
+
if (value.length <= MAX_DEBUG_IDENTITY_STRING) return value;
|
|
10
|
+
return `${value.slice(0, MAX_DEBUG_IDENTITY_STRING - 1)}${DEBUG_IDENTITY_TRUNCATION_MARKER}`;
|
|
11
|
+
}
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
// Kept separate from debug-registry.ts so debug-timing.ts can import the
|
|
4
4
|
// registry without creating an import cycle through the barrel re-export.
|
|
5
5
|
|
|
6
|
+
export {
|
|
7
|
+
DEBUG_IDENTITY_TRUNCATION_MARKER,
|
|
8
|
+
MAX_DEBUG_IDENTITY_STRING,
|
|
9
|
+
truncateDebugIdentity,
|
|
10
|
+
} from "./debug-identity.ts";
|
|
6
11
|
// biome-ignore lint/performance/noReExportAll: preserve the stable debug domain entry point
|
|
7
12
|
export * from "./debug-registry.ts";
|
|
8
13
|
// biome-ignore lint/performance/noReExportAll: preserve the stable debug domain entry point
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-tree-sitter",
|
|
3
|
-
"version": "6.0
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "Structural AST analysis for SuPi code intelligence",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -30,14 +30,13 @@
|
|
|
30
30
|
"src/**/*.mjs",
|
|
31
31
|
"src/**/*.json",
|
|
32
32
|
"resources",
|
|
33
|
-
"scripts/*.mjs",
|
|
34
33
|
"!__tests__"
|
|
35
34
|
],
|
|
36
35
|
"dependencies": {
|
|
37
36
|
"jiti": "^2.7.0",
|
|
38
37
|
"web-tree-sitter": "^0.26.8",
|
|
39
|
-
"@mrclrchtr/supi-code-runtime": "6.0
|
|
40
|
-
"@mrclrchtr/supi-core": "6.0
|
|
38
|
+
"@mrclrchtr/supi-code-runtime": "6.2.0",
|
|
39
|
+
"@mrclrchtr/supi-core": "6.2.0"
|
|
41
40
|
},
|
|
42
41
|
"bundledDependencies": [
|
|
43
42
|
"@mrclrchtr/supi-code-runtime",
|
|
@@ -45,7 +44,6 @@
|
|
|
45
44
|
"jiti",
|
|
46
45
|
"web-tree-sitter"
|
|
47
46
|
],
|
|
48
|
-
"main": "src/api.ts",
|
|
49
47
|
"exports": {
|
|
50
48
|
"./api": "./src/api.ts",
|
|
51
49
|
"./package.json": "./package.json",
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"releaseAsset": "https://github.com/fwcd/tree-sitter-kotlin/releases/download/0.3.8/tree-sitter-kotlin.wasm"
|
|
7
7
|
},
|
|
8
8
|
"generatedWith": {
|
|
9
|
-
"treeSitterCli": "0.26.
|
|
9
|
+
"treeSitterCli": "0.26.13"
|
|
10
10
|
},
|
|
11
11
|
"sha256": "e08447e36ad5d86f39f91f13defce0636aea1490b8d65dafde6fa72649422061"
|
|
12
12
|
}
|
package/src/api.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Public
|
|
1
|
+
// Public Tree-sitter session factory, lifecycle controller, and shared types.
|
|
2
2
|
//
|
|
3
3
|
// This package is library-only — no pi extension surface.
|
|
4
4
|
// Exports structured runtime/service APIs only.
|
|
@@ -7,19 +7,11 @@
|
|
|
7
7
|
// Language detection helpers
|
|
8
8
|
export {
|
|
9
9
|
detectGrammar,
|
|
10
|
-
getSupportedExtension,
|
|
11
10
|
getSupportedExtensions,
|
|
12
|
-
isJsTsGrammar,
|
|
13
|
-
isSupportedFile,
|
|
14
11
|
} from "./language.ts";
|
|
15
12
|
export type { StructuralSearchOperation } from "./operation-support.ts";
|
|
16
13
|
export { getStructuralSearchSupportedExtensions } from "./operation-support.ts";
|
|
17
|
-
export type {
|
|
18
|
-
TsControllerState,
|
|
19
|
-
TsStartResult,
|
|
20
|
-
} from "./session/runtime-controller.ts";
|
|
21
14
|
export { TreeSitterRuntimeController } from "./session/runtime-controller.ts";
|
|
22
|
-
export { getSessionTreeSitterService } from "./session/service-registry.ts";
|
|
23
15
|
export { createTreeSitterSession } from "./session/session.ts";
|
|
24
16
|
|
|
25
17
|
// Shared types
|
|
@@ -32,8 +24,6 @@ export type {
|
|
|
32
24
|
NodeAtResult,
|
|
33
25
|
OutlineItem,
|
|
34
26
|
QueryCapture,
|
|
35
|
-
SessionTreeSitterService,
|
|
36
|
-
SessionTreeSitterServiceState,
|
|
37
27
|
SourceRange,
|
|
38
28
|
SupportedExtension,
|
|
39
29
|
TreeSitterResult,
|
package/src/coordinates.ts
CHANGED
|
@@ -81,6 +81,25 @@ export function nodeToRange(
|
|
|
81
81
|
};
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/** Validate that a public position exists in the source bounds. */
|
|
85
|
+
export function validatePublicPositionBounds(
|
|
86
|
+
line: number,
|
|
87
|
+
character: number,
|
|
88
|
+
source: string,
|
|
89
|
+
): { kind: "validation-error"; message: string } | null {
|
|
90
|
+
const lines = splitSourceLines(source);
|
|
91
|
+
if (line > lines.length) {
|
|
92
|
+
return { kind: "validation-error", message: "line is beyond end of file" };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const lineText = lines[line - 1] ?? "";
|
|
96
|
+
if (character > lineText.length + 1) {
|
|
97
|
+
return { kind: "validation-error", message: "character is beyond end of line" };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
84
103
|
/** Split source into logical lines without CRLF line-ending bytes. */
|
|
85
104
|
export function splitSourceLines(source: string): string[] {
|
|
86
105
|
return source.replace(/\r\n?/g, "\n").split("\n");
|
package/src/language.ts
CHANGED
|
@@ -12,7 +12,7 @@ import type { GrammarId, SupportedExtension } from "./types.ts";
|
|
|
12
12
|
const sourceDir = path.dirname(fileURLToPath(import.meta.url));
|
|
13
13
|
|
|
14
14
|
/** Mapping from file extension to grammar identifier. */
|
|
15
|
-
const EXTENSION_GRAMMAR
|
|
15
|
+
const EXTENSION_GRAMMAR = {
|
|
16
16
|
".js": "javascript",
|
|
17
17
|
".jsx": "javascript",
|
|
18
18
|
".mjs": "javascript",
|
|
@@ -48,17 +48,12 @@ const EXTENSION_GRAMMAR: Record<string, GrammarId> = {
|
|
|
48
48
|
".xhtml": "html",
|
|
49
49
|
".r": "r",
|
|
50
50
|
".sql": "sql",
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const SUPPORTED_EXTENSIONS = new Set<string>(Object.keys(EXTENSION_GRAMMAR));
|
|
51
|
+
} satisfies Record<SupportedExtension, GrammarId>;
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
export function isSupportedFile(filePath: string): boolean {
|
|
57
|
-
return detectGrammar(filePath) !== undefined;
|
|
58
|
-
}
|
|
53
|
+
const SUPPORTED_EXTENSIONS = Object.keys(EXTENSION_GRAMMAR) as SupportedExtension[];
|
|
59
54
|
|
|
60
55
|
/** Return all supported file extensions (with leading dot). */
|
|
61
|
-
export function getSupportedExtensions():
|
|
56
|
+
export function getSupportedExtensions(): SupportedExtension[] {
|
|
62
57
|
return [...SUPPORTED_EXTENSIONS];
|
|
63
58
|
}
|
|
64
59
|
|
|
@@ -69,23 +64,10 @@ export function getSupportedExtensionGrammarEntries(): Array<
|
|
|
69
64
|
return Object.entries(EXTENSION_GRAMMAR) as Array<readonly [SupportedExtension, GrammarId]>;
|
|
70
65
|
}
|
|
71
66
|
|
|
72
|
-
/** Get the file extension if it's supported, otherwise undefined. */
|
|
73
|
-
export function getSupportedExtension(filePath: string): SupportedExtension | undefined {
|
|
74
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
75
|
-
return SUPPORTED_EXTENSIONS.has(ext) ? (ext as SupportedExtension) : undefined;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
67
|
/** Detect the grammar for a file. Returns undefined if unsupported. */
|
|
79
68
|
export function detectGrammar(filePath: string): GrammarId | undefined {
|
|
80
69
|
const ext = path.extname(filePath).toLowerCase();
|
|
81
|
-
return EXTENSION_GRAMMAR[ext];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const JS_TS_GRAMMARS: ReadonlySet<GrammarId> = new Set(["javascript", "typescript", "tsx"]);
|
|
85
|
-
|
|
86
|
-
/** Returns true if the grammar is one the JS/TS extractors understand. */
|
|
87
|
-
export function isJsTsGrammar(grammarId: GrammarId): boolean {
|
|
88
|
-
return JS_TS_GRAMMARS.has(grammarId);
|
|
70
|
+
return EXTENSION_GRAMMAR[ext as SupportedExtension];
|
|
89
71
|
}
|
|
90
72
|
|
|
91
73
|
/** Grammar WASM file names within the vendored resources directory. */
|
package/src/operation-support.ts
CHANGED
|
@@ -1,25 +1,7 @@
|
|
|
1
|
-
import { getSupportedExtensionGrammarEntries
|
|
1
|
+
import { getSupportedExtensionGrammarEntries } from "./language.ts";
|
|
2
2
|
import { supportsCallSitesGrammar } from "./tool/call-sites.ts";
|
|
3
3
|
import type { GrammarId, SupportedExtension } from "./types.ts";
|
|
4
4
|
|
|
5
|
-
const OUTLINE_GRAMMARS: ReadonlySet<GrammarId> = new Set([
|
|
6
|
-
"javascript",
|
|
7
|
-
"typescript",
|
|
8
|
-
"tsx",
|
|
9
|
-
"python",
|
|
10
|
-
"rust",
|
|
11
|
-
"go",
|
|
12
|
-
"c",
|
|
13
|
-
"cpp",
|
|
14
|
-
"java",
|
|
15
|
-
"kotlin",
|
|
16
|
-
"ruby",
|
|
17
|
-
"bash",
|
|
18
|
-
"html",
|
|
19
|
-
"r",
|
|
20
|
-
"sql",
|
|
21
|
-
]);
|
|
22
|
-
|
|
23
5
|
/** Structural collection operations whose language support defines an AST Scan universe. */
|
|
24
6
|
const STRUCTURAL_SEARCH_OPERATIONS = ["outline", "imports", "exports", "call-sites"] as const;
|
|
25
7
|
|
|
@@ -49,10 +31,10 @@ export function supportsGrammarOperation(
|
|
|
49
31
|
case "call-sites":
|
|
50
32
|
return supportsCallSitesGrammar(grammar);
|
|
51
33
|
case "outline":
|
|
52
|
-
return
|
|
34
|
+
return true;
|
|
53
35
|
case "imports":
|
|
54
36
|
case "exports":
|
|
55
|
-
return
|
|
37
|
+
return grammar === "javascript" || grammar === "typescript" || grammar === "tsx";
|
|
56
38
|
default:
|
|
57
39
|
throw new TypeError(`Unsupported structural search operation: ${String(operation)}`);
|
|
58
40
|
}
|
|
@@ -35,31 +35,27 @@ export function createTreeSitterProvider(service: TreeSitterService): Structural
|
|
|
35
35
|
},
|
|
36
36
|
|
|
37
37
|
async exports(file, control?) {
|
|
38
|
-
const result =
|
|
38
|
+
const result = await service.exports(file, control);
|
|
39
39
|
return mapTreeSitterResult(result, mapExportRecords);
|
|
40
40
|
},
|
|
41
41
|
|
|
42
42
|
async outline(file, control?) {
|
|
43
|
-
const result =
|
|
43
|
+
const result = await service.outline(file, control);
|
|
44
44
|
return mapTreeSitterResult(result, mapOutlineItems);
|
|
45
45
|
},
|
|
46
46
|
|
|
47
47
|
async imports(file, control?) {
|
|
48
|
-
const result =
|
|
48
|
+
const result = await service.imports(file, control);
|
|
49
49
|
return mapTreeSitterResult(result, mapImportRecords);
|
|
50
50
|
},
|
|
51
51
|
|
|
52
52
|
async nodeAt(file, line, character, control?) {
|
|
53
|
-
const result = control
|
|
54
|
-
? await service.nodeAt(file, line, character, control)
|
|
55
|
-
: await service.nodeAt(file, line, character);
|
|
53
|
+
const result = await service.nodeAt(file, line, character, control);
|
|
56
54
|
return mapTreeSitterResult(result, mapNodeAtResult);
|
|
57
55
|
},
|
|
58
56
|
|
|
59
57
|
async callSites(file, control?) {
|
|
60
|
-
const result = control
|
|
61
|
-
? await service.callSites(file, control)
|
|
62
|
-
: await service.callSites(file);
|
|
58
|
+
const result = await service.callSites(file, control);
|
|
63
59
|
return mapTreeSitterResult(result, mapCallSites);
|
|
64
60
|
},
|
|
65
61
|
};
|
|
@@ -2,16 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import type { WorkspaceRuntime } from "@mrclrchtr/supi-code-runtime/api";
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
registerTreeSitterCapabilities,
|
|
8
|
-
unregisterTreeSitterCapabilities,
|
|
9
|
-
} from "./runtime-registration.ts";
|
|
10
|
-
import { clearSessionTreeSitterService, setSessionTreeSitterService } from "./service-registry.ts";
|
|
5
|
+
import { createTreeSitterProvider } from "../provider/tree-sitter-provider.ts";
|
|
6
|
+
import type { TreeSitterService, TreeSitterSession } from "../types.ts";
|
|
11
7
|
import { createTreeSitterSession } from "./session.ts";
|
|
12
8
|
|
|
13
9
|
/** Starting state before or after shutdown. */
|
|
14
|
-
|
|
10
|
+
type TsControllerState = TsControllerInitial | TsControllerReady | TsControllerUnavailable;
|
|
15
11
|
|
|
16
12
|
interface TsControllerInitial {
|
|
17
13
|
kind: "initial";
|
|
@@ -29,20 +25,20 @@ interface TsControllerUnavailable {
|
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
/** Result type from {@link TreeSitterRuntimeController.start}. */
|
|
32
|
-
|
|
28
|
+
type TsStartResult = { kind: "ready" } | { kind: "unavailable"; reason: string };
|
|
33
29
|
|
|
34
30
|
/** Pi-independent lifecycle for one shared workspace Structural Worker. */
|
|
35
31
|
export class TreeSitterRuntimeController {
|
|
36
32
|
readonly #cwd: string;
|
|
37
33
|
#state: TsControllerState = { kind: "initial" };
|
|
38
|
-
#runtime: WorkspaceRuntime
|
|
34
|
+
readonly #runtime: WorkspaceRuntime;
|
|
39
35
|
#pendingSession: TreeSitterSession | null = null;
|
|
40
36
|
#generation = 0;
|
|
41
37
|
#transition = Promise.resolve();
|
|
42
38
|
|
|
43
|
-
constructor(cwd: string, runtime
|
|
39
|
+
constructor(cwd: string, runtime: WorkspaceRuntime) {
|
|
44
40
|
this.#cwd = cwd;
|
|
45
|
-
this.#runtime = runtime
|
|
41
|
+
this.#runtime = runtime;
|
|
46
42
|
}
|
|
47
43
|
|
|
48
44
|
get cwd(): string {
|
|
@@ -53,14 +49,10 @@ export class TreeSitterRuntimeController {
|
|
|
53
49
|
return this.#state.kind;
|
|
54
50
|
}
|
|
55
51
|
|
|
56
|
-
get service():
|
|
52
|
+
get service(): TreeSitterService | null {
|
|
57
53
|
return this.#state.kind === "ready" ? this.#state.service : null;
|
|
58
54
|
}
|
|
59
55
|
|
|
60
|
-
setRuntime(runtime: WorkspaceRuntime): void {
|
|
61
|
-
this.#runtime = runtime;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
56
|
/** Start and validate one Structural Worker before capability publication. */
|
|
65
57
|
start(): Promise<TsStartResult> {
|
|
66
58
|
const generation = ++this.#generation;
|
|
@@ -95,8 +87,7 @@ export class TreeSitterRuntimeController {
|
|
|
95
87
|
if (generation !== this.#generation || this.#pendingSession !== session) {
|
|
96
88
|
return supersededStart();
|
|
97
89
|
}
|
|
98
|
-
|
|
99
|
-
if (this.#runtime) registerTreeSitterCapabilities(this.#runtime, this.#cwd, session);
|
|
90
|
+
this.#runtime.registerStructural(this.#cwd, createTreeSitterProvider(session));
|
|
100
91
|
this.#pendingSession = null;
|
|
101
92
|
this.#state = { kind: "ready", session, service: session };
|
|
102
93
|
return { kind: "ready" };
|
|
@@ -119,8 +110,7 @@ export class TreeSitterRuntimeController {
|
|
|
119
110
|
}
|
|
120
111
|
|
|
121
112
|
#takeOwnedSessions(): Set<TreeSitterSession> {
|
|
122
|
-
|
|
123
|
-
clearSessionTreeSitterService(this.#cwd);
|
|
113
|
+
this.#runtime.clearStructural(this.#cwd);
|
|
124
114
|
const sessions = new Set<TreeSitterSession>();
|
|
125
115
|
if (this.#pendingSession) sessions.add(this.#pendingSession);
|
|
126
116
|
if (this.#state.kind === "ready") sessions.add(this.#state.session);
|
package/src/session/session.ts
CHANGED
|
@@ -44,7 +44,13 @@ export function createTreeSitterService(client: StructuralWorkerClient): TreeSit
|
|
|
44
44
|
const control = typeof depthOrOptions === "string" ? undefined : depthOrOptions?.control;
|
|
45
45
|
return execute<CalleesAtResult>(
|
|
46
46
|
client,
|
|
47
|
-
{
|
|
47
|
+
{
|
|
48
|
+
operation: "calleesAt",
|
|
49
|
+
file,
|
|
50
|
+
line,
|
|
51
|
+
character,
|
|
52
|
+
...(depth === undefined ? {} : { depth }),
|
|
53
|
+
},
|
|
48
54
|
control,
|
|
49
55
|
);
|
|
50
56
|
},
|
|
@@ -4,8 +4,6 @@ import { Worker } from "node:worker_threads";
|
|
|
4
4
|
import {
|
|
5
5
|
type CodeRequestControl,
|
|
6
6
|
CodeRequestDeadlineError,
|
|
7
|
-
isCodeRequestDeadlineError,
|
|
8
|
-
isCodeRequestInterruption,
|
|
9
7
|
throwIfCodeRequestInterrupted,
|
|
10
8
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
11
9
|
import { isDebugOperationId, startDebugTimer } from "@mrclrchtr/supi-core/debug";
|
|
@@ -20,6 +18,7 @@ import {
|
|
|
20
18
|
STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
21
19
|
type StructuralWorkerOperation,
|
|
22
20
|
type StructuralWorkerToParentMessage,
|
|
21
|
+
validateStructuralWorkerOperation,
|
|
23
22
|
validateWorkerToParentMessage,
|
|
24
23
|
} from "./structural-worker-protocol.ts";
|
|
25
24
|
|
|
@@ -122,6 +121,10 @@ export class StructuralWorkerClient {
|
|
|
122
121
|
input: StructuralWorkerOperation,
|
|
123
122
|
control?: CodeRequestControl,
|
|
124
123
|
): Promise<TreeSitterResult<T>> {
|
|
124
|
+
const validation = validateStructuralWorkerOperation(input);
|
|
125
|
+
if (validation.kind === "invalid") {
|
|
126
|
+
return { kind: "validation-error", message: validation.reason };
|
|
127
|
+
}
|
|
125
128
|
throwIfCodeRequestInterrupted(control);
|
|
126
129
|
if (this.#closed) return runtimeError("Structural Worker is shut down");
|
|
127
130
|
if (control?.operationId !== undefined && !isDebugOperationId(control.operationId)) {
|
|
@@ -308,6 +311,9 @@ export class StructuralWorkerClient {
|
|
|
308
311
|
const active = this.#active;
|
|
309
312
|
if (!active || active.id !== message.requestId)
|
|
310
313
|
return this.#protocolFailure("Unknown chunk request id");
|
|
314
|
+
if (active.finalSequence !== null) {
|
|
315
|
+
return this.#protocolFailure("Structural Worker sent a chunk after the final chunk");
|
|
316
|
+
}
|
|
311
317
|
if (active.awaitingAck !== null) {
|
|
312
318
|
return this.#protocolFailure("Structural Worker sent more than one unacknowledged chunk");
|
|
313
319
|
}
|
|
@@ -530,9 +536,7 @@ export class StructuralWorkerClient {
|
|
|
530
536
|
if (request.settled) return;
|
|
531
537
|
request.settled = true;
|
|
532
538
|
request.cleanupControl();
|
|
533
|
-
|
|
534
|
-
request.reject(error);
|
|
535
|
-
else request.reject(error);
|
|
539
|
+
request.reject(error);
|
|
536
540
|
}
|
|
537
541
|
}
|
|
538
542
|
|