@mrclrchtr/supi-code-intelligence 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 +2 -2
- 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/node_modules/@mrclrchtr/supi-lsp/README.md +26 -4
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +5 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/@mrclrchtr/supi-core/src/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/node_modules/vscode-jsonrpc/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/lib/common/protocol.colorProvider.d.ts +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/lib/common/protocol.d.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/lib/common/protocol.fileOperations.d.ts +9 -9
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-protocol/package.json +3 -3
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/esm/main.d.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/esm/main.js +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/umd/main.d.ts +2 -2
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/lib/umd/main.js +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/vscode-languageserver-types/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +14 -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 +23 -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 +8 -1
- package/node_modules/@mrclrchtr/supi-lsp/src/config/tsconfig-scope.ts +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/config/types.ts +1 -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 +12 -6
- 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 +849 -117
- package/node_modules/@mrclrchtr/supi-lsp/src/provider/lsp-semantic-provider.ts +6 -4
- 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-diagnostic-surface.ts +10 -0
- 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 +118 -27
- package/node_modules/@mrclrchtr/supi-lsp/src/session/runtime-transition-debug.ts +7 -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 +33 -5
- 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-code-runtime/src/capability/types.ts +5 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/package.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/@mrclrchtr/supi-core/src/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/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +1 -1
- 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/health/recovery.ts +4 -0
- package/src/analysis/health/server-status.ts +64 -0
- package/src/analysis/health/signals.ts +1 -0
- package/src/analysis/provider.ts +2 -1
- package/src/analysis/search/ast-scan-timing.ts +4 -2
- package/src/analysis/search/ast-scan.ts +1 -1
- package/src/analysis/target/symbol.ts +28 -16
- package/src/analysis/target/types.ts +1 -0
- package/src/api.ts +1 -0
- package/src/extension.ts +4 -2
- package/src/session/find-workflow.ts +5 -12
- package/src/session/health-refresh.ts +30 -4
- package/src/session/health-types.ts +27 -2
- package/src/session/health-workflow.ts +5 -1
- 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/session/semantic-demand.ts +36 -0
- package/src/session/target-workflow.ts +9 -12
- 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/guidance.ts +2 -2
- package/src/tool/code_health/markdown.ts +81 -69
- 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 +15 -5
- package/src/tool/code_health/spec.ts +2 -1
- package/src/tool/code_health/tui.ts +42 -8
- 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/result/errors.ts +1 -0
- package/src/tool/result/types.ts +6 -0
- package/src/tool/schemas.ts +21 -11
- package/src/ui/footer.ts +7 -5
- package/src/ui/status-command.ts +31 -0
- package/src/ui/status-overlay.ts +69 -23
- 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
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
type CodeRequestControl,
|
|
8
8
|
CodeRequestDeadlineError,
|
|
9
9
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
startDebugTimer,
|
|
12
|
+
truncateDebugIdentity as truncateIdentity,
|
|
13
|
+
} from "@mrclrchtr/supi-core/debug";
|
|
11
14
|
import {
|
|
12
15
|
CancellationTokenSource,
|
|
13
16
|
createMessageConnection,
|
|
@@ -18,7 +21,7 @@ import {
|
|
|
18
21
|
StreamMessageReader,
|
|
19
22
|
StreamMessageWriter,
|
|
20
23
|
} from "vscode-jsonrpc/node";
|
|
21
|
-
import { boundCwd, LSP_REQUEST_TIMEOUT_ERROR_CODE
|
|
24
|
+
import { boundCwd, LSP_REQUEST_TIMEOUT_ERROR_CODE } from "../debug-telemetry.ts";
|
|
22
25
|
|
|
23
26
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
24
27
|
|
|
@@ -112,34 +115,40 @@ export class JsonRpcClient {
|
|
|
112
115
|
const methodClass = classifyRequestMethod(method);
|
|
113
116
|
const boundedMethod = truncateIdentity(method);
|
|
114
117
|
const timer = startDebugTimer();
|
|
118
|
+
// A request cancelled before dispatch must not produce protocol traffic.
|
|
119
|
+
if (signal?.aborted) {
|
|
120
|
+
return rejectUndispatchedRequest(
|
|
121
|
+
signal.reason ?? new Error(`Request ${method} was cancelled`),
|
|
122
|
+
{
|
|
123
|
+
timer,
|
|
124
|
+
operationId: options?.operationId,
|
|
125
|
+
observation: { method: boundedMethod, methodClass, outcome: "cancelled" },
|
|
126
|
+
identity: { server: this.server, cwd: this.cwd },
|
|
127
|
+
},
|
|
128
|
+
);
|
|
129
|
+
}
|
|
115
130
|
// An expired absolute deadline must not even send the request: the caller
|
|
116
131
|
// no longer awaits a result, so no protocol traffic may start.
|
|
117
132
|
if (deadlineMs !== undefined && deadlineMs <= 0) {
|
|
118
|
-
|
|
133
|
+
return rejectUndispatchedRequest(new CodeRequestDeadlineError(), {
|
|
119
134
|
timer,
|
|
120
|
-
options?.operationId,
|
|
121
|
-
{
|
|
135
|
+
operationId: options?.operationId,
|
|
136
|
+
observation: {
|
|
122
137
|
method: boundedMethod,
|
|
123
138
|
methodClass,
|
|
124
139
|
outcome: "timed-out",
|
|
125
140
|
errorCode: LSP_REQUEST_TIMEOUT_ERROR_CODE,
|
|
126
141
|
},
|
|
127
|
-
{ server: this.server, cwd: this.cwd },
|
|
128
|
-
);
|
|
129
|
-
return Promise.reject(new CodeRequestDeadlineError());
|
|
142
|
+
identity: { server: this.server, cwd: this.cwd },
|
|
143
|
+
});
|
|
130
144
|
}
|
|
131
145
|
if (this.closed || !this.connection) {
|
|
132
|
-
|
|
146
|
+
return rejectUndispatchedRequest(new Error("JSON-RPC client is closed"), {
|
|
133
147
|
timer,
|
|
134
|
-
options?.operationId,
|
|
135
|
-
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
outcome: "cancelled",
|
|
139
|
-
},
|
|
140
|
-
{ server: this.server, cwd: this.cwd },
|
|
141
|
-
);
|
|
142
|
-
return Promise.reject(new Error("JSON-RPC client is closed"));
|
|
148
|
+
operationId: options?.operationId,
|
|
149
|
+
observation: { method: boundedMethod, methodClass, outcome: "cancelled" },
|
|
150
|
+
identity: { server: this.server, cwd: this.cwd },
|
|
151
|
+
});
|
|
143
152
|
}
|
|
144
153
|
const tokenSource = new CancellationTokenSource();
|
|
145
154
|
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
@@ -344,6 +353,19 @@ function jsonRpcErrorCode(error: unknown): number | undefined {
|
|
|
344
353
|
return typeof code === "number" && Number.isInteger(code) ? code : undefined;
|
|
345
354
|
}
|
|
346
355
|
|
|
356
|
+
function rejectUndispatchedRequest(
|
|
357
|
+
error: unknown,
|
|
358
|
+
timing: {
|
|
359
|
+
timer: ReturnType<typeof startDebugTimer>;
|
|
360
|
+
operationId: string | undefined;
|
|
361
|
+
observation: RequestTimingObservation;
|
|
362
|
+
identity: { server?: string; cwd?: string };
|
|
363
|
+
},
|
|
364
|
+
): Promise<never> {
|
|
365
|
+
recordRequestTiming(timing.timer, timing.operationId, timing.observation, timing.identity);
|
|
366
|
+
return Promise.reject(error);
|
|
367
|
+
}
|
|
368
|
+
|
|
347
369
|
function recordRequestTiming(
|
|
348
370
|
timer: ReturnType<typeof startDebugTimer>,
|
|
349
371
|
operationId: string | undefined,
|
|
@@ -4,6 +4,7 @@ import * as fs from "node:fs";
|
|
|
4
4
|
import * as path from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { loadSupiConfigForScope } from "@mrclrchtr/supi-core/config";
|
|
7
|
+
import { truncateDebugIdentity } from "@mrclrchtr/supi-core/debug";
|
|
7
8
|
import type { LspConfig, ServerConfig } from "./types.ts";
|
|
8
9
|
|
|
9
10
|
const CONFIG_DIR = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -24,17 +25,16 @@ export const LANGUAGE_ALIASES: Record<string, string> = {
|
|
|
24
25
|
cpp: "c",
|
|
25
26
|
};
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
export function resolveLanguageAlias(name: string): string {
|
|
29
|
-
return LANGUAGE_ALIASES[name] ?? name;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function resolveAliasesInOverrides(servers: Record<string, Partial<ServerConfig>>): void {
|
|
28
|
+
function resolveAliasesInOverrides(servers: Record<string, unknown>): void {
|
|
33
29
|
for (const [alias, target] of Object.entries(LANGUAGE_ALIASES)) {
|
|
34
|
-
if (servers
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
if (!Object.hasOwn(servers, alias)) continue;
|
|
31
|
+
const aliasOverride = servers[alias];
|
|
32
|
+
const targetOverride = servers[target];
|
|
33
|
+
servers[target] =
|
|
34
|
+
isRecord(aliasOverride) && isRecord(targetOverride)
|
|
35
|
+
? { ...targetOverride, ...aliasOverride }
|
|
36
|
+
: aliasOverride;
|
|
37
|
+
delete servers[alias];
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -49,13 +49,13 @@ export function loadConfig(cwd: string, options?: LoadConfigOptions): LspConfig
|
|
|
49
49
|
const globalLsp = loadSupiConfigForScope(
|
|
50
50
|
"lsp",
|
|
51
51
|
cwd,
|
|
52
|
-
{
|
|
52
|
+
{ servers: {} as Record<string, ServerConfig> },
|
|
53
53
|
{ scope: "global", homeDir: options?.homeDir },
|
|
54
54
|
);
|
|
55
55
|
const projectLsp = loadSupiConfigForScope(
|
|
56
56
|
"lsp",
|
|
57
57
|
cwd,
|
|
58
|
-
{
|
|
58
|
+
{ servers: {} as Record<string, ServerConfig> },
|
|
59
59
|
{ scope: "project" },
|
|
60
60
|
);
|
|
61
61
|
|
|
@@ -91,6 +91,13 @@ function mergeServerConfigs(
|
|
|
91
91
|
projectOverrides: unknown,
|
|
92
92
|
): Record<string, ServerConfig> {
|
|
93
93
|
const merged: Record<string, ServerConfig> = { ...defaults };
|
|
94
|
+
const warnings = new Map<string, { fields: Set<string>; skipped: boolean }>();
|
|
95
|
+
const reportWarning: ServerConfigWarningReporter = (name, fields, skipped) => {
|
|
96
|
+
const warning = warnings.get(name) ?? { fields: new Set<string>(), skipped: false };
|
|
97
|
+
for (const field of fields) warning.fields.add(field);
|
|
98
|
+
warning.skipped ||= skipped;
|
|
99
|
+
warnings.set(name, warning);
|
|
100
|
+
};
|
|
94
101
|
|
|
95
102
|
const globalServers = isServerRecord(globalOverrides) ? globalOverrides : {};
|
|
96
103
|
const projectServers = isServerRecord(projectOverrides) ? projectOverrides : {};
|
|
@@ -100,14 +107,29 @@ function mergeServerConfigs(
|
|
|
100
107
|
|
|
101
108
|
// Apply global per-key overrides against defaults
|
|
102
109
|
for (const [lang, override] of Object.entries(globalServers)) {
|
|
103
|
-
const
|
|
110
|
+
const builtIn = defaults[lang] !== undefined;
|
|
111
|
+
const result = mergeSingleServer({
|
|
112
|
+
name: lang,
|
|
113
|
+
base: defaults[lang],
|
|
114
|
+
value: override,
|
|
115
|
+
builtIn,
|
|
116
|
+
reportWarning,
|
|
117
|
+
});
|
|
104
118
|
if (result) merged[lang] = result;
|
|
105
119
|
}
|
|
106
120
|
|
|
107
121
|
// Apply project per-key overrides against the result so far
|
|
108
122
|
for (const [lang, override] of Object.entries(projectServers)) {
|
|
109
|
-
const
|
|
123
|
+
const builtIn = defaults[lang] !== undefined;
|
|
124
|
+
const result = mergeSingleServer({
|
|
125
|
+
name: lang,
|
|
126
|
+
base: merged[lang] ?? defaults[lang],
|
|
127
|
+
value: override,
|
|
128
|
+
builtIn,
|
|
129
|
+
reportWarning,
|
|
130
|
+
});
|
|
110
131
|
if (result) merged[lang] = result;
|
|
132
|
+
else if (!builtIn) delete merged[lang];
|
|
111
133
|
}
|
|
112
134
|
|
|
113
135
|
// Remove servers whose final merged config has enabled === false
|
|
@@ -117,29 +139,141 @@ function mergeServerConfigs(
|
|
|
117
139
|
}
|
|
118
140
|
}
|
|
119
141
|
|
|
142
|
+
for (const [name, warning] of warnings) {
|
|
143
|
+
warnInvalidServerConfig(name, [...warning.fields], warning.skipped);
|
|
144
|
+
}
|
|
120
145
|
return merged;
|
|
121
146
|
}
|
|
122
147
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
148
|
+
type ServerConfigWarningReporter = (
|
|
149
|
+
name: string,
|
|
150
|
+
fields: readonly string[],
|
|
151
|
+
skipped: boolean,
|
|
152
|
+
) => void;
|
|
153
|
+
|
|
154
|
+
function mergeSingleServer(options: {
|
|
155
|
+
name: string;
|
|
156
|
+
base: ServerConfig | undefined;
|
|
157
|
+
value: unknown;
|
|
158
|
+
builtIn: boolean;
|
|
159
|
+
reportWarning: ServerConfigWarningReporter;
|
|
160
|
+
}): ServerConfig | null {
|
|
161
|
+
const { name, base, value, builtIn, reportWarning } = options;
|
|
162
|
+
const { override, invalidFields } = validateServerOverride(value);
|
|
163
|
+
const missingFields = base
|
|
164
|
+
? []
|
|
165
|
+
: [
|
|
166
|
+
...(typeof override.command === "string" ? [] : ["command"]),
|
|
167
|
+
...(override.fileTypes && override.fileTypes.length > 0 ? [] : ["fileTypes"]),
|
|
168
|
+
];
|
|
169
|
+
const issues = [...new Set([...invalidFields, ...missingFields])];
|
|
170
|
+
if ((!builtIn && invalidFields.length > 0) || (!base && issues.length > 0)) {
|
|
171
|
+
reportWarning(name, issues, true);
|
|
138
172
|
return null;
|
|
139
173
|
}
|
|
174
|
+
if (!base) {
|
|
175
|
+
return {
|
|
176
|
+
...override,
|
|
177
|
+
command: override.command as string,
|
|
178
|
+
fileTypes: override.fileTypes as string[],
|
|
179
|
+
rootMarkers: override.rootMarkers ?? [],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (invalidFields.length > 0) reportWarning(name, invalidFields, false);
|
|
140
184
|
return { ...base, ...override };
|
|
141
185
|
}
|
|
142
186
|
|
|
143
|
-
|
|
187
|
+
type ServerOverrideSetter = (override: Partial<ServerConfig>, candidate: unknown) => boolean;
|
|
188
|
+
|
|
189
|
+
const SERVER_OVERRIDE_SETTERS: Record<string, ServerOverrideSetter> = {
|
|
190
|
+
command(override, candidate) {
|
|
191
|
+
if (typeof candidate !== "string" || candidate.trim().length === 0) return false;
|
|
192
|
+
override.command = candidate;
|
|
193
|
+
return true;
|
|
194
|
+
},
|
|
195
|
+
args(override, candidate) {
|
|
196
|
+
if (!isStringArray(candidate)) return false;
|
|
197
|
+
override.args = candidate;
|
|
198
|
+
return true;
|
|
199
|
+
},
|
|
200
|
+
fileTypes(override, candidate) {
|
|
201
|
+
if (!isNonEmptyStringArray(candidate)) return false;
|
|
202
|
+
override.fileTypes = candidate;
|
|
203
|
+
return true;
|
|
204
|
+
},
|
|
205
|
+
rootMarkers(override, candidate) {
|
|
206
|
+
if (!isStringArray(candidate)) return false;
|
|
207
|
+
override.rootMarkers = candidate;
|
|
208
|
+
return true;
|
|
209
|
+
},
|
|
210
|
+
enabled(override, candidate) {
|
|
211
|
+
if (typeof candidate !== "boolean") return false;
|
|
212
|
+
override.enabled = candidate;
|
|
213
|
+
return true;
|
|
214
|
+
},
|
|
215
|
+
env(override, candidate) {
|
|
216
|
+
if (!isStringRecord(candidate)) return false;
|
|
217
|
+
override.env = candidate;
|
|
218
|
+
return true;
|
|
219
|
+
},
|
|
220
|
+
initializationOptions(override, candidate) {
|
|
221
|
+
override.initializationOptions = candidate;
|
|
222
|
+
return true;
|
|
223
|
+
},
|
|
224
|
+
readinessTimeoutMs(override, candidate) {
|
|
225
|
+
if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate <= 0) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
override.readinessTimeoutMs = candidate;
|
|
229
|
+
return true;
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
function validateServerOverride(value: unknown): {
|
|
234
|
+
override: Partial<ServerConfig>;
|
|
235
|
+
invalidFields: string[];
|
|
236
|
+
} {
|
|
237
|
+
if (!isRecord(value)) return { override: {}, invalidFields: ["definition"] };
|
|
238
|
+
const override: Partial<ServerConfig> = {};
|
|
239
|
+
const invalidFields: string[] = [];
|
|
240
|
+
|
|
241
|
+
for (const [field, candidate] of Object.entries(value)) {
|
|
242
|
+
const setter = SERVER_OVERRIDE_SETTERS[field];
|
|
243
|
+
if (!setter?.(override, candidate)) invalidFields.push(field);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return { override, invalidFields };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function isStringArray(value: unknown): value is string[] {
|
|
250
|
+
return Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function isNonEmptyStringArray(value: unknown): value is string[] {
|
|
254
|
+
return (
|
|
255
|
+
Array.isArray(value) &&
|
|
256
|
+
value.length > 0 &&
|
|
257
|
+
value.every((entry) => typeof entry === "string" && entry.length > 0)
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function isStringRecord(value: unknown): value is Record<string, string> {
|
|
262
|
+
return isRecord(value) && Object.values(value).every((entry) => typeof entry === "string");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function warnInvalidServerConfig(name: string, fields: readonly string[], skipped: boolean): void {
|
|
266
|
+
const boundedName = truncateDebugIdentity(name);
|
|
267
|
+
const boundedFields = truncateDebugIdentity(fields.join(", "));
|
|
268
|
+
const action = skipped ? "Skipped invalid" : "Ignored invalid fields in";
|
|
269
|
+
// biome-ignore lint/suspicious/noConsole: malformed user configuration must be visible.
|
|
270
|
+
console.warn(`[supi-lsp] ${action} LSP server configuration "${boundedName}": ${boundedFields}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function isServerRecord(value: unknown): value is Record<string, unknown> {
|
|
274
|
+
return isRecord(value);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
144
278
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
145
279
|
}
|
|
@@ -1,100 +1,22 @@
|
|
|
1
|
-
// LSP settings
|
|
2
|
-
//
|
|
3
|
-
// These are the non-UI config helpers extracted from settings-registration.ts
|
|
4
|
-
// so they can be consumed by the library-only runtime controller without
|
|
5
|
-
// importing pi-specific UI modules.
|
|
1
|
+
// LSP settings used by workspace lifecycle and automatic path policy.
|
|
6
2
|
|
|
7
|
-
import { loadSupiConfig
|
|
3
|
+
import { loadSupiConfig } from "@mrclrchtr/supi-core/config";
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export interface LspSettings extends Record<string, unknown> {
|
|
12
|
-
enabled: boolean;
|
|
13
|
-
active: string[];
|
|
5
|
+
/** Effective non-server LSP settings. */
|
|
6
|
+
export interface LspSettings {
|
|
14
7
|
exclude: string[];
|
|
15
8
|
}
|
|
16
9
|
|
|
17
10
|
export const LSP_DEFAULTS: LspSettings = {
|
|
18
|
-
enabled: true,
|
|
19
|
-
active: [],
|
|
20
11
|
exclude: [],
|
|
21
12
|
};
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Load LSP settings from supi config for the given cwd.
|
|
27
|
-
*
|
|
28
|
-
* Merges project and global scopes with defaults, returning the
|
|
29
|
-
* effective LspSettings for session startup.
|
|
30
|
-
*/
|
|
14
|
+
/** Load effective LSP settings for one workspace. */
|
|
31
15
|
export function loadLspSettings(cwd: string, homeDir?: string): LspSettings {
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Return a user-facing message explaining why LSP may appear disabled.
|
|
37
|
-
*
|
|
38
|
-
* **Since the always-on policy:** `lsp.enabled: false` is deprecated and
|
|
39
|
-
* ignored. This function is kept for backward compatibility with the
|
|
40
|
-
* settings UI and reports that LSP is always attempted.
|
|
41
|
-
*/
|
|
42
|
-
export function getLspDisabledMessage(cwd: string, homeDir?: string): string {
|
|
43
|
-
const global = loadSupiConfigForScope("lsp", cwd, LSP_DEFAULTS, { scope: "global", homeDir });
|
|
44
|
-
const project = loadSupiConfigForScope("lsp", cwd, LSP_DEFAULTS, { scope: "project", homeDir });
|
|
45
|
-
|
|
46
|
-
if (project.enabled === false) {
|
|
47
|
-
return "LSP is always attempted; `lsp.enabled: false` in project settings (.pi/supi/config.json) is deprecated and ignored";
|
|
48
|
-
}
|
|
49
|
-
if (global.enabled === false) {
|
|
50
|
-
return "LSP is always attempted; `lsp.enabled: false` in global settings (~/.pi/agent/supi/config.json) is deprecated and ignored";
|
|
51
|
-
}
|
|
52
|
-
return "LSP is always attempted";
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ── Deprecated-key detection (always-on policy) ────────────────
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Result of checking for deprecated LSP configuration keys.
|
|
59
|
-
*/
|
|
60
|
-
export interface DeprecatedLspKeys {
|
|
61
|
-
/** `lsp.enabled` presence in project config. */
|
|
62
|
-
projectEnabled: boolean;
|
|
63
|
-
/** `lsp.enabled` presence in global config. */
|
|
64
|
-
globalEnabled: boolean;
|
|
65
|
-
/** `lsp.active` presence in project config. */
|
|
66
|
-
projectActive: boolean;
|
|
67
|
-
/** `lsp.active` presence in global config. */
|
|
68
|
-
globalActive: boolean;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Check whether deprecated `lsp.enabled` or `lsp.active` keys exist
|
|
73
|
-
* in project or global config. These keys are ignored by the always-on
|
|
74
|
-
* LSP policy but may be present in user config.
|
|
75
|
-
*/
|
|
76
|
-
export function getDeprecatedLspKeys(cwd: string, homeDir?: string): DeprecatedLspKeys {
|
|
77
|
-
const global = loadSupiConfigForScope("lsp", cwd, LSP_DEFAULTS, { scope: "global", homeDir });
|
|
78
|
-
const project = loadSupiConfigForScope("lsp", cwd, LSP_DEFAULTS, { scope: "project", homeDir });
|
|
79
|
-
|
|
16
|
+
const loaded = loadSupiConfig("lsp", cwd, LSP_DEFAULTS, { homeDir });
|
|
80
17
|
return {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
globalActive: hasExplicitActiveKey(global),
|
|
18
|
+
exclude: Array.isArray(loaded.exclude)
|
|
19
|
+
? loaded.exclude.filter((entry): entry is string => typeof entry === "string")
|
|
20
|
+
: [],
|
|
85
21
|
};
|
|
86
22
|
}
|
|
87
|
-
|
|
88
|
-
/** Whether the loaded settings had an explicit `enabled` key (different from default). */
|
|
89
|
-
function hasExplicitEnabledKey(settings: Partial<{ enabled: boolean }>): boolean {
|
|
90
|
-
return settings.enabled === false;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/** Whether the loaded settings had an explicit `active` key. */
|
|
94
|
-
function hasExplicitActiveKey(settings: Partial<{ active: string[] }>): boolean {
|
|
95
|
-
return Array.isArray(settings.active) && settings.active.length > 0;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Alias for backwards compatibility with the RED test name
|
|
99
|
-
/** @deprecated Use {@link getDeprecatedLspKeys} instead. */
|
|
100
|
-
export const hasDeprecatedLspKeys: typeof getDeprecatedLspKeys = getDeprecatedLspKeys;
|
|
@@ -26,9 +26,16 @@ export interface DetectedProjectServer {
|
|
|
26
26
|
fileTypes: string[];
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
/** Structured reason for a route-level process-crash recovery state. */
|
|
30
|
+
export type ProjectServerStatusReason =
|
|
31
|
+
| "process-crashed"
|
|
32
|
+
| "process-crash-recovery-pending"
|
|
33
|
+
| "process-crash-recovery-exhausted";
|
|
34
|
+
|
|
29
35
|
export interface ProjectServerInfo extends DetectedProjectServer {
|
|
30
36
|
status: "running" | "error" | "unavailable";
|
|
31
|
-
|
|
37
|
+
/** Structured lifecycle reason when process-crash recovery is active. */
|
|
38
|
+
statusReason?: ProjectServerStatusReason;
|
|
32
39
|
openFiles: string[];
|
|
33
40
|
/** Whether the LSP server is currently not indexing and ready to serve queries. */
|
|
34
41
|
ready: boolean;
|
|
@@ -379,15 +379,14 @@ export function invalidateTsconfigCacheForConfig(configPath: string): void {
|
|
|
379
379
|
}
|
|
380
380
|
|
|
381
381
|
/**
|
|
382
|
-
* Invalidate nearest-config lookups that
|
|
382
|
+
* Invalidate nearest-config lookups under a directory that gained a config.
|
|
383
383
|
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
384
|
+
* A new config can replace either a no-config result or a cached lower-priority
|
|
385
|
+
* config, such as `jsconfig.json` when `tsconfig.json` is created.
|
|
386
386
|
*/
|
|
387
387
|
export function invalidateTsconfigCacheForConfigDir(dir: string): void {
|
|
388
388
|
const normalizedDir = normalizePath(dir);
|
|
389
|
-
for (const
|
|
390
|
-
if (value !== null) continue;
|
|
389
|
+
for (const key of nearestConfigCache.keys()) {
|
|
391
390
|
const keyDir = key.split("::", 1)[0];
|
|
392
391
|
if (keyDir === normalizedDir || keyDir.startsWith(`${normalizedDir}/`)) {
|
|
393
392
|
nearestConfigCache.delete(key);
|
|
@@ -49,40 +49,12 @@ export {
|
|
|
49
49
|
WorkspaceSymbol,
|
|
50
50
|
} from "vscode-languageserver-types";
|
|
51
51
|
|
|
52
|
-
// Alias for backward compatibility — our code uses ClientDiagnosticCapabilities
|
|
53
|
-
import type { DiagnosticClientCapabilities } from "vscode-languageserver-protocol";
|
|
54
|
-
export type ClientDiagnosticCapabilities = DiagnosticClientCapabilities;
|
|
55
|
-
|
|
56
|
-
// ── JSON-RPC types (local — replaced by vscode-jsonrpc in transport task) ──
|
|
57
|
-
export type JsonRpcId = number | string;
|
|
58
|
-
|
|
59
|
-
export interface JsonRpcRequest {
|
|
60
|
-
jsonrpc: "2.0";
|
|
61
|
-
id: JsonRpcId;
|
|
62
|
-
method: string;
|
|
63
|
-
params?: unknown;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export interface JsonRpcResponse {
|
|
67
|
-
jsonrpc: "2.0";
|
|
68
|
-
id: JsonRpcId | null;
|
|
69
|
-
result?: unknown;
|
|
70
|
-
error?: { code: number; message: string; data?: unknown };
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export interface JsonRpcNotification {
|
|
74
|
-
jsonrpc: "2.0";
|
|
75
|
-
method: string;
|
|
76
|
-
params?: unknown;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export type JsonRpcMessage = JsonRpcRequest | JsonRpcResponse | JsonRpcNotification;
|
|
80
|
-
|
|
81
52
|
// ── SuPi-specific server config ──────────────────────────────────────
|
|
82
53
|
export type {
|
|
83
54
|
DetectedProjectServer,
|
|
84
55
|
LspConfig,
|
|
85
56
|
MissingServer,
|
|
86
57
|
ProjectServerInfo,
|
|
58
|
+
ProjectServerStatusReason,
|
|
87
59
|
ServerConfig,
|
|
88
60
|
} from "./server-config.ts";
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
// Bounded identity vocabulary for LSP debug telemetry.
|
|
2
2
|
//
|
|
3
|
-
// LSP debug events
|
|
4
|
-
// identity for local protocol diagnosis.
|
|
5
|
-
//
|
|
6
|
-
|
|
3
|
+
// LSP debug events can include server, workspace, file, method, and root
|
|
4
|
+
// identity for local protocol diagnosis. Each identity string and list uses
|
|
5
|
+
// the shared bounds.
|
|
6
|
+
|
|
7
|
+
import { truncateDebugIdentity } from "@mrclrchtr/supi-core/debug";
|
|
7
8
|
|
|
8
9
|
/** Maximum number of server entries in one bounded LSP debug payload. */
|
|
9
10
|
export const MAX_SERVERS = 16;
|
|
10
11
|
|
|
11
|
-
/** Maximum UTF-16 code-unit length of one emitted identity string in an LSP debug payload. */
|
|
12
|
-
export const MAX_IDENTITY_STRING = 512;
|
|
13
|
-
|
|
14
|
-
/** Marker appended to an identity string truncated to MAX_IDENTITY_STRING. */
|
|
15
|
-
export const IDENTITY_TRUNCATION_MARKER = "…";
|
|
16
|
-
|
|
17
12
|
/**
|
|
18
13
|
* JSON-RPC error code recorded for client-local request timeouts.
|
|
19
14
|
*
|
|
@@ -24,22 +19,13 @@ export const IDENTITY_TRUNCATION_MARKER = "…";
|
|
|
24
19
|
*/
|
|
25
20
|
export const LSP_REQUEST_TIMEOUT_ERROR_CODE = -32_095;
|
|
26
21
|
|
|
27
|
-
/**
|
|
28
|
-
* Truncate one identity string so the emitted value (marker included) never
|
|
29
|
-
* exceeds MAX_IDENTITY_STRING UTF-16 code units.
|
|
30
|
-
*/
|
|
31
|
-
export function truncateIdentity(value: string): string {
|
|
32
|
-
if (value.length <= MAX_IDENTITY_STRING) return value;
|
|
33
|
-
return `${value.slice(0, MAX_IDENTITY_STRING - 1)}${IDENTITY_TRUNCATION_MARKER}`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
22
|
/** Bound an optional workspace root for event-level identity; undefined stays absent. */
|
|
37
23
|
export function boundCwd(cwd: string | undefined): string | undefined {
|
|
38
24
|
if (cwd === undefined) return undefined;
|
|
39
|
-
return
|
|
25
|
+
return truncateDebugIdentity(cwd);
|
|
40
26
|
}
|
|
41
27
|
|
|
42
28
|
/** Bound a server-name list to MAX_SERVERS entries, truncating each name. */
|
|
43
29
|
export function boundServerNames(names: readonly string[]): string[] {
|
|
44
|
-
return names.slice(0, MAX_SERVERS).map(
|
|
30
|
+
return names.slice(0, MAX_SERVERS).map(truncateDebugIdentity);
|
|
45
31
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Diagnostic, DiagnosticSeverity } from "../config/types.ts";
|
|
2
|
+
|
|
3
|
+
/** Return Error when a diagnostic omits the optional LSP severity. */
|
|
4
|
+
export function effectiveDiagnosticSeverity(diagnostic: Diagnostic): DiagnosticSeverity {
|
|
5
|
+
return diagnostic.severity ?? DiagnosticSeverity.Error;
|
|
6
|
+
}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
+
import { uriToFile } from "@mrclrchtr/supi-core/path";
|
|
1
2
|
import { type Diagnostic, DiagnosticSeverity } from "../config/types.ts";
|
|
2
3
|
import type { OutstandingDiagnosticSummaryEntry } from "../manager/manager-types.ts";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { uriToFile } from "../utils.ts";
|
|
4
|
+
import { displayRelativeFilePath } from "../summary.ts";
|
|
5
|
+
import { effectiveDiagnosticSeverity } from "./diagnostic-severity.ts";
|
|
6
6
|
|
|
7
7
|
export function collectDiagnosticSummaryCounts(
|
|
8
8
|
fileDiags: Map<string, { errors: number; warnings: number }>,
|
|
9
9
|
entry: { uri: string; diagnostics: Diagnostic[] },
|
|
10
10
|
cwd: string,
|
|
11
|
-
|
|
11
|
+
includeFile: (file: string) => boolean,
|
|
12
12
|
): void {
|
|
13
13
|
const file = relativeFilePathFromUri(entry.uri, cwd);
|
|
14
|
-
if (
|
|
15
|
-
if (excludePatterns?.some((p) => isGlobMatch(file, p))) return;
|
|
14
|
+
if (!includeFile(file)) return;
|
|
16
15
|
|
|
17
16
|
const current = fileDiags.get(file) ?? { errors: 0, warnings: 0 };
|
|
18
17
|
for (const diagnostic of entry.diagnostics) {
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const severity = effectiveDiagnosticSeverity(diagnostic);
|
|
19
|
+
if (severity === DiagnosticSeverity.Error) current.errors++;
|
|
20
|
+
else if (severity === DiagnosticSeverity.Warning) current.warnings++;
|
|
21
21
|
}
|
|
22
22
|
fileDiags.set(file, current);
|
|
23
23
|
}
|
|
@@ -46,7 +46,7 @@ export function accumulateOutstandingDiagnostics(
|
|
|
46
46
|
if (!isDiagnosticWithinThreshold(diagnostic, maxSeverity)) continue;
|
|
47
47
|
|
|
48
48
|
next.total++;
|
|
49
|
-
incrementOutstandingDiagnosticCount(next, diagnostic
|
|
49
|
+
incrementOutstandingDiagnosticCount(next, effectiveDiagnosticSeverity(diagnostic));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
return next;
|
|
@@ -56,11 +56,8 @@ export function relativeFilePathFromUri(uri: string, cwd: string): string {
|
|
|
56
56
|
return displayRelativeFilePath(uriToFile(uri), cwd);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
function isDiagnosticWithinThreshold(
|
|
60
|
-
diagnostic
|
|
61
|
-
maxSeverity: number,
|
|
62
|
-
): diagnostic is Diagnostic & { severity: number } {
|
|
63
|
-
return diagnostic.severity !== undefined && diagnostic.severity <= maxSeverity;
|
|
59
|
+
function isDiagnosticWithinThreshold(diagnostic: Diagnostic, maxSeverity: number): boolean {
|
|
60
|
+
return effectiveDiagnosticSeverity(diagnostic) <= maxSeverity;
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
function incrementOutstandingDiagnosticCount(
|
|
@@ -35,8 +35,3 @@ export function summarizeDiagnosticEvidence(
|
|
|
35
35
|
for (const document of documents) counts[document.status]++;
|
|
36
36
|
return { ...counts, documents: [...documents] };
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
/** Return an empty evidence summary for a refresh with no tracked documents. */
|
|
40
|
-
export function emptyDiagnosticEvidence(): DiagnosticEvidenceSummary {
|
|
41
|
-
return summarizeDiagnosticEvidence([]);
|
|
42
|
-
}
|