@mrclrchtr/supi-code-intelligence 1.3.1 → 1.5.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 +70 -32
- package/node_modules/@mrclrchtr/supi-core/README.md +52 -41
- package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/api.ts +15 -13
- package/node_modules/@mrclrchtr/supi-core/src/{config-settings.ts → config/config-settings.ts} +2 -2
- package/node_modules/@mrclrchtr/{supi-lsp/node_modules/@mrclrchtr/supi-core/src → supi-core/src/context}/context-provider-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/extension.ts +1 -1
- package/node_modules/@mrclrchtr/supi-core/src/index.ts +15 -13
- package/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
- package/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +42 -10
- package/node_modules/@mrclrchtr/{supi-lsp/node_modules/@mrclrchtr/supi-core/src → supi-core/src/settings}/settings-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/README.md +58 -39
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/README.md +52 -41
- 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/api.ts +15 -13
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/{config-settings.ts → config/config-settings.ts} +2 -2
- package/node_modules/@mrclrchtr/{supi-core/src → supi-lsp/node_modules/@mrclrchtr/supi-core/src/context}/context-provider-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/extension.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/index.ts +15 -13
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +42 -10
- package/node_modules/@mrclrchtr/{supi-core/src → supi-lsp/node_modules/@mrclrchtr/supi-core/src/settings}/settings-registry.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/package.json +3 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +16 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client-refresh.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/client/client.ts +27 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/client/transport.ts +61 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +244 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/{types.ts → config/types.ts} +4 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/coordinates.ts +11 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-augmentation.ts +5 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-context.ts +115 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-display.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostic-summary.ts +3 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/diagnostics.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/stale-diagnostics.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/diagnostics/suppression-diagnostics.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/{workspace-sentinels.ts → diagnostics/workspace-sentinels.ts} +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/format.ts +2 -23
- package/node_modules/@mrclrchtr/supi-lsp/src/index.ts +18 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/lsp.ts +72 -120
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-diagnostics.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-helpers.ts +4 -2
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-project-info.ts +10 -21
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-recovery.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager-workspace-symbol.ts +158 -6
- package/node_modules/@mrclrchtr/supi-lsp/src/manager/manager.ts +202 -43
- package/node_modules/@mrclrchtr/supi-lsp/src/{lsp-state.ts → session/lsp-state.ts} +22 -11
- package/node_modules/@mrclrchtr/supi-lsp/src/{scanner.ts → session/scanner.ts} +3 -3
- package/node_modules/@mrclrchtr/supi-lsp/src/{service-registry.ts → session/service-registry.ts} +109 -33
- package/node_modules/@mrclrchtr/supi-lsp/src/{settings-registration.ts → session/settings-registration.ts} +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/session/tree-persist.ts +75 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/summary.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/guidance.ts +78 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/names.ts +19 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/{overrides.ts → tool/overrides.ts} +55 -24
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/register-tools.ts +71 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/service-actions.ts +258 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/tool/tool-specs.ts +248 -0
- package/node_modules/@mrclrchtr/supi-lsp/src/{ui.ts → ui/ui.ts} +4 -4
- package/node_modules/@mrclrchtr/supi-lsp/src/utils.ts +5 -23
- package/node_modules/@mrclrchtr/supi-tree-sitter/README.md +58 -39
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/README.md +107 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +44 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/api.ts +85 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config-settings.ts +76 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/config/config.ts +186 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-messages.ts +119 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-provider-registry.ts +36 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/context/context-tag.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/debug-registry.ts +255 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/extension.ts +1 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/index.ts +85 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/path-utils.ts +40 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/project-roots.ts +170 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/registry-utils.ts +86 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/session-utils.ts +29 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-command.ts +15 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-registry.ts +41 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/settings/settings-ui.ts +226 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/terminal.ts +60 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +8 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/api.ts +6 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/index.ts +6 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{runtime.ts → session/runtime.ts} +6 -5
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/session/service-registry.ts +30 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{session.ts → session/session.ts} +20 -12
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/action-specs.ts +92 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{callees.ts → tool/callees.ts} +3 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{exports.ts → tool/exports.ts} +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{formatting.ts → tool/formatting.ts} +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tool/guidance.ts +31 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{imports.ts → tool/imports.ts} +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{node-at.ts → tool/node-at.ts} +3 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/{outline.ts → tool/outline.ts} +3 -3
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/tree-sitter.ts +118 -91
- package/node_modules/@mrclrchtr/supi-tree-sitter/src/types.ts +13 -2
- package/package.json +4 -4
- package/src/actions/affected-action.ts +4 -4
- package/src/actions/brief-action.ts +12 -13
- package/src/actions/callees-action.ts +14 -10
- package/src/actions/callers-action.ts +4 -4
- package/src/actions/implementations-action.ts +4 -4
- package/src/code-intelligence.ts +4 -11
- package/src/pattern-structured.ts +20 -22
- package/src/providers/semantic-provider.ts +34 -0
- package/src/providers/structural-provider.ts +26 -0
- package/src/search-helpers.ts +4 -15
- package/src/target-resolution.ts +26 -35
- package/src/tool/action-specs.ts +66 -0
- package/src/tool/guidance.ts +18 -0
- package/src/tool-actions.ts +23 -40
- package/node_modules/@mrclrchtr/supi-lsp/src/guidance.ts +0 -163
- package/node_modules/@mrclrchtr/supi-lsp/src/search-fallback.ts +0 -98
- package/node_modules/@mrclrchtr/supi-lsp/src/tool-actions.ts +0 -430
- package/node_modules/@mrclrchtr/supi-lsp/src/tree-persist.ts +0 -48
- package/node_modules/@mrclrchtr/supi-lsp/src/tsconfig-scope.ts +0 -156
- package/src/guidance.ts +0 -42
- /package/node_modules/@mrclrchtr/supi-core/src/{config.ts → config/config.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{context-messages.ts → context/context-messages.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{context-tag.ts → context/context-tag.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{settings-command.ts → settings/settings-command.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-core/src/{settings-ui.ts → settings/settings-ui.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/{config.ts → config/config.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/{context-messages.ts → context/context-messages.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/{context-tag.ts → context/context-tag.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/{settings-command.ts → settings/settings-command.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/{settings-ui.ts → settings/settings-ui.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/src/{capabilities.ts → config/capabilities.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/src/{config.ts → config/config.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/src/{defaults.json → config/defaults.json} +0 -0
- /package/node_modules/@mrclrchtr/supi-lsp/src/{renderer.ts → ui/renderer.ts} +0 -0
- /package/node_modules/@mrclrchtr/supi-tree-sitter/src/{structure.ts → tool/structure.ts} +0 -0
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
// biome-ignore lint/nursery/noExcessiveLinesPerFile: LspClient remains a cohesive stateful wrapper; refresh logic is already split out.
|
|
5
5
|
import { type ChildProcess, spawn } from "node:child_process";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
|
-
import
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { CLIENT_CAPABILITIES } from "../config/capabilities.ts";
|
|
8
9
|
import type {
|
|
9
10
|
CodeAction,
|
|
10
11
|
CodeActionContext,
|
|
@@ -27,9 +28,9 @@ import type {
|
|
|
27
28
|
VersionedTextDocumentIdentifier,
|
|
28
29
|
WorkspaceEdit,
|
|
29
30
|
WorkspaceSymbol,
|
|
30
|
-
} from "../types.ts";
|
|
31
|
+
} from "../config/types.ts";
|
|
31
32
|
import { detectLanguageId, fileToUri, uriToFile } from "../utils.ts";
|
|
32
|
-
import { JsonRpcClient } from "./transport.ts";
|
|
33
|
+
import { JsonRpcClient, JsonRpcRequestError } from "./transport.ts";
|
|
33
34
|
|
|
34
35
|
const SHUTDOWN_TIMEOUT_MS = 5_000;
|
|
35
36
|
const DIAGNOSTIC_WAIT_MS = 3_000;
|
|
@@ -119,6 +120,7 @@ export class LspClient {
|
|
|
119
120
|
this.handlePublishDiagnostics(params as PublishDiagnosticsParams);
|
|
120
121
|
}
|
|
121
122
|
});
|
|
123
|
+
this.rpc.onRequest((method, params) => this.handleServerRequest(method, params));
|
|
122
124
|
|
|
123
125
|
// Handle crashes
|
|
124
126
|
this.process.on("exit", (_code) => {
|
|
@@ -469,6 +471,28 @@ export class LspClient {
|
|
|
469
471
|
}
|
|
470
472
|
}
|
|
471
473
|
|
|
474
|
+
private handleServerRequest(method: string, params: unknown): unknown {
|
|
475
|
+
switch (method) {
|
|
476
|
+
case "workspace/configuration":
|
|
477
|
+
return this.buildWorkspaceConfigurationResult(params);
|
|
478
|
+
case "workspace/workspaceFolders":
|
|
479
|
+
return [{ uri: fileToUri(this.root), name: path.basename(this.root) || this.root }];
|
|
480
|
+
case "client/registerCapability":
|
|
481
|
+
case "client/unregisterCapability":
|
|
482
|
+
case "window/workDoneProgress/create":
|
|
483
|
+
return null;
|
|
484
|
+
default:
|
|
485
|
+
throw new JsonRpcRequestError(-32601, `Method not found: ${method}`);
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
private buildWorkspaceConfigurationResult(params: unknown): unknown[] {
|
|
490
|
+
if (!params || typeof params !== "object") return [];
|
|
491
|
+
const items = (params as { items?: unknown }).items;
|
|
492
|
+
if (!Array.isArray(items)) return [];
|
|
493
|
+
return items.map(() => null);
|
|
494
|
+
}
|
|
495
|
+
|
|
472
496
|
private handlePublishDiagnostics(params: PublishDiagnosticsParams): void {
|
|
473
497
|
// If the publication includes a version and we have a newer synced
|
|
474
498
|
// version for this open document, ignore the stale publication.
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
import type { Readable, Writable } from "node:stream";
|
|
4
4
|
import type {
|
|
5
|
+
JsonRpcId,
|
|
5
6
|
JsonRpcMessage,
|
|
6
7
|
JsonRpcNotification,
|
|
7
8
|
JsonRpcRequest,
|
|
8
9
|
JsonRpcResponse,
|
|
9
|
-
} from "../types.ts";
|
|
10
|
+
} from "../config/types.ts";
|
|
10
11
|
|
|
11
12
|
const CONTENT_LENGTH = "Content-Length: ";
|
|
12
13
|
const HEADER_DELIMITER = "\r\n\r\n";
|
|
@@ -15,6 +16,7 @@ const DEFAULT_TIMEOUT_MS = 30_000;
|
|
|
15
16
|
// ── Types ─────────────────────────────────────────────────────────────
|
|
16
17
|
|
|
17
18
|
export type NotificationHandler = (method: string, params: unknown) => void;
|
|
19
|
+
export type RequestHandler = (method: string, params: unknown) => Promise<unknown> | unknown;
|
|
18
20
|
|
|
19
21
|
interface PendingRequest {
|
|
20
22
|
resolve: (result: unknown) => void;
|
|
@@ -22,13 +24,25 @@ interface PendingRequest {
|
|
|
22
24
|
timer: ReturnType<typeof setTimeout>;
|
|
23
25
|
}
|
|
24
26
|
|
|
27
|
+
export class JsonRpcRequestError extends Error {
|
|
28
|
+
constructor(
|
|
29
|
+
readonly code: number,
|
|
30
|
+
message: string,
|
|
31
|
+
readonly data?: unknown,
|
|
32
|
+
) {
|
|
33
|
+
super(message);
|
|
34
|
+
this.name = "JsonRpcRequestError";
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
25
38
|
// ── JsonRpcClient ─────────────────────────────────────────────────────
|
|
26
39
|
|
|
27
40
|
export class JsonRpcClient {
|
|
28
41
|
private nextId = 1;
|
|
29
42
|
private buffer = Buffer.alloc(0);
|
|
30
|
-
private pending = new Map<
|
|
43
|
+
private pending = new Map<JsonRpcId, PendingRequest>();
|
|
31
44
|
private notificationHandler: NotificationHandler | null = null;
|
|
45
|
+
private requestHandler: RequestHandler | null = null;
|
|
32
46
|
private closed = false;
|
|
33
47
|
private readonly timeoutMs: number;
|
|
34
48
|
|
|
@@ -48,6 +62,11 @@ export class JsonRpcClient {
|
|
|
48
62
|
this.notificationHandler = handler;
|
|
49
63
|
}
|
|
50
64
|
|
|
65
|
+
/** Register a handler for server-initiated requests. */
|
|
66
|
+
onRequest(handler: RequestHandler): void {
|
|
67
|
+
this.requestHandler = handler;
|
|
68
|
+
}
|
|
69
|
+
|
|
51
70
|
/** Send a request and wait for the correlated response, optionally overriding the timeout. */
|
|
52
71
|
sendRequest(
|
|
53
72
|
method: string,
|
|
@@ -147,9 +166,11 @@ export class JsonRpcClient {
|
|
|
147
166
|
// Response (has id, has result or error)
|
|
148
167
|
if ("id" in msg && msg.id != null && ("result" in msg || "error" in msg)) {
|
|
149
168
|
const response = msg as JsonRpcResponse;
|
|
150
|
-
const
|
|
169
|
+
const id = response.id;
|
|
170
|
+
if (id === null) return;
|
|
171
|
+
const pending = this.pending.get(id);
|
|
151
172
|
if (pending) {
|
|
152
|
-
this.pending.delete(
|
|
173
|
+
this.pending.delete(id);
|
|
153
174
|
clearTimeout(pending.timer);
|
|
154
175
|
if (response.error) {
|
|
155
176
|
pending.reject(new Error(`LSP error ${response.error.code}: ${response.error.message}`));
|
|
@@ -164,9 +185,44 @@ export class JsonRpcClient {
|
|
|
164
185
|
if ("method" in msg && !("id" in msg)) {
|
|
165
186
|
const notification = msg as JsonRpcNotification;
|
|
166
187
|
this.notificationHandler?.(notification.method, notification.params);
|
|
188
|
+
return;
|
|
167
189
|
}
|
|
168
190
|
|
|
169
|
-
// Request from server (has id + method)
|
|
191
|
+
// Request from server (has id + method)
|
|
192
|
+
if ("method" in msg && "id" in msg && msg.id != null) {
|
|
193
|
+
void this.handleInboundRequest(msg as JsonRpcRequest);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private async handleInboundRequest(request: JsonRpcRequest): Promise<void> {
|
|
198
|
+
if (this.closed) return;
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
if (!this.requestHandler) {
|
|
202
|
+
throw new JsonRpcRequestError(-32601, `Method not found: ${request.method}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const result = await this.requestHandler(request.method, request.params);
|
|
206
|
+
this.writeMessage({
|
|
207
|
+
jsonrpc: "2.0",
|
|
208
|
+
id: request.id,
|
|
209
|
+
result: result ?? null,
|
|
210
|
+
} satisfies JsonRpcResponse);
|
|
211
|
+
} catch (error) {
|
|
212
|
+
const failure =
|
|
213
|
+
error instanceof JsonRpcRequestError
|
|
214
|
+
? error
|
|
215
|
+
: new JsonRpcRequestError(-32603, error instanceof Error ? error.message : String(error));
|
|
216
|
+
this.writeMessage({
|
|
217
|
+
jsonrpc: "2.0",
|
|
218
|
+
id: request.id,
|
|
219
|
+
error: {
|
|
220
|
+
code: failure.code,
|
|
221
|
+
message: failure.message,
|
|
222
|
+
...(failure.data !== undefined ? { data: failure.data } : {}),
|
|
223
|
+
},
|
|
224
|
+
} satisfies JsonRpcResponse);
|
|
225
|
+
}
|
|
170
226
|
}
|
|
171
227
|
|
|
172
228
|
private onClose(): void {
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// tsconfig-aware file scope detection.
|
|
2
|
+
//
|
|
3
|
+
// Determines whether a file is within the compilation scope of its nearest
|
|
4
|
+
// tsconfig.json or jsconfig.json using the TypeScript compiler's own config
|
|
5
|
+
// parsing APIs. Used by the diagnostic filter to suppress LSP errors on files
|
|
6
|
+
// that TypeScript itself would not include in the project.
|
|
7
|
+
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import ts from "typescript";
|
|
10
|
+
|
|
11
|
+
interface ParsedProjectConfig {
|
|
12
|
+
configPath: string;
|
|
13
|
+
configDir: string;
|
|
14
|
+
fileNames: Set<string>;
|
|
15
|
+
explicitFiles: Set<string> | null;
|
|
16
|
+
includeFilePattern: RegExp | null;
|
|
17
|
+
excludePattern: RegExp | null;
|
|
18
|
+
supportedExtensions: Set<string>;
|
|
19
|
+
usesDefaultInclude: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const nearestConfigCache = new Map<string, string | null>();
|
|
23
|
+
const parsedConfigCache = new Map<string, ParsedProjectConfig | null>();
|
|
24
|
+
|
|
25
|
+
const tsInternal = ts as typeof ts & {
|
|
26
|
+
getFileMatcherPatterns?: (
|
|
27
|
+
configDir: string,
|
|
28
|
+
excludes: readonly string[] | undefined,
|
|
29
|
+
includes: readonly string[] | undefined,
|
|
30
|
+
useCaseSensitiveFileNames: boolean,
|
|
31
|
+
currentDirectory: string,
|
|
32
|
+
) => {
|
|
33
|
+
includeFilePattern?: string;
|
|
34
|
+
excludePattern?: string;
|
|
35
|
+
};
|
|
36
|
+
getSupportedExtensions?: (
|
|
37
|
+
options: ts.CompilerOptions,
|
|
38
|
+
extraFileExtensions?: unknown,
|
|
39
|
+
) => ReadonlyArray<ReadonlyArray<string>>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Check whether a file is excluded by its nearest tsconfig.json or jsconfig.json.
|
|
44
|
+
*
|
|
45
|
+
* @param filePath - Project-relative file path (e.g., "packages/foo/__tests__/x.test.ts")
|
|
46
|
+
* @param cwd - Absolute project root directory
|
|
47
|
+
* @returns `true` if the file is excluded from compilation scope
|
|
48
|
+
*/
|
|
49
|
+
export function isFileExcludedByTsconfig(filePath: string, cwd: string): boolean {
|
|
50
|
+
const absolutePath = path.resolve(cwd, filePath);
|
|
51
|
+
const configPath = findNearestProjectConfig(path.dirname(absolutePath), cwd);
|
|
52
|
+
if (!configPath) return false;
|
|
53
|
+
|
|
54
|
+
const parsed = parseProjectConfig(configPath);
|
|
55
|
+
if (!parsed) return false;
|
|
56
|
+
|
|
57
|
+
return !isFileInProjectScope(parsed, absolutePath);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Find the nearest tsconfig.json or jsconfig.json walking upward from `startDir`,
|
|
62
|
+
* stopping at `rootDir`.
|
|
63
|
+
*/
|
|
64
|
+
function findNearestProjectConfig(startDir: string, rootDir: string): string | null {
|
|
65
|
+
let dir = path.resolve(startDir);
|
|
66
|
+
const resolvedRoot = path.resolve(rootDir);
|
|
67
|
+
|
|
68
|
+
while (true) {
|
|
69
|
+
const cacheKey = `${normalizePath(dir)}::${normalizePath(resolvedRoot)}`;
|
|
70
|
+
const cached = nearestConfigCache.get(cacheKey);
|
|
71
|
+
if (cached !== undefined) return cached;
|
|
72
|
+
|
|
73
|
+
const configPath = getLocalProjectConfig(dir);
|
|
74
|
+
if (configPath) {
|
|
75
|
+
const resolvedConfigPath = path.resolve(configPath);
|
|
76
|
+
nearestConfigCache.set(cacheKey, resolvedConfigPath);
|
|
77
|
+
return resolvedConfigPath;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (path.relative(resolvedRoot, dir).startsWith("..") || dir === resolvedRoot) {
|
|
81
|
+
nearestConfigCache.set(cacheKey, null);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const parent = path.dirname(dir);
|
|
86
|
+
if (parent === dir) {
|
|
87
|
+
nearestConfigCache.set(cacheKey, null);
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
dir = parent;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getLocalProjectConfig(directory: string): string | null {
|
|
95
|
+
const tsconfigPath = path.join(directory, "tsconfig.json");
|
|
96
|
+
if (ts.sys.fileExists(tsconfigPath)) return tsconfigPath;
|
|
97
|
+
|
|
98
|
+
const jsconfigPath = path.join(directory, "jsconfig.json");
|
|
99
|
+
if (ts.sys.fileExists(jsconfigPath)) return jsconfigPath;
|
|
100
|
+
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function parseProjectConfig(configPath: string): ParsedProjectConfig | null {
|
|
105
|
+
const normalizedConfigPath = normalizePath(configPath);
|
|
106
|
+
const cached = parsedConfigCache.get(normalizedConfigPath);
|
|
107
|
+
if (cached !== undefined) return cached;
|
|
108
|
+
|
|
109
|
+
const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, createParseConfigHost());
|
|
110
|
+
if (!parsed) {
|
|
111
|
+
parsedConfigCache.set(normalizedConfigPath, null);
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const configDir = path.dirname(path.resolve(configPath));
|
|
116
|
+
const explicitFiles = extractExplicitFiles(parsed.raw.files, configDir);
|
|
117
|
+
const usesDefaultInclude = explicitFiles === null && !Array.isArray(parsed.raw.include);
|
|
118
|
+
const { includeFilePattern, excludePattern } = createFileMatchers(
|
|
119
|
+
configDir,
|
|
120
|
+
parsed.raw.include,
|
|
121
|
+
parsed.raw.exclude,
|
|
122
|
+
usesDefaultInclude,
|
|
123
|
+
);
|
|
124
|
+
const supportedExtensions = new Set(getSupportedExtensions(parsed.options));
|
|
125
|
+
if (parsed.options.resolveJsonModule) supportedExtensions.add(".json");
|
|
126
|
+
|
|
127
|
+
const result = {
|
|
128
|
+
configPath: path.resolve(configPath),
|
|
129
|
+
configDir,
|
|
130
|
+
fileNames: new Set(parsed.fileNames.map(normalizePath)),
|
|
131
|
+
explicitFiles,
|
|
132
|
+
includeFilePattern,
|
|
133
|
+
excludePattern,
|
|
134
|
+
supportedExtensions,
|
|
135
|
+
usesDefaultInclude,
|
|
136
|
+
} satisfies ParsedProjectConfig;
|
|
137
|
+
parsedConfigCache.set(normalizedConfigPath, result);
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function extractExplicitFiles(rawFiles: unknown, configDir: string): Set<string> | null {
|
|
142
|
+
if (!Array.isArray(rawFiles)) return null;
|
|
143
|
+
return new Set(
|
|
144
|
+
rawFiles
|
|
145
|
+
.filter((entry): entry is string => typeof entry === "string")
|
|
146
|
+
.map((entry) => normalizePath(path.resolve(configDir, entry))),
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function createFileMatchers(
|
|
151
|
+
configDir: string,
|
|
152
|
+
rawInclude: unknown,
|
|
153
|
+
rawExclude: unknown,
|
|
154
|
+
useDefaultInclude: boolean,
|
|
155
|
+
): {
|
|
156
|
+
includeFilePattern: RegExp | null;
|
|
157
|
+
excludePattern: RegExp | null;
|
|
158
|
+
} {
|
|
159
|
+
const includeSpecs = Array.isArray(rawInclude)
|
|
160
|
+
? rawInclude.filter((entry): entry is string => typeof entry === "string")
|
|
161
|
+
: undefined;
|
|
162
|
+
const excludeSpecs = Array.isArray(rawExclude)
|
|
163
|
+
? rawExclude.filter((entry): entry is string => typeof entry === "string")
|
|
164
|
+
: undefined;
|
|
165
|
+
const matcherPatterns = getFileMatcherPatterns(
|
|
166
|
+
configDir,
|
|
167
|
+
excludeSpecs,
|
|
168
|
+
useDefaultInclude ? ["**/*"] : includeSpecs,
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
includeFilePattern: matcherPatterns.includeFilePattern
|
|
173
|
+
? new RegExp(matcherPatterns.includeFilePattern)
|
|
174
|
+
: null,
|
|
175
|
+
excludePattern: matcherPatterns.excludePattern
|
|
176
|
+
? new RegExp(matcherPatterns.excludePattern)
|
|
177
|
+
: null,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function isFileInProjectScope(parsed: ParsedProjectConfig, absolutePath: string): boolean {
|
|
182
|
+
const normalizedPath = normalizePath(absolutePath);
|
|
183
|
+
if (parsed.fileNames.has(normalizedPath)) return true;
|
|
184
|
+
|
|
185
|
+
const extension = path.extname(absolutePath).toLowerCase();
|
|
186
|
+
if (!parsed.supportedExtensions.has(extension)) return false;
|
|
187
|
+
|
|
188
|
+
if (parsed.explicitFiles) return parsed.explicitFiles.has(normalizedPath);
|
|
189
|
+
if (!isWithinOrEqual(parsed.configDir, absolutePath)) return false;
|
|
190
|
+
if (parsed.excludePattern?.test(normalizedPath)) return false;
|
|
191
|
+
if (parsed.usesDefaultInclude) return true;
|
|
192
|
+
return parsed.includeFilePattern ? parsed.includeFilePattern.test(normalizedPath) : false;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function getSupportedExtensions(options: ts.CompilerOptions): string[] {
|
|
196
|
+
return tsInternal.getSupportedExtensions
|
|
197
|
+
? [...tsInternal.getSupportedExtensions(options, undefined).flat()]
|
|
198
|
+
: [".ts", ".tsx", ".d.ts", ".cts", ".d.cts", ".mts", ".d.mts"];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function getFileMatcherPatterns(
|
|
202
|
+
configDir: string,
|
|
203
|
+
excludeSpecs: readonly string[] | undefined,
|
|
204
|
+
includeSpecs: readonly string[] | undefined,
|
|
205
|
+
): { includeFilePattern?: string; excludePattern?: string } {
|
|
206
|
+
return tsInternal.getFileMatcherPatterns
|
|
207
|
+
? tsInternal.getFileMatcherPatterns(
|
|
208
|
+
configDir,
|
|
209
|
+
excludeSpecs,
|
|
210
|
+
includeSpecs,
|
|
211
|
+
ts.sys.useCaseSensitiveFileNames,
|
|
212
|
+
path.parse(configDir).root,
|
|
213
|
+
)
|
|
214
|
+
: {};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function createParseConfigHost(): ts.ParseConfigFileHost {
|
|
218
|
+
return {
|
|
219
|
+
...ts.sys,
|
|
220
|
+
onUnRecoverableConfigFileDiagnostic: () => {
|
|
221
|
+
// Treat invalid configs as unsupported rather than surfacing a secondary
|
|
222
|
+
// filter failure to the agent.
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function isWithinOrEqual(root: string, target: string): boolean {
|
|
228
|
+
const relative = path.relative(root, target);
|
|
229
|
+
return relative === "" || (!relative.startsWith(`..${path.sep}`) && relative !== "..");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function normalizePath(target: string): string {
|
|
233
|
+
const resolved = path.resolve(target).replaceAll("\\", "/");
|
|
234
|
+
return ts.sys.useCaseSensitiveFileNames ? resolved : resolved.toLowerCase();
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Clear cached nearest-config lookups and parsed project config state.
|
|
239
|
+
* Useful for testing and after workspace file changes.
|
|
240
|
+
*/
|
|
241
|
+
export function clearTsconfigCache(): void {
|
|
242
|
+
nearestConfigCache.clear();
|
|
243
|
+
parsedConfigCache.clear();
|
|
244
|
+
}
|
|
@@ -348,16 +348,18 @@ export interface TextDocumentPositionParams {
|
|
|
348
348
|
|
|
349
349
|
// ── JSON-RPC ──────────────────────────────────────────────────────────
|
|
350
350
|
|
|
351
|
+
export type JsonRpcId = number | string;
|
|
352
|
+
|
|
351
353
|
export interface JsonRpcRequest {
|
|
352
354
|
jsonrpc: "2.0";
|
|
353
|
-
id:
|
|
355
|
+
id: JsonRpcId;
|
|
354
356
|
method: string;
|
|
355
357
|
params?: unknown;
|
|
356
358
|
}
|
|
357
359
|
|
|
358
360
|
export interface JsonRpcResponse {
|
|
359
361
|
jsonrpc: "2.0";
|
|
360
|
-
id:
|
|
362
|
+
id: JsonRpcId | null;
|
|
361
363
|
result?: unknown;
|
|
362
364
|
error?: { code: number; message: string; data?: unknown };
|
|
363
365
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Position } from "./config/types.ts";
|
|
2
|
+
|
|
3
|
+
/** Convert public 1-based coordinates into a 0-based LSP position. */
|
|
4
|
+
export function toLspPosition(line: number, character: number): Position {
|
|
5
|
+
return { line: line - 1, character: character - 1 };
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/** Convert a 0-based LSP position into 1-based display coordinates. */
|
|
9
|
+
export function toOneBasedPosition(position: Position): { line: number; character: number } {
|
|
10
|
+
return { line: position.line + 1, character: position.character + 1 };
|
|
11
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Diagnostic, Hover, MarkedString, MarkupContent } from "../config/types.ts";
|
|
2
2
|
import type { LspManager } from "../manager/manager.ts";
|
|
3
|
-
import
|
|
3
|
+
import { resolveSessionPath } from "../utils.ts";
|
|
4
4
|
|
|
5
5
|
const AUGMENT_TIMEOUT_MS = 500;
|
|
6
6
|
|
|
@@ -12,13 +12,13 @@ export async function augmentDiagnostics(
|
|
|
12
12
|
filePath: string,
|
|
13
13
|
diags: Diagnostic[],
|
|
14
14
|
manager: LspManager,
|
|
15
|
-
|
|
15
|
+
cwd: string,
|
|
16
16
|
): Promise<string | null> {
|
|
17
17
|
const firstError = diags.find((d) => d.severity === 1);
|
|
18
18
|
if (!firstError) return null;
|
|
19
19
|
|
|
20
|
-
const resolvedPath =
|
|
21
|
-
const client = await manager.getClientForFile(
|
|
20
|
+
const resolvedPath = resolveSessionPath(cwd, filePath);
|
|
21
|
+
const client = await manager.getClientForFile(resolvedPath);
|
|
22
22
|
if (!client) return null;
|
|
23
23
|
|
|
24
24
|
const pos = firstError.range.start;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// Diagnostic context formatting for the LSP extension.
|
|
2
|
+
// Extracted from guidance.ts to keep prompt surfaces separate from formatting logic.
|
|
3
|
+
|
|
4
|
+
import type { Diagnostic } from "../config/types.ts";
|
|
5
|
+
import type { OutstandingDiagnosticSummaryEntry } from "../manager/manager-types.ts";
|
|
6
|
+
import { splitSuppressionDiagnostics } from "./suppression-diagnostics.ts";
|
|
7
|
+
|
|
8
|
+
export const MAX_DETAILED_DIAGNOSTICS = 5;
|
|
9
|
+
const MAX_DETAIL_LINES_PER_FILE = 3;
|
|
10
|
+
|
|
11
|
+
interface DetailedDiagnostics {
|
|
12
|
+
file: string;
|
|
13
|
+
diagnostics: Diagnostic[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function formatDiagnosticsContext(
|
|
17
|
+
diagnostics: OutstandingDiagnosticSummaryEntry[],
|
|
18
|
+
maxFiles: number = 3,
|
|
19
|
+
detailed?: DetailedDiagnostics[],
|
|
20
|
+
staleWarning?: string | null,
|
|
21
|
+
): string | null {
|
|
22
|
+
if (diagnostics.length === 0) return null;
|
|
23
|
+
|
|
24
|
+
const totalDiags = diagnostics.reduce((sum, d) => sum + d.total, 0);
|
|
25
|
+
const detailMap = buildDetailMap(totalDiags, detailed);
|
|
26
|
+
|
|
27
|
+
const lines: string[] = [];
|
|
28
|
+
if (staleWarning) lines.push(staleWarning);
|
|
29
|
+
const visible = diagnostics.slice(0, maxFiles);
|
|
30
|
+
|
|
31
|
+
for (const entry of visible) {
|
|
32
|
+
lines.push(`- ${entry.file}: ${formatCounts(entry)}`);
|
|
33
|
+
appendDetailLines(lines, detailMap?.get(entry.file));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const remaining = diagnostics.length - visible.length;
|
|
37
|
+
if (remaining > 0) {
|
|
38
|
+
lines.push(`- +${remaining} more file${remaining === 1 ? "" : "s"}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
appendSuppressionCleanup(
|
|
42
|
+
lines,
|
|
43
|
+
visible.map((entry) => entry.file),
|
|
44
|
+
detailMap,
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return [
|
|
48
|
+
'<extension-context source="supi-lsp">',
|
|
49
|
+
"Outstanding diagnostics — fix these before proceeding:",
|
|
50
|
+
...lines,
|
|
51
|
+
"</extension-context>",
|
|
52
|
+
].join("\n");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function buildDetailMap(
|
|
56
|
+
totalDiags: number,
|
|
57
|
+
detailed?: DetailedDiagnostics[],
|
|
58
|
+
): Map<string, Diagnostic[]> | null {
|
|
59
|
+
if (totalDiags > MAX_DETAILED_DIAGNOSTICS || !detailed || detailed.length === 0) return null;
|
|
60
|
+
return new Map(detailed.map((d) => [d.file, d.diagnostics]));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function appendDetailLines(lines: string[], details?: Diagnostic[]): void {
|
|
64
|
+
if (!details) return;
|
|
65
|
+
for (const d of details.slice(0, MAX_DETAIL_LINES_PER_FILE)) {
|
|
66
|
+
const line = d.range.start.line + 1;
|
|
67
|
+
const char = d.range.start.character + 1;
|
|
68
|
+
const source = d.source ? ` ${d.source}` : "";
|
|
69
|
+
lines.push(` L${line} C${char}${source}: ${d.message}`);
|
|
70
|
+
}
|
|
71
|
+
if (details.length > MAX_DETAIL_LINES_PER_FILE) {
|
|
72
|
+
const extra = details.length - MAX_DETAIL_LINES_PER_FILE;
|
|
73
|
+
lines.push(` +${extra} more`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function appendSuppressionCleanup(
|
|
78
|
+
lines: string[],
|
|
79
|
+
visibleFiles: string[],
|
|
80
|
+
detailMap: Map<string, Diagnostic[]> | null,
|
|
81
|
+
): void {
|
|
82
|
+
if (!detailMap) return;
|
|
83
|
+
|
|
84
|
+
const suppressionLines: string[] = [];
|
|
85
|
+
for (const file of visibleFiles) {
|
|
86
|
+
const diagnostics = detailMap.get(file);
|
|
87
|
+
if (!diagnostics) continue;
|
|
88
|
+
|
|
89
|
+
const { suppressions } = splitSuppressionDiagnostics(diagnostics, 1);
|
|
90
|
+
if (suppressions.length === 0) continue;
|
|
91
|
+
|
|
92
|
+
suppressionLines.push(`- ${file}`);
|
|
93
|
+
appendDetailLines(suppressionLines, suppressions);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (suppressionLines.length === 0) return;
|
|
97
|
+
lines.push("", "Stale suppression comments — clean these up:", ...suppressionLines);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function diagnosticsContextFingerprint(content: string | null): string | null {
|
|
101
|
+
return content;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function formatCounts(entry: OutstandingDiagnosticSummaryEntry): string {
|
|
105
|
+
const counts: string[] = [];
|
|
106
|
+
if (entry.errors > 0) counts.push(pluralize(entry.errors, "error"));
|
|
107
|
+
if (entry.warnings > 0) counts.push(pluralize(entry.warnings, "warning"));
|
|
108
|
+
if (entry.information > 0) counts.push(pluralize(entry.information, "info"));
|
|
109
|
+
if (entry.hints > 0) counts.push(pluralize(entry.hints, "hint"));
|
|
110
|
+
return counts.join(", ");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function pluralize(count: number, word: string): string {
|
|
114
|
+
return `${count} ${word}${count === 1 ? "" : "s"}`;
|
|
115
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { Diagnostic } from "../config/types.ts";
|
|
1
2
|
import type { OutstandingDiagnosticSummaryEntry } from "../manager/manager-types.ts";
|
|
2
|
-
import type { Diagnostic } from "../types.ts";
|
|
3
3
|
|
|
4
4
|
export function formatDiagnosticsDisplayContent(
|
|
5
5
|
diagnostics: OutstandingDiagnosticSummaryEntry[],
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { type Diagnostic, DiagnosticSeverity } from "../config/types.ts";
|
|
1
2
|
import type { OutstandingDiagnosticSummaryEntry } from "../manager/manager-types.ts";
|
|
2
3
|
import { isGlobMatch } from "../pattern-matcher.ts";
|
|
3
4
|
import { displayRelativeFilePath, shouldIgnoreLspPath } from "../summary.ts";
|
|
4
|
-
import {
|
|
5
|
+
import { uriToFile } from "../utils.ts";
|
|
5
6
|
|
|
6
7
|
export function collectDiagnosticSummaryCounts(
|
|
7
8
|
fileDiags: Map<string, { errors: number; warnings: number }>,
|
|
@@ -52,7 +53,7 @@ export function accumulateOutstandingDiagnostics(
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export function relativeFilePathFromUri(uri: string, cwd: string): string {
|
|
55
|
-
return displayRelativeFilePath(uri
|
|
56
|
+
return displayRelativeFilePath(uriToFile(uri), cwd);
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
function isDiagnosticWithinThreshold(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Diagnostic formatting and severity utilities.
|
|
2
2
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
-
import type { Diagnostic } from "../types.ts";
|
|
4
|
+
import type { Diagnostic } from "../config/types.ts";
|
|
5
5
|
|
|
6
6
|
/** Map severity number to label. */
|
|
7
7
|
export function severityLabel(severity: number | undefined): string {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { FileChangeType, type FileEvent } from "
|
|
4
|
-
import { fileToUri } from "
|
|
3
|
+
import { FileChangeType, type FileEvent } from "../config/types.ts";
|
|
4
|
+
import { fileToUri } from "../utils.ts";
|
|
5
5
|
|
|
6
6
|
const IGNORED_DIRECTORIES = new Set(["node_modules", ".pnpm", ".git", "dist", "coverage"]);
|
|
7
7
|
const ROOT_LOCKFILES = ["pnpm-lock.yaml", "package-lock.json", "yarn.lock", "bun.lockb"];
|