@mrclrchtr/supi-code-intelligence 6.1.0 → 6.3.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 +3 -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 +23 -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/node_modules/ignore/README.md +52 -0
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/index.js +785 -129
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/legacy.js +660 -98
- package/node_modules/@mrclrchtr/supi-lsp/node_modules/ignore/package.json +10 -4
- package/node_modules/@mrclrchtr/supi-lsp/package.json +4 -5
- package/node_modules/@mrclrchtr/supi-lsp/src/api.ts +16 -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-process-crash-report.ts +106 -0
- 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 +577 -152
- 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 +54 -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 +74 -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 +296 -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/node_modules/web-tree-sitter/README.md +29 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs +99 -19
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.cjs.map +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js +94 -18
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.js.map +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/debug/web-tree-sitter.wasm.map +14 -14
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/package.json +13 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs +97 -19
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.cjs.map +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts +28 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.cts.map +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts +28 -8
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.d.ts.map +1 -1
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js +92 -18
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.js.map +4 -4
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/node_modules/web-tree-sitter/web-tree-sitter.wasm.map +17 -17
- package/node_modules/@mrclrchtr/supi-tree-sitter/package.json +7 -6
- package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/kotlin/tree-sitter-kotlin.wasm.json +2 -2
- package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm +0 -0
- package/node_modules/@mrclrchtr/supi-tree-sitter/resources/grammars/sql/tree-sitter-sql.wasm.json +2 -2
- 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 +26 -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 +7 -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 +76 -0
- package/src/tool/code_health/refresh-status.ts +212 -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ignore",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.8",
|
|
4
4
|
"description": "Ignore is a manager and filter for .gitignore rules, the one used by eslint, gitbook and many others.",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -25,9 +25,15 @@
|
|
|
25
25
|
"test:mjs:16": "ts-node --compilerOptions '{\"moduleResolution\": \"Node16\", \"module\": \"Node16\"}' ./test/import/simple.mjs && babel -o ./test/import/simple-mjs.js ./test/import/simple.mjs && node ./test/import/simple-mjs.js",
|
|
26
26
|
|
|
27
27
|
"===================== cases =======================": "",
|
|
28
|
-
"test:cases": "npm run tap test/*.test.js -- --coverage",
|
|
28
|
+
"test:cases": "npm run tap test/*.test.js -- --coverage --100",
|
|
29
29
|
"tap": "tap --reporter classic",
|
|
30
30
|
|
|
31
|
+
"=================== benchmark =====================": "",
|
|
32
|
+
"benchmark": "node benchmark",
|
|
33
|
+
|
|
34
|
+
"==================== compat =======================": "",
|
|
35
|
+
"compat": "node compat && node compat --win32",
|
|
36
|
+
|
|
31
37
|
"===================== debug =======================": "",
|
|
32
38
|
"test:git": "npm run tap test/git-check-ignore.test.js",
|
|
33
39
|
"test:ignore": "npm run tap test/ignore.test.js",
|
|
@@ -35,13 +41,13 @@
|
|
|
35
41
|
"test:others": "npm run tap test/others.test.js",
|
|
36
42
|
"test:no-coverage": "npm run tap test/*.test.js -- --no-check-coverage",
|
|
37
43
|
|
|
38
|
-
"test": "npm run lint && npm run ts && npm run build && npm run test:cases",
|
|
44
|
+
"test": "npm run lint && npm run ts && npm run build && npm run test:cases && npm run compat",
|
|
39
45
|
"test:win32": "IGNORE_TEST_WIN32=1 npm run test",
|
|
40
46
|
"report": "tap --coverage-report=html"
|
|
41
47
|
},
|
|
42
48
|
"repository": {
|
|
43
49
|
"type": "git",
|
|
44
|
-
"url": "
|
|
50
|
+
"url": "https://github.com/kaelzhang/node-ignore.git"
|
|
45
51
|
},
|
|
46
52
|
"keywords": [
|
|
47
53
|
"ignore",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrclrchtr/supi-lsp",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Language Server Protocol runtime for SuPi code intelligence",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"vscode-jsonrpc": "^9.0.0",
|
|
38
38
|
"vscode-languageserver-protocol": "^3.18.0",
|
|
39
39
|
"vscode-languageserver-types": "^3.18.0",
|
|
40
|
-
"@mrclrchtr/supi-code-runtime": "6.
|
|
41
|
-
"@mrclrchtr/supi-core": "6.
|
|
40
|
+
"@mrclrchtr/supi-code-runtime": "6.3.0",
|
|
41
|
+
"@mrclrchtr/supi-core": "6.3.0"
|
|
42
42
|
},
|
|
43
43
|
"bundledDependencies": [
|
|
44
44
|
"@mrclrchtr/supi-code-runtime",
|
|
@@ -53,7 +53,6 @@
|
|
|
53
53
|
"exports": {
|
|
54
54
|
"./api": "./src/api.ts",
|
|
55
55
|
"./package.json": "./package.json",
|
|
56
|
-
"./provider/lsp-semantic-provider": "./src/provider/lsp-semantic-provider.ts"
|
|
57
|
-
"./debug-telemetry": "./src/debug-telemetry.ts"
|
|
56
|
+
"./provider/lsp-semantic-provider": "./src/provider/lsp-semantic-provider.ts"
|
|
58
57
|
}
|
|
59
58
|
}
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
// Public API surface for the LSP session-scoped service.
|
|
2
2
|
|
|
3
3
|
export { type LoadConfigOptions, loadConfig } from "./config/config.ts";
|
|
4
|
-
export type {
|
|
5
|
-
export {
|
|
6
|
-
getDeprecatedLspKeys,
|
|
7
|
-
getLspDisabledMessage,
|
|
8
|
-
hasDeprecatedLspKeys,
|
|
9
|
-
loadLspSettings,
|
|
10
|
-
} from "./config/lsp-settings.ts";
|
|
4
|
+
export type { LspSettings } from "./config/lsp-settings.ts";
|
|
5
|
+
export { loadLspSettings } from "./config/lsp-settings.ts";
|
|
11
6
|
export {
|
|
12
7
|
clearTsconfigCache,
|
|
13
8
|
type FileScopeDecision,
|
|
@@ -43,6 +38,8 @@ export { isLikelyStaleDiagnostic } from "./diagnostics/stale-diagnostics.ts";
|
|
|
43
38
|
export {
|
|
44
39
|
scanWorkspaceSentinels,
|
|
45
40
|
syncWorkspaceSentinelSnapshot,
|
|
41
|
+
type WorkspaceSentinelScanOptions,
|
|
42
|
+
type WorkspaceSentinelSyncResult,
|
|
46
43
|
} from "./diagnostics/workspace-sentinels.ts";
|
|
47
44
|
export { raceReadinessValue, raceRequestControl } from "./session/readiness.ts";
|
|
48
45
|
export type {
|
|
@@ -59,6 +56,10 @@ export type {
|
|
|
59
56
|
DiagnosticEvidenceSummary,
|
|
60
57
|
OutstandingDiagnosticSummaryEntry,
|
|
61
58
|
ProcessCrashDiagnosticDemand,
|
|
59
|
+
ProcessCrashRecoveryEntry,
|
|
60
|
+
ProcessCrashRecoveryNextAction,
|
|
61
|
+
ProcessCrashRecoveryOutcome,
|
|
62
|
+
ProcessCrashRecoveryReport,
|
|
62
63
|
RecoverDiagnosticsResult,
|
|
63
64
|
RoutedMutationResponse,
|
|
64
65
|
SemanticReadinessResult,
|
|
@@ -71,8 +72,16 @@ export type {
|
|
|
71
72
|
} from "./session/runtime-registry.ts";
|
|
72
73
|
export {
|
|
73
74
|
clearWorkspaceLspRuntime,
|
|
75
|
+
emptyProcessCrashRecoveryReport,
|
|
74
76
|
getWorkspaceLspRuntime,
|
|
77
|
+
MAX_PROCESS_CRASH_RECOVERY_ENTRIES,
|
|
75
78
|
setWorkspaceLspRuntimeState,
|
|
76
79
|
waitForWorkspaceLspRuntime,
|
|
77
80
|
} from "./session/runtime-registry.ts";
|
|
78
81
|
export { scanMissingServers } from "./session/scanner.ts";
|
|
82
|
+
export {
|
|
83
|
+
AUTOMATIC_LSP_EXCLUDED_DIRECTORIES,
|
|
84
|
+
type AutomaticLspPathPolicy,
|
|
85
|
+
createAutomaticLspPathPolicy,
|
|
86
|
+
createDefaultAutomaticLspPathPolicy,
|
|
87
|
+
} from "./workspace-path-policy.ts";
|
|
@@ -66,11 +66,6 @@ export class ClientDynamicRegistrations {
|
|
|
66
66
|
return (this.idsByMethod.get(method)?.size ?? 0) > 0;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
/** Snapshot of the active registration ids for a method. */
|
|
70
|
-
ids(method: string): readonly string[] {
|
|
71
|
-
return [...(this.idsByMethod.get(method) ?? [])];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
69
|
/** Drop all registrations — capability loss on shutdown, crash, or disposal. */
|
|
75
70
|
clear(): void {
|
|
76
71
|
this.idsByMethod.clear();
|
|
@@ -9,9 +9,12 @@
|
|
|
9
9
|
// and timing data. They never carry diagnostic payloads or source text.
|
|
10
10
|
|
|
11
11
|
import * as path from "node:path";
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
import {
|
|
13
|
+
recordDebugEvent,
|
|
14
|
+
truncateDebugIdentity as truncateIdentity,
|
|
15
|
+
} from "@mrclrchtr/supi-core/debug";
|
|
16
|
+
import { uriToFile } from "@mrclrchtr/supi-core/path";
|
|
17
|
+
import { boundCwd } from "../debug-telemetry.ts";
|
|
15
18
|
|
|
16
19
|
/** Maximum tracked synchronizations before the oldest entry is evicted. */
|
|
17
20
|
export const MAX_TRACKED_SYNCHRONIZATIONS = 64;
|
|
@@ -5,12 +5,13 @@ import {
|
|
|
5
5
|
isCodeRequestInterruption,
|
|
6
6
|
throwIfCodeRequestInterrupted,
|
|
7
7
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
8
|
+
import { fileToUri, uriToFile } from "@mrclrchtr/supi-core/path";
|
|
8
9
|
import type { TextDocumentIdentifier } from "../config/types.ts";
|
|
9
10
|
import {
|
|
10
11
|
type DiagnosticEvidenceSummary,
|
|
11
12
|
summarizeDiagnosticEvidence,
|
|
12
13
|
} from "../diagnostics/evidence.ts";
|
|
13
|
-
import { detectLanguageId
|
|
14
|
+
import { detectLanguageId } from "../utils.ts";
|
|
14
15
|
import {
|
|
15
16
|
type DiagnosticCacheEntry,
|
|
16
17
|
type DiagnosticSynchronization,
|
|
@@ -1,6 +1,9 @@
|
|
|
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";
|
|
6
|
+
import { boundCwd } from "../debug-telemetry.ts";
|
|
4
7
|
|
|
5
8
|
type DiagnosticCollection = "cache" | "fallback" | "none" | "pull" | "push";
|
|
6
9
|
type DiagnosticFreshness = "not-observed" | "observed";
|
|
@@ -7,9 +7,10 @@ import {
|
|
|
7
7
|
throwIfCodeRequestInterrupted,
|
|
8
8
|
unavailableCodeQuery,
|
|
9
9
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
10
|
+
import { fileToUri, uriToFile } from "@mrclrchtr/supi-core/path";
|
|
10
11
|
import type { Diagnostic, TextDocumentItem } from "../config/types.ts";
|
|
11
12
|
import type { DiagnosticEvidenceSummary } from "../diagnostics/evidence.ts";
|
|
12
|
-
import { detectLanguageId
|
|
13
|
+
import { detectLanguageId } from "../utils.ts";
|
|
13
14
|
import { applyPushDiagnostics, buildClientDiagnosticSnapshot } from "./client-diagnostic-cache.ts";
|
|
14
15
|
import { collectSynchronizedFileDiagnostics } from "./client-diagnostic-collection.ts";
|
|
15
16
|
import {
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
throwIfCodeRequestInterrupted,
|
|
13
13
|
unavailableCodeQuery,
|
|
14
14
|
} from "@mrclrchtr/supi-code-runtime/api";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
recordDebugEvent,
|
|
17
|
+
truncateDebugIdentity as truncateIdentity,
|
|
18
|
+
} from "@mrclrchtr/supi-core/debug";
|
|
19
|
+
import { fileToUri } from "@mrclrchtr/supi-core/path";
|
|
16
20
|
import { type ProgressToken, TextDocumentSyncKind } from "vscode-languageserver-protocol";
|
|
17
21
|
import { CLIENT_CAPABILITIES } from "../config/capabilities.ts";
|
|
18
22
|
import type {
|
|
@@ -35,10 +39,9 @@ import type {
|
|
|
35
39
|
WorkspaceEdit,
|
|
36
40
|
WorkspaceSymbol,
|
|
37
41
|
} from "../config/types.ts";
|
|
38
|
-
import { boundCwd
|
|
42
|
+
import { boundCwd } from "../debug-telemetry.ts";
|
|
39
43
|
import type { DiagnosticEvidenceSummary } from "../diagnostics/evidence.ts";
|
|
40
44
|
import { raceRequestControl } from "../session/readiness.ts";
|
|
41
|
-
import { fileToUri } from "../utils.ts";
|
|
42
45
|
import {
|
|
43
46
|
ClientDynamicRegistrations,
|
|
44
47
|
DOCUMENT_DIAGNOSTIC_METHOD,
|
|
@@ -141,6 +144,15 @@ function killProcessTree(pid: number): void {
|
|
|
141
144
|
}
|
|
142
145
|
}
|
|
143
146
|
|
|
147
|
+
/** Terminate a failed startup without leaving server descendants running. */
|
|
148
|
+
function killFailedStartupProcess(child: ChildProcess): void {
|
|
149
|
+
if (child.pid) {
|
|
150
|
+
killProcessTree(child.pid);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
child.kill();
|
|
154
|
+
}
|
|
155
|
+
|
|
144
156
|
// ── Types ─────────────────────────────────────────────────────────────
|
|
145
157
|
export type ClientStatus = "initializing" | "running" | "error" | "shutdown";
|
|
146
158
|
|
|
@@ -285,7 +297,7 @@ export class LspClient {
|
|
|
285
297
|
if (!this.process.stdin || !this.process.stdout) {
|
|
286
298
|
const failure = new Error(`${cmd}: missing stdin/stdout`);
|
|
287
299
|
this.handleProcessFailure(failure);
|
|
288
|
-
this.process
|
|
300
|
+
killFailedStartupProcess(this.process);
|
|
289
301
|
throw failure;
|
|
290
302
|
}
|
|
291
303
|
|
|
@@ -350,7 +362,7 @@ export class LspClient {
|
|
|
350
362
|
} catch (err) {
|
|
351
363
|
const failure = new Error(`${this.name}: initialize failed: ${err}`, { cause: err });
|
|
352
364
|
this.handleProcessFailure(failure);
|
|
353
|
-
this.process
|
|
365
|
+
killFailedStartupProcess(this.process);
|
|
354
366
|
throw failure;
|
|
355
367
|
}
|
|
356
368
|
}
|
|
@@ -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
|
}
|