@mrclrchtr/supi-code-intelligence 6.1.0 → 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 +1 -1
- package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- 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/node_modules/@mrclrchtr/supi-lsp/README.md +21 -3
- 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-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
- package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +12 -7
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-cache.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-capabilities.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-publication.ts +6 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-refresh.ts +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostic-timing.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-diagnostics.ts +2 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +17 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +40 -18
- package/node_modules/@mrclrchtr/supi-lsp/src/config/config.ts +164 -30
- package/node_modules/@mrclrchtr/supi-lsp/src/config/lsp-settings.ts +9 -87
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-config.ts +0 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +0 -29
- package/node_modules/@mrclrchtr/supi-lsp/src/debug-telemetry.ts +7 -21
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-severity.ts +6 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-summary.ts +11 -14
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/evidence.ts +0 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/stale-diagnostics.ts +0 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/workspace-sentinels.ts +29 -49
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-client-state.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +4 -8
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-helpers.ts +1 -9
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +6 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +9 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +26 -41
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +275 -99
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +4 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/semantic-symbol-mapper.ts +59 -28
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-controller.ts +27 -19
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-diagnostics.ts +26 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registration.ts +0 -17
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-registry.ts +83 -19
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +5 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/session/scanner.ts +24 -21
- package/node_modules/@mrclrchtr/supi-lsp/src/session/workspace-lsp-runtime.ts +29 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +19 -40
- package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +13 -19
- package/node_modules/@mrclrchtr/supi-lsp/src/workspace-path-policy.ts +287 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +6 -18
- 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-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-identity.ts +11 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug.ts +5 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +3 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +1 -11
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/coordinates.ts +19 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/language.ts +5 -23
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/operation-support.ts +3 -21
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/provider/tree-sitter-provider.ts +5 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-controller.ts +10 -20
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/session.ts +7 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-client.ts +9 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/structural-worker-protocol.ts +134 -9
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-name.ts +96 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/call-sites.ts +11 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/callees.ts +39 -56
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/exports.ts +9 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/js-binding-pattern.ts +26 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/node-at.ts +2 -21
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline-html-sql.ts +144 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/outline.ts +50 -37
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/scope.ts +138 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +0 -7
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/parsed-file-store.ts +1 -14
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/runtime.ts +0 -10
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/service.ts +6 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/worker/worker-main.ts +34 -10
- package/package.json +5 -5
- package/src/analysis/capability/capability-warnings.ts +4 -22
- package/src/analysis/search/ast-scan-timing.ts +4 -2
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/api.ts +1 -0
- package/src/extension.ts +4 -2
- package/src/session/health-refresh.ts +24 -2
- package/src/session/health-types.ts +19 -0
- package/src/session/input/health-refactor.ts +16 -14
- package/src/session/refactor-types.ts +14 -1
- package/src/session/refactor-workflow.ts +21 -16
- package/src/substrate/lsp/lifecycle.ts +0 -3
- package/src/substrate/lsp/maintenance.ts +4 -5
- package/src/substrate/lsp/settings.ts +6 -9
- package/src/substrate/lsp/state.ts +0 -2
- package/src/substrate/workspace-provider-host.ts +2 -2
- package/src/tool/code_health/file-scope-markdown.ts +43 -0
- package/src/tool/code_health/markdown.ts +66 -66
- package/src/tool/code_health/refresh-outcome.ts +46 -0
- package/src/tool/code_health/refresh-status.ts +166 -23
- package/src/tool/code_health/result.ts +1 -0
- package/src/tool/code_health/tui.ts +18 -5
- package/src/tool/code_refactor_apply/guidance.ts +3 -2
- package/src/tool/code_refactor_plan/guidance.ts +1 -1
- package/src/tool/register.ts +5 -2
- package/src/tool/schemas.ts +21 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/config/server-actions.ts +0 -59
- package/node_modules/@mrclrchtr/supi-lsp/src/pattern-matcher.ts +0 -24
- package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-kotlin-wasm.mjs +0 -132
- package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/generate-sql-wasm.mjs +0 -158
- package/node_modules/@mrclrchtr/supi-tree-sitter/scripts/vendor-wasm.mjs +0 -167
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +0 -42
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/runtime-registration.ts +0 -37
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/service-registry.ts +0 -30
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/structure.ts +0 -8
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { SyntaxNodeLike } from "../syntax-node.ts";
|
|
2
|
+
import { extractBindingIdentifiers } from "./js-binding-pattern.ts";
|
|
3
|
+
|
|
4
|
+
/** Return the declared name for one executable syntax scope. */
|
|
5
|
+
export function extractScopeName(node: SyntaxNodeLike): string {
|
|
6
|
+
const declaredName = findDeclaredName(node);
|
|
7
|
+
if (declaredName) return declaredName;
|
|
8
|
+
|
|
9
|
+
if (node.type === "arrow_function" || node.type === "function_expression") {
|
|
10
|
+
const binding = findNearestJavaScriptBinding(node);
|
|
11
|
+
if (binding) return binding;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (node.type === "function_definition") {
|
|
15
|
+
const binding = findNearestRBinding(node);
|
|
16
|
+
if (binding) return binding;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return "anonymous";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function findDeclaredName(node: SyntaxNodeLike): string | null {
|
|
23
|
+
const name = node.childForFieldName("name");
|
|
24
|
+
if (name && isNameNode(name)) return name.text;
|
|
25
|
+
|
|
26
|
+
const declarator = node.childForFieldName("declarator");
|
|
27
|
+
return declarator ? findDeclaratorName(declarator) : null;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function findDeclaratorName(node: SyntaxNodeLike): string | null {
|
|
31
|
+
const namedChild = node.childForFieldName("name");
|
|
32
|
+
if (namedChild && isNameNode(namedChild)) return namedChild.text;
|
|
33
|
+
if (isNameNode(node)) return node.text;
|
|
34
|
+
const nested = node.childForFieldName("declarator");
|
|
35
|
+
if (nested) {
|
|
36
|
+
const name = findDeclaratorName(nested);
|
|
37
|
+
if (name) return name;
|
|
38
|
+
}
|
|
39
|
+
for (const child of node.children) {
|
|
40
|
+
const name = findDeclaratorName(child);
|
|
41
|
+
if (name) return name;
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findNearestJavaScriptBinding(node: SyntaxNodeLike): string | null {
|
|
47
|
+
for (let current = node.parent; current; current = current.parent) {
|
|
48
|
+
const binding = bindingForJavaScriptAncestor(current, node);
|
|
49
|
+
if (binding) return binding;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: binding lookup covers the grammar's distinct assignment and object-pattern forms
|
|
55
|
+
function bindingForJavaScriptAncestor(node: SyntaxNodeLike, target: SyntaxNodeLike): string | null {
|
|
56
|
+
if (node.type === "variable_declarator") {
|
|
57
|
+
return isDirectValue(node, target)
|
|
58
|
+
? (extractBindingIdentifiers(node.childForFieldName("name"))[0] ?? null)
|
|
59
|
+
: null;
|
|
60
|
+
}
|
|
61
|
+
if (node.type === "pair_pattern") {
|
|
62
|
+
return isDirectValue(node, target)
|
|
63
|
+
? (extractBindingIdentifiers(node.childForFieldName("value"))[0] ??
|
|
64
|
+
node.childForFieldName("key")?.text ??
|
|
65
|
+
null)
|
|
66
|
+
: null;
|
|
67
|
+
}
|
|
68
|
+
if (node.type === "pair") {
|
|
69
|
+
return isDirectValue(node, target) ? (node.childForFieldName("key")?.text ?? null) : null;
|
|
70
|
+
}
|
|
71
|
+
if (node.type === "assignment_expression") {
|
|
72
|
+
const right = node.childForFieldName("right");
|
|
73
|
+
if (!sameNode(right, target)) return null;
|
|
74
|
+
const left = node.childForFieldName("left");
|
|
75
|
+
return left
|
|
76
|
+
? (extractBindingIdentifiers(left)[0] ??
|
|
77
|
+
(left.type === "member_expression" || left.type === "subscript_expression"
|
|
78
|
+
? left.text
|
|
79
|
+
: null))
|
|
80
|
+
: null;
|
|
81
|
+
}
|
|
82
|
+
if (node.type === "public_field_definition") {
|
|
83
|
+
return isDirectValue(node, target)
|
|
84
|
+
? ((node.childForFieldName("name") ?? node.childForFieldName("key"))?.text ?? null)
|
|
85
|
+
: null;
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isDirectValue(node: SyntaxNodeLike, target: SyntaxNodeLike): boolean {
|
|
91
|
+
return sameNode(node.childForFieldName("value"), target);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function findNearestRBinding(node: SyntaxNodeLike): string | null {
|
|
95
|
+
for (let current = node.parent; current; current = current.parent) {
|
|
96
|
+
const binding = bindingForRAncestor(current, node);
|
|
97
|
+
if (binding) return binding;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function bindingForRAncestor(node: SyntaxNodeLike, target: SyntaxNodeLike): string | null {
|
|
103
|
+
if (node.type !== "binary_operator") return null;
|
|
104
|
+
const right = node.childForFieldName("rhs") ?? node.childForFieldName("right");
|
|
105
|
+
const left = node.childForFieldName("lhs") ?? node.childForFieldName("left");
|
|
106
|
+
return right && left && sameNode(right, target) && left.type === "identifier" ? left.text : null;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function sameNode(left: SyntaxNodeLike | null, right: SyntaxNodeLike): boolean {
|
|
110
|
+
if (!left) return false;
|
|
111
|
+
return (
|
|
112
|
+
left.type === right.type &&
|
|
113
|
+
left.startPosition.row === right.startPosition.row &&
|
|
114
|
+
left.startPosition.column === right.startPosition.column &&
|
|
115
|
+
left.endPosition.row === right.endPosition.row &&
|
|
116
|
+
left.endPosition.column === right.endPosition.column
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const NAME_NODE_TYPES = new Set([
|
|
121
|
+
"identifier",
|
|
122
|
+
"type_identifier",
|
|
123
|
+
"field_identifier",
|
|
124
|
+
"property_identifier",
|
|
125
|
+
"private_property_identifier",
|
|
126
|
+
"simple_identifier",
|
|
127
|
+
"word",
|
|
128
|
+
"constant",
|
|
129
|
+
"scope_resolution",
|
|
130
|
+
"qualified_identifier",
|
|
131
|
+
"template_function",
|
|
132
|
+
"operator_name",
|
|
133
|
+
"destructor_name",
|
|
134
|
+
]);
|
|
135
|
+
|
|
136
|
+
function isNameNode(node: SyntaxNodeLike): boolean {
|
|
137
|
+
return NAME_NODE_TYPES.has(node.type);
|
|
138
|
+
}
|
|
@@ -128,13 +128,6 @@ export interface TreeSitterSession extends TreeSitterService {
|
|
|
128
128
|
dispose(): Promise<void>;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
/** Session-scoped shared structural service published by the extension runtime. */
|
|
132
|
-
export type SessionTreeSitterService = TreeSitterService;
|
|
133
|
-
|
|
134
|
-
export type SessionTreeSitterServiceState =
|
|
135
|
-
| { kind: "ready"; service: SessionTreeSitterService }
|
|
136
|
-
| { kind: "unavailable"; reason: string };
|
|
137
|
-
|
|
138
131
|
/** Supported grammar identifiers. */
|
|
139
132
|
export type GrammarId =
|
|
140
133
|
| "javascript"
|
|
@@ -196,10 +196,8 @@ export class ParsedFileStore {
|
|
|
196
196
|
withQuery<T>(
|
|
197
197
|
grammarId: GrammarId,
|
|
198
198
|
queryText: string,
|
|
199
|
-
|
|
200
|
-
legacyExecute?: (query: Pick<Query, "matches">, cache: StructuralCacheObservation) => T,
|
|
199
|
+
execution: QueryExecution<T>,
|
|
201
200
|
): { readonly data: T; readonly cache: StructuralCacheObservation } {
|
|
202
|
-
const execution = normalizeQueryExecution(compileOrExecution, legacyExecute);
|
|
203
201
|
this.#assertActive();
|
|
204
202
|
throwIfStructuralRequestInterrupted(execution.control);
|
|
205
203
|
const key = queryKey(grammarId, queryText);
|
|
@@ -365,17 +363,6 @@ export class ParsedFileStore {
|
|
|
365
363
|
}
|
|
366
364
|
}
|
|
367
365
|
|
|
368
|
-
function normalizeQueryExecution<T>(
|
|
369
|
-
compileOrExecution: (() => Query) | QueryExecution<T>,
|
|
370
|
-
legacyExecute:
|
|
371
|
-
| ((query: Pick<Query, "matches">, cache: StructuralCacheObservation) => T)
|
|
372
|
-
| undefined,
|
|
373
|
-
): QueryExecution<T> {
|
|
374
|
-
if (typeof compileOrExecution !== "function") return compileOrExecution;
|
|
375
|
-
if (!legacyExecute) throw new Error("Query execution callback is required");
|
|
376
|
-
return { compile: compileOrExecution, execute: legacyExecute };
|
|
377
|
-
}
|
|
378
|
-
|
|
379
366
|
function fileReadMessage(error: unknown): string {
|
|
380
367
|
return error instanceof Error ? error.message : "File could not be read";
|
|
381
368
|
}
|
|
@@ -372,16 +372,6 @@ export class TreeSitterRuntime {
|
|
|
372
372
|
}
|
|
373
373
|
}
|
|
374
374
|
|
|
375
|
-
/** Get the grammar ID for a file, or undefined if unsupported. */
|
|
376
|
-
getGrammarId(filePath: string): GrammarId | undefined {
|
|
377
|
-
return detectGrammar(filePath);
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
/** Resolve a file path from cwd. */
|
|
381
|
-
resolvePath(filePath: string): string {
|
|
382
|
-
return resolveToolPath(this.cwd, filePath);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
375
|
/** Dispose all held tree, query, and parser resources. */
|
|
386
376
|
dispose(): void {
|
|
387
377
|
if (this.disposed) return;
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { detectGrammar } from "../language.ts";
|
|
2
2
|
import { supportsGrammarOperation } from "../operation-support.ts";
|
|
3
3
|
import type { StructuralWorkerOperation } from "../session/structural-worker-protocol.ts";
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
lookupNodeAt,
|
|
11
|
-
} from "../tool/structure.ts";
|
|
4
|
+
import { extractCallSites } from "../tool/call-sites.ts";
|
|
5
|
+
import { lookupCalleesAt } from "../tool/callees.ts";
|
|
6
|
+
import { extractExports } from "../tool/exports.ts";
|
|
7
|
+
import { extractImports } from "../tool/imports.ts";
|
|
8
|
+
import { lookupNodeAt } from "../tool/node-at.ts";
|
|
9
|
+
import { collectOutline as extractOutline } from "../tool/outline.ts";
|
|
12
10
|
import type { TreeSitterResult } from "../types.ts";
|
|
13
11
|
import {
|
|
14
12
|
type StructuralRequestControl,
|
|
@@ -4,11 +4,11 @@ import type { StructuralTimingEvent } from "../session/structural-timing.ts";
|
|
|
4
4
|
import { assertStructuralProtocolMessageSize } from "../session/structural-worker-message-size.ts";
|
|
5
5
|
import {
|
|
6
6
|
encodeStructuralResult,
|
|
7
|
-
|
|
7
|
+
getStructuralWorkerMessageGeneration,
|
|
8
8
|
STRUCTURAL_WORKER_PROTOCOL_VERSION,
|
|
9
9
|
type StructuralWorkerChunkAckMessage,
|
|
10
10
|
type StructuralWorkerRequestMessage,
|
|
11
|
-
|
|
11
|
+
validateParentToStructuralWorkerMessage,
|
|
12
12
|
} from "../session/structural-worker-protocol.ts";
|
|
13
13
|
import type { TreeSitterResult } from "../types.ts";
|
|
14
14
|
import type { StructuralRequestControl } from "./request-control.ts";
|
|
@@ -56,21 +56,37 @@ export async function runStructuralWorker(
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: protocol dispatch keeps request, cancel, and acknowledgement validation together
|
|
59
|
-
parentPort.on("message", (
|
|
60
|
-
|
|
59
|
+
parentPort.on("message", (value: unknown) => {
|
|
60
|
+
const validation = validateParentToStructuralWorkerMessage(value);
|
|
61
|
+
if (validation.kind === "invalid") {
|
|
62
|
+
const generation = getStructuralWorkerMessageGeneration(value);
|
|
63
|
+
if (generation !== undefined && generation !== workerData.generation) return;
|
|
64
|
+
throw new Error(`Structural Worker protocol violation: ${validation.reason}`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const message = validation.message;
|
|
61
68
|
if (message.generation !== workerData.generation) return;
|
|
62
69
|
if (message.kind === "cancel") {
|
|
63
|
-
if (active
|
|
70
|
+
if (!active) return;
|
|
71
|
+
assertActiveRequestOwner(active, message.requestId);
|
|
72
|
+
active.abortController.abort();
|
|
64
73
|
return;
|
|
65
74
|
}
|
|
66
75
|
if (message.kind === "chunk-ack") {
|
|
67
|
-
if (active
|
|
76
|
+
if (!active) return;
|
|
77
|
+
assertActiveRequestOwner(active, message.requestId);
|
|
78
|
+
if (!active.awaitingAck || message.sequence !== active.nextSequence - 1) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
"Structural Worker protocol violation: Invalid chunk acknowledgement state",
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
sendNextChunk(message);
|
|
68
84
|
return;
|
|
69
85
|
}
|
|
70
|
-
if (
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
void execute(
|
|
86
|
+
if (active) {
|
|
87
|
+
throw new Error("Structural Worker protocol violation: Structural Worker request is busy");
|
|
88
|
+
}
|
|
89
|
+
void execute(message);
|
|
74
90
|
});
|
|
75
91
|
|
|
76
92
|
try {
|
|
@@ -187,6 +203,14 @@ export async function runStructuralWorker(
|
|
|
187
203
|
active = null;
|
|
188
204
|
}
|
|
189
205
|
|
|
206
|
+
function assertActiveRequestOwner(request: ActiveWorkerRequest, requestId: string): void {
|
|
207
|
+
if (request.message.requestId !== requestId) {
|
|
208
|
+
throw new Error(
|
|
209
|
+
"Structural Worker protocol violation: Message does not own the active request",
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
190
214
|
function updateInterruptionOutcome(request: ActiveWorkerRequest): void {
|
|
191
215
|
if (request.message.deadline !== undefined && Date.now() >= request.message.deadline) {
|
|
192
216
|
request.outcome = "timeout";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-code-intelligence",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "LSP and AST navigation, search, diagnostics, and refactoring",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"yaml": "^2.9.0",
|
|
38
|
-
"@mrclrchtr/supi-
|
|
39
|
-
"@mrclrchtr/supi-
|
|
40
|
-
"@mrclrchtr/supi-
|
|
41
|
-
"@mrclrchtr/supi-
|
|
38
|
+
"@mrclrchtr/supi-code-runtime": "6.2.0",
|
|
39
|
+
"@mrclrchtr/supi-tree-sitter": "6.2.0",
|
|
40
|
+
"@mrclrchtr/supi-lsp": "6.2.0",
|
|
41
|
+
"@mrclrchtr/supi-core": "6.2.0"
|
|
42
42
|
},
|
|
43
43
|
"bundledDependencies": [
|
|
44
44
|
"@mrclrchtr/supi-code-runtime",
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Capability Warning evaluation for reduced semantic and structural analysis.
|
|
3
3
|
*
|
|
4
|
-
* Normalizes LSP startup state
|
|
5
|
-
*
|
|
4
|
+
* Normalizes LSP startup state and Tree-sitter health into a structured report
|
|
5
|
+
* consumed by the startup notice, /supi-ci-status,
|
|
6
6
|
* and code_health.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { getDefaultWorkspaceRuntime } from "@mrclrchtr/supi-code-runtime/api";
|
|
10
10
|
import { loadSupiConfigForScope } from "@mrclrchtr/supi-core/config";
|
|
11
|
-
import {
|
|
11
|
+
import { loadConfig, scanMissingServers } from "@mrclrchtr/supi-lsp/api";
|
|
12
12
|
|
|
13
13
|
/** One actionable warning about reduced Code intelligence capability. */
|
|
14
14
|
export interface CapabilityWarning {
|
|
15
|
-
type: "
|
|
15
|
+
type: "language-disabled" | "missing-server" | "structural-unavailable";
|
|
16
16
|
message: string;
|
|
17
17
|
language?: string;
|
|
18
18
|
detail?: string;
|
|
@@ -31,7 +31,6 @@ export interface CapabilityWarningMissingServerSource {
|
|
|
31
31
|
|
|
32
32
|
/** Current runtime/config facts needed to evaluate Capability Warnings. */
|
|
33
33
|
export interface CapabilityWarningInput {
|
|
34
|
-
deprecatedKeys: ReturnType<typeof getDeprecatedLspKeys>;
|
|
35
34
|
explicitlyDisabledLanguages: string[];
|
|
36
35
|
missingServers: Array<{ name: string; command: string; foundExtensions: string[] }>;
|
|
37
36
|
structuralState: { kind: string; reason?: string };
|
|
@@ -41,21 +40,6 @@ export interface CapabilityWarningInput {
|
|
|
41
40
|
export function evaluateCapabilityWarnings(input: CapabilityWarningInput): CapabilityWarningReport {
|
|
42
41
|
const warnings: CapabilityWarning[] = [];
|
|
43
42
|
|
|
44
|
-
if (input.deprecatedKeys.projectEnabled || input.deprecatedKeys.globalEnabled) {
|
|
45
|
-
warnings.push({
|
|
46
|
-
type: "deprecated-key",
|
|
47
|
-
message:
|
|
48
|
-
"lsp.enabled is deprecated and ignored. Use lsp.servers.<language>.enabled: false for per-language disable.",
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
if (input.deprecatedKeys.projectActive || input.deprecatedKeys.globalActive) {
|
|
52
|
-
warnings.push({
|
|
53
|
-
type: "deprecated-key",
|
|
54
|
-
message:
|
|
55
|
-
"lsp.active is deprecated and ignored. All detected servers are attempted unless explicitly disabled.",
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
43
|
for (const language of input.explicitlyDisabledLanguages) {
|
|
60
44
|
warnings.push({
|
|
61
45
|
type: "language-disabled",
|
|
@@ -143,7 +127,6 @@ export function gatherCapabilityWarningInput(
|
|
|
143
127
|
cwd: string,
|
|
144
128
|
lspController: CapabilityWarningMissingServerSource | null,
|
|
145
129
|
): CapabilityWarningInput {
|
|
146
|
-
const deprecatedKeys = getDeprecatedLspKeys(cwd);
|
|
147
130
|
const structuralState = getDefaultWorkspaceRuntime().getWorkspace(cwd).structural.state;
|
|
148
131
|
const explicitlyDisabledLanguages = detectExplicitlyDisabledLanguages(cwd);
|
|
149
132
|
const missingServers = lspController
|
|
@@ -151,7 +134,6 @@ export function gatherCapabilityWarningInput(
|
|
|
151
134
|
: scanMissingServers(loadConfig(cwd), cwd);
|
|
152
135
|
|
|
153
136
|
return {
|
|
154
|
-
deprecatedKeys,
|
|
155
137
|
explicitlyDisabledLanguages,
|
|
156
138
|
missingServers,
|
|
157
139
|
structuralState,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { CodeRequestControl } from "@mrclrchtr/supi-code-runtime/api";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
startDebugTimer,
|
|
4
|
+
truncateDebugIdentity as truncateIdentity,
|
|
5
|
+
} from "@mrclrchtr/supi-core/debug";
|
|
4
6
|
import type { StructuralSearchOperation } from "@mrclrchtr/supi-tree-sitter/api";
|
|
5
7
|
import type { StructuredFileAnalysis, StructuredPatternParams } from "./pattern-analysis.ts";
|
|
6
8
|
|
|
@@ -150,7 +150,7 @@ export async function enumerateAstFiles(
|
|
|
150
150
|
class AstFileEnumerator {
|
|
151
151
|
readonly #operations: AstScanOperations;
|
|
152
152
|
readonly #now: () => number;
|
|
153
|
-
readonly #grammarExtensions = new Set(getSupportedExtensions());
|
|
153
|
+
readonly #grammarExtensions: ReadonlySet<string> = new Set(getSupportedExtensions());
|
|
154
154
|
readonly #operationExtensions: ReadonlySet<string>;
|
|
155
155
|
readonly #files = new Set<string>();
|
|
156
156
|
readonly #visitedDirectories = new Set<string>();
|
package/src/api.ts
CHANGED
package/src/extension.ts
CHANGED
|
@@ -6,8 +6,10 @@ import type {
|
|
|
6
6
|
ExtensionAPI,
|
|
7
7
|
ExtensionContext,
|
|
8
8
|
} from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import {
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
recordDebugEvent,
|
|
11
|
+
truncateDebugIdentity as truncateIdentity,
|
|
12
|
+
} from "@mrclrchtr/supi-core/debug";
|
|
11
13
|
import { buildArchitectureModel } from "./analysis/architecture/discovery.ts";
|
|
12
14
|
import { createCodeIntelligenceApp } from "./app/app.ts";
|
|
13
15
|
import { registerCodeIntelligenceSettings, resolveOverviewEnabled } from "./config.ts";
|
|
@@ -2,11 +2,19 @@ import {
|
|
|
2
2
|
type CodeRequestControl,
|
|
3
3
|
isCodeRequestInterruption,
|
|
4
4
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
5
|
-
import
|
|
5
|
+
import {
|
|
6
|
+
emptyProcessCrashRecoverySummary,
|
|
7
|
+
type WorkspaceDiagnosticReport,
|
|
8
|
+
type WorkspaceLspRuntime,
|
|
9
|
+
} from "@mrclrchtr/supi-lsp/api";
|
|
6
10
|
import { recoverDiagnosticRuntime } from "../analysis/health/recovery.ts";
|
|
7
11
|
import { mergeDiagnosticEvidence } from "../diagnostics/evidence.ts";
|
|
8
12
|
import { refreshFileLspMaintenance, refreshLspMaintenance } from "../substrate/lsp/maintenance.ts";
|
|
9
|
-
import type {
|
|
13
|
+
import type {
|
|
14
|
+
HealthDiagnosticScope,
|
|
15
|
+
HealthFileReadiness,
|
|
16
|
+
HealthRefreshAttempt,
|
|
17
|
+
} from "./health-types.ts";
|
|
10
18
|
|
|
11
19
|
interface HealthRefreshAttemptOptions {
|
|
12
20
|
readonly runtime: WorkspaceLspRuntime;
|
|
@@ -51,6 +59,8 @@ async function collectFileRefreshAttempt(
|
|
|
51
59
|
undefined,
|
|
52
60
|
options.control,
|
|
53
61
|
);
|
|
62
|
+
const fileReadiness: HealthFileReadiness =
|
|
63
|
+
readiness.kind === "ready" ? "ready" : readiness.kind === "timeout" ? "pending" : "unavailable";
|
|
54
64
|
return {
|
|
55
65
|
attempt: {
|
|
56
66
|
kind: "completed",
|
|
@@ -59,7 +69,9 @@ async function collectFileRefreshAttempt(
|
|
|
59
69
|
requestedDiagnosticScope: scope,
|
|
60
70
|
operationScope: "file-runtime",
|
|
61
71
|
attemptedActiveClients: readiness.kind === "ready" ? 1 : 0,
|
|
72
|
+
fileReadiness,
|
|
62
73
|
restartedClients: 0,
|
|
74
|
+
processCrashRecovery: readiness.processCrashRecovery ?? emptyProcessCrashRecoverySummary(),
|
|
63
75
|
staleAssessment: {
|
|
64
76
|
scope: "file",
|
|
65
77
|
suspected: null,
|
|
@@ -126,7 +138,16 @@ async function collectWorkspaceRefreshAttempt(
|
|
|
126
138
|
elapsedMs: Date.now() - options.attemptedAt,
|
|
127
139
|
requestedDiagnosticScope: options.diagnosticsScope,
|
|
128
140
|
operationScope: "workspace-runtime",
|
|
141
|
+
attemptedActiveClients: recovery.attemptedClients,
|
|
142
|
+
restartedClients: recovery.restartedClients,
|
|
143
|
+
staleAssessment: {
|
|
144
|
+
scope: "workspace",
|
|
145
|
+
suspected: recovery.staleAssessment.suspected,
|
|
146
|
+
matchedFileCount: recovery.staleAssessment.matchedFiles.length,
|
|
147
|
+
warning: recovery.staleAssessment.warning,
|
|
148
|
+
},
|
|
129
149
|
diagnosticEvidence,
|
|
150
|
+
processCrashRecovery: recovery.processCrashRecovery,
|
|
130
151
|
reason: recovery.refreshFailureReason,
|
|
131
152
|
},
|
|
132
153
|
diagnosticReport: recovery.diagnosticReport,
|
|
@@ -141,6 +162,7 @@ async function collectWorkspaceRefreshAttempt(
|
|
|
141
162
|
operationScope: "workspace-runtime",
|
|
142
163
|
attemptedActiveClients: recovery.attemptedClients,
|
|
143
164
|
restartedClients: recovery.restartedClients,
|
|
165
|
+
processCrashRecovery: recovery.processCrashRecovery,
|
|
144
166
|
diagnosticEvidence,
|
|
145
167
|
staleAssessment: {
|
|
146
168
|
scope: "workspace",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
DiagnosticEvidenceSummary,
|
|
3
3
|
FileScopeDecision,
|
|
4
|
+
ProcessCrashRecoverySummary,
|
|
4
5
|
ProjectServerInfo,
|
|
5
6
|
ProjectServerStatusReason,
|
|
6
7
|
} from "@mrclrchtr/supi-lsp/api";
|
|
@@ -93,6 +94,9 @@ export interface HealthStaleAssessment {
|
|
|
93
94
|
|
|
94
95
|
export type HealthRefreshOperationScope = "file-runtime" | "workspace-runtime";
|
|
95
96
|
|
|
97
|
+
/** Readiness result for a file-scoped maintenance attempt. */
|
|
98
|
+
export type HealthFileReadiness = "ready" | "pending" | "unavailable";
|
|
99
|
+
|
|
96
100
|
/** Shared facts for one completed refresh or file-maintenance attempt. */
|
|
97
101
|
interface CompletedHealthRefreshAttempt {
|
|
98
102
|
readonly kind: "completed";
|
|
@@ -103,7 +107,12 @@ interface CompletedHealthRefreshAttempt {
|
|
|
103
107
|
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
104
108
|
/** Active clients targeted by the best-effort operation; this is not a confirmed-success count. */
|
|
105
109
|
readonly attemptedActiveClients: number;
|
|
110
|
+
/** File readiness after the bounded wait, when this is file-scoped. */
|
|
111
|
+
readonly fileReadiness?: HealthFileReadiness;
|
|
112
|
+
/** Clients restarted by stale-diagnostic recovery. */
|
|
106
113
|
readonly restartedClients: number;
|
|
114
|
+
/** Separate outcome for process-crash route recovery. */
|
|
115
|
+
readonly processCrashRecovery: ProcessCrashRecoverySummary;
|
|
107
116
|
readonly staleAssessment: HealthStaleAssessment;
|
|
108
117
|
}
|
|
109
118
|
|
|
@@ -125,8 +134,18 @@ export type HealthRefreshAttempt =
|
|
|
125
134
|
readonly elapsedMs: number;
|
|
126
135
|
readonly requestedDiagnosticScope: HealthDiagnosticScope;
|
|
127
136
|
readonly operationScope: HealthRefreshOperationScope;
|
|
137
|
+
/** Active clients targeted before the operation failed, when available. */
|
|
138
|
+
readonly attemptedActiveClients?: number;
|
|
139
|
+
/** Clients restarted by stale-diagnostic recovery, when available. */
|
|
140
|
+
readonly restartedClients?: number;
|
|
141
|
+
/** Stale-diagnostic assessment, when the recovery pass returned one. */
|
|
142
|
+
readonly staleAssessment?: HealthStaleAssessment;
|
|
128
143
|
/** Evidence collected before the operation failed, when available. */
|
|
129
144
|
readonly diagnosticEvidence?: DiagnosticEvidenceSummary;
|
|
145
|
+
/** Process-crash outcome, when the recovery pass returned one. */
|
|
146
|
+
readonly processCrashRecovery?: ProcessCrashRecoverySummary;
|
|
147
|
+
/** File readiness outcome, when a file-scoped attempt failed. */
|
|
148
|
+
readonly fileReadiness?: HealthFileReadiness;
|
|
130
149
|
readonly reason: string;
|
|
131
150
|
};
|
|
132
151
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/** Runtime parsers for health and refactor session workflows. */
|
|
2
2
|
|
|
3
3
|
import type { HealthSection, HealthWorkflowInput } from "../health-types.ts";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
import {
|
|
5
|
+
PUBLIC_REFACTOR_OPERATION_NAMES,
|
|
6
|
+
type PublicSourceRange,
|
|
7
|
+
type RefactorApplyWorkflowInput,
|
|
8
|
+
type RefactorOperationInput,
|
|
9
|
+
type RefactorPlanWorkflowInput,
|
|
9
10
|
} from "../refactor-types.ts";
|
|
10
11
|
import type { RefactorTargetInput } from "../target-input.ts";
|
|
11
12
|
import {
|
|
@@ -94,22 +95,23 @@ export function parseRefactorPlanWorkflowInput(
|
|
|
94
95
|
function parseRefactorOperation(value: unknown): InputValidation<RefactorOperationInput> {
|
|
95
96
|
const record = requireRecord(value, "operation");
|
|
96
97
|
if (record.kind === "invalid-input") return record;
|
|
97
|
-
const keysError = requireOnlyKeys(
|
|
98
|
-
record.value,
|
|
99
|
-
["rename_symbol", "extract_function", "extract_variable"],
|
|
100
|
-
"operation",
|
|
101
|
-
);
|
|
98
|
+
const keysError = requireOnlyKeys(record.value, PUBLIC_REFACTOR_OPERATION_NAMES, "operation");
|
|
102
99
|
if (keysError) return invalid(keysError);
|
|
103
|
-
const selected = (
|
|
104
|
-
(key) => record.value[key] !== undefined,
|
|
105
|
-
);
|
|
100
|
+
const selected = PUBLIC_REFACTOR_OPERATION_NAMES.filter((key) => record.value[key] !== undefined);
|
|
106
101
|
if (selected.length !== 1) return invalid("Select exactly one refactor operation.");
|
|
107
102
|
|
|
108
103
|
const name = selected[0];
|
|
109
104
|
const payload = requireRecord(record.value[name], `operation.${name}`);
|
|
110
105
|
if (payload.kind === "invalid-input") return payload;
|
|
111
106
|
if (name === "rename_symbol") return parseRenameOperation(payload.value);
|
|
112
|
-
|
|
107
|
+
if (name === "extract_function" || name === "extract_variable") {
|
|
108
|
+
return parseExtractOperation(name, payload.value);
|
|
109
|
+
}
|
|
110
|
+
const payloadError = requireOnlyKeys(payload.value, [], `operation.${name}`);
|
|
111
|
+
if (payloadError) return invalid(payloadError);
|
|
112
|
+
return name === "update_imports"
|
|
113
|
+
? valid({ update_imports: {} })
|
|
114
|
+
: valid({ delete_dead_code: {} });
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
function parseRenameOperation(
|
|
@@ -3,6 +3,17 @@ import type { ApplyResult } from "../analysis/refactor/apply.ts";
|
|
|
3
3
|
import type { RefactorPlan } from "./refactor-plans.ts";
|
|
4
4
|
import type { RefactorTargetInput, SourcePointInput } from "./target-input.ts";
|
|
5
5
|
|
|
6
|
+
/** Public refactor operations exposed by code_refactor_plan. */
|
|
7
|
+
export const PUBLIC_REFACTOR_OPERATION_NAMES = [
|
|
8
|
+
"rename_symbol",
|
|
9
|
+
"extract_function",
|
|
10
|
+
"extract_variable",
|
|
11
|
+
"update_imports",
|
|
12
|
+
"delete_dead_code",
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
15
|
+
export type PublicRefactorOperationName = (typeof PUBLIC_REFACTOR_OPERATION_NAMES)[number];
|
|
16
|
+
|
|
6
17
|
export interface PublicSourceRange {
|
|
7
18
|
readonly start: Omit<SourcePointInput, "file">;
|
|
8
19
|
readonly end: Omit<SourcePointInput, "file">;
|
|
@@ -21,7 +32,9 @@ export type RefactorOperationInput =
|
|
|
21
32
|
readonly newName: string;
|
|
22
33
|
readonly range: PublicSourceRange;
|
|
23
34
|
};
|
|
24
|
-
}
|
|
35
|
+
}
|
|
36
|
+
| { readonly update_imports: Record<string, never> }
|
|
37
|
+
| { readonly delete_dead_code: Record<string, never> };
|
|
25
38
|
|
|
26
39
|
export interface RefactorPlanWorkflowInput {
|
|
27
40
|
readonly target: RefactorTargetInput;
|