@mrclrchtr/supi-lsp 11.1.0 → 11.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.
Files changed (80) hide show
  1. package/README.md +81 -7
  2. package/node_modules/@mrclrchtr/supi-code-runtime/package.json +1 -1
  3. package/node_modules/@mrclrchtr/supi-code-runtime/src/capability/types.ts +3 -1
  4. package/node_modules/@mrclrchtr/supi-code-runtime/src/query-result.ts +9 -0
  5. package/node_modules/@mrclrchtr/supi-core/package.json +1 -1
  6. package/node_modules/@mrclrchtr/supi-core/src/child-web-tools.ts +110 -0
  7. package/node_modules/@mrclrchtr/supi-core/src/session.ts +11 -0
  8. package/node_modules/semver/LICENSE +15 -0
  9. package/node_modules/semver/README.md +680 -0
  10. package/node_modules/semver/bin/semver.js +195 -0
  11. package/node_modules/semver/classes/comparator.js +143 -0
  12. package/node_modules/semver/classes/index.js +7 -0
  13. package/node_modules/semver/classes/range.js +577 -0
  14. package/node_modules/semver/classes/semver.js +350 -0
  15. package/node_modules/semver/functions/clean.js +8 -0
  16. package/node_modules/semver/functions/cmp.js +54 -0
  17. package/node_modules/semver/functions/coerce.js +62 -0
  18. package/node_modules/semver/functions/compare-build.js +9 -0
  19. package/node_modules/semver/functions/compare-loose.js +5 -0
  20. package/node_modules/semver/functions/compare.js +7 -0
  21. package/node_modules/semver/functions/diff.js +60 -0
  22. package/node_modules/semver/functions/eq.js +5 -0
  23. package/node_modules/semver/functions/gt.js +5 -0
  24. package/node_modules/semver/functions/gte.js +5 -0
  25. package/node_modules/semver/functions/inc.js +21 -0
  26. package/node_modules/semver/functions/lt.js +5 -0
  27. package/node_modules/semver/functions/lte.js +5 -0
  28. package/node_modules/semver/functions/major.js +5 -0
  29. package/node_modules/semver/functions/minor.js +5 -0
  30. package/node_modules/semver/functions/neq.js +5 -0
  31. package/node_modules/semver/functions/parse.js +18 -0
  32. package/node_modules/semver/functions/patch.js +5 -0
  33. package/node_modules/semver/functions/prerelease.js +8 -0
  34. package/node_modules/semver/functions/rcompare.js +5 -0
  35. package/node_modules/semver/functions/rsort.js +5 -0
  36. package/node_modules/semver/functions/satisfies.js +12 -0
  37. package/node_modules/semver/functions/sort.js +5 -0
  38. package/node_modules/semver/functions/truncate.js +48 -0
  39. package/node_modules/semver/functions/valid.js +8 -0
  40. package/node_modules/semver/index.js +93 -0
  41. package/node_modules/semver/internal/constants.js +37 -0
  42. package/node_modules/semver/internal/debug.js +11 -0
  43. package/node_modules/semver/internal/identifiers.js +29 -0
  44. package/node_modules/semver/internal/lrucache.js +42 -0
  45. package/node_modules/semver/internal/parse-options.js +17 -0
  46. package/node_modules/semver/internal/re.js +223 -0
  47. package/node_modules/semver/package.json +78 -0
  48. package/node_modules/semver/preload.js +4 -0
  49. package/node_modules/semver/range.bnf +17 -0
  50. package/node_modules/semver/ranges/gtr.js +6 -0
  51. package/node_modules/semver/ranges/intersects.js +9 -0
  52. package/node_modules/semver/ranges/ltr.js +6 -0
  53. package/node_modules/semver/ranges/max-satisfying.js +27 -0
  54. package/node_modules/semver/ranges/min-satisfying.js +26 -0
  55. package/node_modules/semver/ranges/min-version.js +63 -0
  56. package/node_modules/semver/ranges/outside.js +82 -0
  57. package/node_modules/semver/ranges/simplify.js +49 -0
  58. package/node_modules/semver/ranges/subset.js +249 -0
  59. package/node_modules/semver/ranges/to-comparators.js +10 -0
  60. package/node_modules/semver/ranges/valid.js +13 -0
  61. package/package.json +5 -3
  62. package/src/client/client-diagnostic-collection.ts +11 -4
  63. package/src/client/client-diagnostics.ts +77 -6
  64. package/src/client/client-input-admission.ts +149 -0
  65. package/src/client/client-typescript-project.ts +40 -0
  66. package/src/client/client.ts +174 -49
  67. package/src/config/config.ts +53 -2
  68. package/src/config/operation-support.ts +19 -4
  69. package/src/config/server-config.ts +22 -0
  70. package/src/config/typescript-launch.ts +276 -0
  71. package/src/diagnostics/evidence.ts +2 -2
  72. package/src/manager/manager-project-info.ts +22 -10
  73. package/src/manager/manager-workspace-symbol.ts +157 -23
  74. package/src/manager/manager.ts +306 -75
  75. package/src/provider/refactor-planning.ts +4 -3
  76. package/src/session/runtime-controller.ts +2 -2
  77. package/src/session/runtime-registry.ts +19 -2
  78. package/src/session/runtime-rename.ts +1 -0
  79. package/src/session/scanner.ts +27 -15
  80. package/src/session/workspace-lsp-runtime.ts +5 -1
@@ -139,6 +139,8 @@ function recordScopeDecisionEvent(manager: LspManager): void {
139
139
  }
140
140
  }
141
141
 
142
+ const FILE_STARTUP_FAILURE_REASON = "The routed LSP client could not be started for this file";
143
+
142
144
  class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
143
145
  constructor(private readonly manager: LspManager) {}
144
146
 
@@ -157,6 +159,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
157
159
  const resolvedPath = this.resolveFilePath(filePath);
158
160
  const client = await this.manager.ensureFileOpen(resolvedPath, {
159
161
  recoverProcessCrash: true,
162
+ protectInputs: true,
160
163
  control,
161
164
  });
162
165
  if (!client) return unavailableFileQuery("hover", resolvedPath);
@@ -171,6 +174,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
171
174
  const resolvedPath = this.resolveFilePath(filePath);
172
175
  const client = await this.manager.ensureFileOpen(resolvedPath, {
173
176
  recoverProcessCrash: true,
177
+ protectInputs: true,
174
178
  control,
175
179
  });
176
180
  if (!client) return unavailableFileQuery("definition", resolvedPath);
@@ -185,6 +189,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
185
189
  const resolvedPath = this.resolveFilePath(filePath);
186
190
  const client = await this.manager.ensureFileOpen(resolvedPath, {
187
191
  recoverProcessCrash: true,
192
+ protectInputs: true,
188
193
  control,
189
194
  });
190
195
  if (!client) return unavailableFileQuery("references", resolvedPath);
@@ -202,6 +207,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
202
207
  const resolvedPath = this.resolveFilePath(filePath);
203
208
  const client = await this.manager.ensureFileOpen(resolvedPath, {
204
209
  recoverProcessCrash: true,
210
+ protectInputs: true,
205
211
  control,
206
212
  });
207
213
  if (!client) return unavailableFileQuery("implementation", resolvedPath);
@@ -215,6 +221,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
215
221
  const resolvedPath = this.resolveFilePath(filePath);
216
222
  const client = await this.manager.ensureFileOpen(resolvedPath, {
217
223
  recoverProcessCrash: true,
224
+ protectInputs: true,
218
225
  control,
219
226
  });
220
227
  if (!client) return unavailableFileQuery("document symbols", resolvedPath);
@@ -260,6 +267,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
260
267
  const resolvedPath = this.resolveFilePath(filePath);
261
268
  const client = await this.manager.ensureFileOpen(resolvedPath, {
262
269
  recoverProcessCrash: true,
270
+ protectInputs: true,
263
271
  control,
264
272
  });
265
273
  if (!client) return null;
@@ -309,7 +317,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
309
317
  const processCrashRecovery = this.manager.getProcessCrashRecoveryReportForFile(resolvedPath);
310
318
  return {
311
319
  kind: "unavailable",
312
- reason: "No LSP client can serve this file",
320
+ reason: this.fileUnavailableReason(resolvedPath, "No LSP client can serve this file"),
313
321
  ...(processCrashRecovery ? { processCrashRecovery } : {}),
314
322
  };
315
323
  }
@@ -347,7 +355,7 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
347
355
  if (!client) {
348
356
  return {
349
357
  kind: "unavailable",
350
- reason: "The routed LSP client could not be started for this file",
358
+ reason: this.fileUnavailableReason(resolvedPath, FILE_STARTUP_FAILURE_REASON),
351
359
  ...startup,
352
360
  ...recovery,
353
361
  };
@@ -355,6 +363,15 @@ class DefaultWorkspaceLspRuntime implements WorkspaceLspRuntime {
355
363
  return { kind: "ready", ...startup, ...recovery };
356
364
  }
357
365
 
366
+ private fileUnavailableReason(filePath: string, configuredRouteReason: string): string {
367
+ if (!this.manager.hasConfiguredServerForFile(filePath)) {
368
+ return "No compatible LSP server is configured for this file";
369
+ }
370
+ return this.manager.hasFailedStartupForFile(filePath)
371
+ ? FILE_STARTUP_FAILURE_REASON
372
+ : configuredRouteReason;
373
+ }
374
+
358
375
  /**
359
376
  * Wait until all started LSP clients are ready for semantic queries.
360
377
  * Performs one representative warm-up probe per client/root.
@@ -21,6 +21,7 @@ export async function runRoutedRename(options: {
21
21
  const { manager, file, position, newName, control } = options;
22
22
  const client = await manager.ensureFileOpen(file, {
23
23
  recoverProcessCrash: true,
24
+ protectInputs: true,
24
25
  control,
25
26
  });
26
27
  if (!client) return null;
@@ -7,6 +7,7 @@ import type {
7
7
  MissingServer,
8
8
  ServerConfig,
9
9
  } from "../config/types.ts";
10
+ import { inspectTypeScriptLaunch } from "../config/typescript-launch.ts";
10
11
  import type { LspManager } from "../manager/manager.ts";
11
12
  import { commandExists } from "../utils.ts";
12
13
  import {
@@ -32,20 +33,16 @@ export function scanProjectCapabilities(
32
33
 
33
34
  return Object.entries(config.servers)
34
35
  .flatMap(([serverName, server]) => {
35
- if (!commandExists(server.command)) return [];
36
36
  const allRoots = new Set(markerMatches.get(serverName) ?? []);
37
37
  if (extensionBasedServers.has(serverName)) {
38
38
  allRoots.add(cwd);
39
39
  }
40
40
  const roots = dedupeTopmostRoots(Array.from(allRoots));
41
- return roots.map(
42
- (root) =>
43
- ({
44
- name: serverName,
45
- root,
46
- fileTypes: [...server.fileTypes],
47
- }) satisfies DetectedProjectServer,
48
- );
41
+ return roots.flatMap((root) => {
42
+ const { command, ...selection } = inspectTypeScriptLaunch(serverName, server, root);
43
+ if (!selection.failureMessage && !commandExists(command)) return [];
44
+ return [{ name: serverName, root, fileTypes: [...server.fileTypes], ...selection }];
45
+ });
49
46
  })
50
47
  .sort((a, b) => a.root.localeCompare(b.root) || a.name.localeCompare(b.name));
51
48
  }
@@ -79,8 +76,6 @@ function inspectDirectory(
79
76
  ctx: HintContext,
80
77
  ): void {
81
78
  for (const [serverName, server] of Object.entries(servers)) {
82
- if (!commandExists(server.command)) continue;
83
-
84
79
  if (server.rootMarkers.length === 0) {
85
80
  if (hasMatchingFile(directory, entryNames, server.fileTypes)) {
86
81
  ctx.extensionBasedServers.add(serverName);
@@ -122,7 +117,7 @@ export async function startDetectedServers(
122
117
 
123
118
  /**
124
119
  * Scan the project for languages whose source files exist but whose LSP server
125
- * binary is not installed on PATH. Walks the project directory tree collecting
120
+ * executable or selected compiler is unavailable. Walks the project tree collecting
126
121
  * file extensions, then checks each configured server.
127
122
  */
128
123
  export function scanMissingServers(
@@ -142,14 +137,31 @@ export function scanMissingServers(
142
137
  });
143
138
 
144
139
  const missing: MissingServer[] = [];
140
+ const { markerMatches } = collectServerHints(config, cwd, maxDepth, policy);
145
141
 
146
142
  for (const [name, server] of Object.entries(config.servers)) {
147
- if (commandExists(server.command)) continue;
148
-
149
143
  const matching = server.fileTypes.filter((ft) => foundExtensions.has(ft));
150
144
  if (matching.length === 0) continue;
151
145
 
152
- missing.push({ name, command: server.command, foundExtensions: matching });
146
+ const roots = dedupeTopmostRoots(Array.from(markerMatches.get(name) ?? []));
147
+ for (const root of roots.length ? roots : [cwd]) {
148
+ const selection = inspectTypeScriptLaunch(name, server, root);
149
+ const command = selection.command;
150
+ if (selection.failureMessage) {
151
+ missing.push({
152
+ name,
153
+ command,
154
+ foundExtensions: matching,
155
+ root,
156
+ failureMessage: selection.failureMessage,
157
+ });
158
+ continue;
159
+ }
160
+ if (!commandExists(command)) {
161
+ missing.push({ name, command, foundExtensions: matching });
162
+ break;
163
+ }
164
+ }
153
165
  }
154
166
 
155
167
  return missing;
@@ -143,7 +143,11 @@ export interface WorkspaceLspRuntime extends WorkspaceLspDiagnosticSurface {
143
143
  filePath: string,
144
144
  control?: CodeRequestControl,
145
145
  ): Promise<CodeQueryResult<DocumentSymbol[] | SymbolInformation[]>>;
146
- /** Collect symbols from routes that can contribute within the optional path scopes. */
146
+ /**
147
+ * Collect symbols from contributing routes; completeness is relative to scopes.
148
+ * Data may include out-of-scope rows, which callers must filter themselves.
149
+ * Only policy exclusions proven outside every scope are irrelevant to completeness.
150
+ */
147
151
  workspaceSymbol(
148
152
  query: string,
149
153
  control?: CodeRequestControl,