pi-lens 3.6.2 → 3.6.4
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/CHANGELOG.md +10 -2
- package/package.json +4 -4
- package/tsconfig.json +1 -1
- package/clients/__tests__/file-time.test.js +0 -216
- package/clients/__tests__/file-time.test.ts +0 -276
- package/clients/__tests__/format-service.test.js +0 -245
- package/clients/__tests__/format-service.test.ts +0 -339
- package/clients/__tests__/formatters.test.js +0 -271
- package/clients/__tests__/formatters.test.ts +0 -401
- package/clients/agent-behavior-client.js +0 -110
- package/clients/agent-behavior-client.test.js +0 -94
- package/clients/agent-behavior-client.test.ts +0 -116
- package/clients/amain-types.js +0 -164
- package/clients/architect-client.js +0 -291
- package/clients/ast-grep-client.js +0 -253
- package/clients/ast-grep-parser.js +0 -84
- package/clients/ast-grep-rule-manager.js +0 -89
- package/clients/ast-grep-types.js +0 -9
- package/clients/auto-loop.js +0 -131
- package/clients/biome-client.js +0 -420
- package/clients/biome-client.test.js +0 -144
- package/clients/biome-client.test.ts +0 -163
- package/clients/cache/rule-cache.js +0 -72
- package/clients/cache-manager.js +0 -245
- package/clients/cache-manager.test.js +0 -197
- package/clients/cache-manager.test.ts +0 -299
- package/clients/complexity-client.js +0 -675
- package/clients/complexity-client.test.js +0 -234
- package/clients/complexity-client.test.ts +0 -255
- package/clients/config-validator.js +0 -465
- package/clients/dependency-checker.js +0 -325
- package/clients/dependency-checker.test.js +0 -60
- package/clients/dependency-checker.test.ts +0 -71
- package/clients/dispatch/__tests__/autofix-integration.test.js +0 -245
- package/clients/dispatch/__tests__/autofix-integration.test.ts +0 -300
- package/clients/dispatch/__tests__/runner-registration.test.js +0 -234
- package/clients/dispatch/__tests__/runner-registration.test.ts +0 -286
- package/clients/dispatch/debug.log +0 -1
- package/clients/dispatch/dispatcher.edge.test.js +0 -82
- package/clients/dispatch/dispatcher.edge.test.ts +0 -100
- package/clients/dispatch/dispatcher.format.test.js +0 -46
- package/clients/dispatch/dispatcher.format.test.ts +0 -58
- package/clients/dispatch/dispatcher.inline.test.js +0 -74
- package/clients/dispatch/dispatcher.inline.test.ts +0 -93
- package/clients/dispatch/dispatcher.js +0 -381
- package/clients/dispatch/dispatcher.test.js +0 -116
- package/clients/dispatch/dispatcher.test.ts +0 -149
- package/clients/dispatch/integration.js +0 -108
- package/clients/dispatch/plan.js +0 -183
- package/clients/dispatch/runners/architect.js +0 -83
- package/clients/dispatch/runners/architect.test.js +0 -138
- package/clients/dispatch/runners/architect.test.ts +0 -162
- package/clients/dispatch/runners/ast-grep-napi.js +0 -405
- package/clients/dispatch/runners/ast-grep-napi.test.js +0 -107
- package/clients/dispatch/runners/ast-grep-napi.test.ts +0 -129
- package/clients/dispatch/runners/ast-grep.js +0 -157
- package/clients/dispatch/runners/biome.js +0 -55
- package/clients/dispatch/runners/config-validation.js +0 -67
- package/clients/dispatch/runners/go-vet.js +0 -48
- package/clients/dispatch/runners/index.js +0 -47
- package/clients/dispatch/runners/lsp.js +0 -102
- package/clients/dispatch/runners/oxlint.js +0 -67
- package/clients/dispatch/runners/oxlint.test.js +0 -230
- package/clients/dispatch/runners/oxlint.test.ts +0 -303
- package/clients/dispatch/runners/pyright.js +0 -100
- package/clients/dispatch/runners/pyright.test.js +0 -98
- package/clients/dispatch/runners/pyright.test.ts +0 -121
- package/clients/dispatch/runners/python-slop.js +0 -97
- package/clients/dispatch/runners/python-slop.test.js +0 -203
- package/clients/dispatch/runners/python-slop.test.ts +0 -298
- package/clients/dispatch/runners/ruff.js +0 -48
- package/clients/dispatch/runners/rust-clippy.js +0 -102
- package/clients/dispatch/runners/scan_codebase.test.js +0 -89
- package/clients/dispatch/runners/scan_codebase.test.ts +0 -105
- package/clients/dispatch/runners/shellcheck.js +0 -147
- package/clients/dispatch/runners/shellcheck.test.js +0 -98
- package/clients/dispatch/runners/shellcheck.test.ts +0 -129
- package/clients/dispatch/runners/similarity.js +0 -230
- package/clients/dispatch/runners/spellcheck.js +0 -106
- package/clients/dispatch/runners/spellcheck.test.js +0 -158
- package/clients/dispatch/runners/spellcheck.test.ts +0 -214
- package/clients/dispatch/runners/tree-sitter.js +0 -246
- package/clients/dispatch/runners/ts-lsp.js +0 -125
- package/clients/dispatch/runners/ts-slop.js +0 -113
- package/clients/dispatch/runners/type-safety.js +0 -142
- package/clients/dispatch/runners/utils/diagnostic-parsers.js +0 -134
- package/clients/dispatch/runners/utils/runner-helpers.js +0 -115
- package/clients/dispatch/runners/utils.js +0 -51
- package/clients/dispatch/runners/yaml-rule-parser.js +0 -360
- package/clients/dispatch/types.js +0 -16
- package/clients/dispatch/utils/format-utils.js +0 -44
- package/clients/dogfood.test.js +0 -201
- package/clients/dogfood.test.ts +0 -269
- package/clients/file-kinds.js +0 -177
- package/clients/file-kinds.test.js +0 -169
- package/clients/file-kinds.test.ts +0 -210
- package/clients/file-time.js +0 -152
- package/clients/file-utils.js +0 -40
- package/clients/fix-scanners.js +0 -204
- package/clients/format-service.js +0 -184
- package/clients/formatters.js +0 -488
- package/clients/go-client.js +0 -203
- package/clients/go-client.test.js +0 -127
- package/clients/go-client.test.ts +0 -143
- package/clients/installer/index.js +0 -403
- package/clients/interviewer-templates.js +0 -75
- package/clients/interviewer.js +0 -173
- package/clients/jscpd-client.js +0 -196
- package/clients/jscpd-client.test.js +0 -127
- package/clients/jscpd-client.test.ts +0 -145
- package/clients/knip-client.js +0 -239
- package/clients/knip-client.test.js +0 -112
- package/clients/knip-client.test.ts +0 -128
- package/clients/latency-logger.js +0 -40
- package/clients/lsp/__tests__/client.test.js +0 -310
- package/clients/lsp/__tests__/client.test.ts +0 -412
- package/clients/lsp/__tests__/config.test.js +0 -167
- package/clients/lsp/__tests__/config.test.ts +0 -217
- package/clients/lsp/__tests__/error-recovery.test.js +0 -213
- package/clients/lsp/__tests__/error-recovery.test.ts +0 -279
- package/clients/lsp/__tests__/integration.test.js +0 -127
- package/clients/lsp/__tests__/integration.test.ts +0 -160
- package/clients/lsp/__tests__/launch.test.js +0 -313
- package/clients/lsp/__tests__/launch.test.ts +0 -394
- package/clients/lsp/__tests__/server.test.js +0 -259
- package/clients/lsp/__tests__/server.test.ts +0 -332
- package/clients/lsp/__tests__/service.test.js +0 -438
- package/clients/lsp/__tests__/service.test.ts +0 -530
- package/clients/lsp/client.js +0 -350
- package/clients/lsp/config.js +0 -112
- package/clients/lsp/index.js +0 -318
- package/clients/lsp/installer/index.js +0 -391
- package/clients/lsp/interactive-install.js +0 -221
- package/clients/lsp/language.js +0 -170
- package/clients/lsp/launch.js +0 -329
- package/clients/lsp/lsp/launch.js +0 -116
- package/clients/lsp/lsp/server.js +0 -532
- package/clients/lsp/lsp-index.js +0 -10
- package/clients/lsp/path-utils.js +0 -5
- package/clients/lsp/server.js +0 -725
- package/clients/lsp/test-py-spawn/requirements.txt +0 -1
- package/clients/lsp/test-py-spawn/test.py +0 -3
- package/clients/lsp/test-py-svc/requirements.txt +0 -1
- package/clients/lsp/test-py-svc/test.py +0 -3
- package/clients/lsp/test-python-project/requirements.txt +0 -1
- package/clients/lsp/test-python-project/test.py +0 -5
- package/clients/metrics-client.js +0 -107
- package/clients/metrics-client.test.js +0 -128
- package/clients/metrics-client.test.ts +0 -163
- package/clients/metrics-history.js +0 -367
- package/clients/path-utils.js +0 -142
- package/clients/pipeline.js +0 -272
- package/clients/production-readiness.js +0 -522
- package/clients/project-index.js +0 -255
- package/clients/project-metadata.js +0 -531
- package/clients/ruff-client.js +0 -325
- package/clients/ruff-client.test.js +0 -132
- package/clients/ruff-client.test.ts +0 -153
- package/clients/rules-scanner.js +0 -97
- package/clients/runner-tracker.js +0 -152
- package/clients/rust-client.js +0 -205
- package/clients/rust-client.test.js +0 -108
- package/clients/rust-client.test.ts +0 -130
- package/clients/safe-spawn-async.js +0 -163
- package/clients/safe-spawn.js +0 -241
- package/clients/sanitize.js +0 -291
- package/clients/sanitize.test.js +0 -177
- package/clients/sanitize.test.ts +0 -223
- package/clients/scan-architectural-debt.js +0 -167
- package/clients/scan-utils.js +0 -83
- package/clients/secrets-scanner.js +0 -119
- package/clients/secrets-scanner.test.js +0 -100
- package/clients/secrets-scanner.test.ts +0 -113
- package/clients/sg-runner.js +0 -292
- package/clients/state-matrix.js +0 -160
- package/clients/subprocess-client.js +0 -65
- package/clients/symbol-types.js +0 -5
- package/clients/test-runner-client.js +0 -523
- package/clients/test-runner-client.test.js +0 -192
- package/clients/test-runner-client.test.ts +0 -253
- package/clients/test-utils.js +0 -27
- package/clients/test-utils.ts +0 -36
- package/clients/todo-scanner.js +0 -200
- package/clients/todo-scanner.test.js +0 -301
- package/clients/todo-scanner.test.ts +0 -352
- package/clients/tool-availability.js +0 -207
- package/clients/tree-sitter-client.js +0 -601
- package/clients/tree-sitter-query-loader.js +0 -355
- package/clients/tree-sitter-symbol-extractor.js +0 -289
- package/clients/ts-service.js +0 -129
- package/clients/type-coverage-client.js +0 -127
- package/clients/type-coverage-client.test.js +0 -105
- package/clients/type-coverage-client.test.ts +0 -125
- package/clients/type-safety-client.js +0 -138
- package/clients/types.js +0 -11
- package/clients/typescript-client.codefix.test.js +0 -157
- package/clients/typescript-client.codefix.test.ts +0 -186
- package/clients/typescript-client.js +0 -509
- package/clients/typescript-client.test.js +0 -105
- package/clients/typescript-client.test.ts +0 -126
- package/commands/booboo.js +0 -1007
- package/commands/fix-from-booboo.js +0 -398
- package/commands/fix-simplified.js +0 -618
- package/commands/rate.js +0 -281
- package/commands/rate.test.js +0 -119
- package/commands/rate.test.ts +0 -131
- package/commands/refactor.js +0 -130
package/clients/lsp/client.js
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LSP Client for pi-lens
|
|
3
|
-
*
|
|
4
|
-
* Handles JSON-RPC communication with language servers:
|
|
5
|
-
* - Initialize/shutdown lifecycle
|
|
6
|
-
* - Document synchronization (didOpen, didChange)
|
|
7
|
-
* - Diagnostics with debouncing
|
|
8
|
-
* - Request/response handling
|
|
9
|
-
*/
|
|
10
|
-
import { EventEmitter } from "node:events";
|
|
11
|
-
import { pathToFileURL } from "node:url";
|
|
12
|
-
import { createMessageConnection, StreamMessageReader, StreamMessageWriter, } from "vscode-jsonrpc/node.js";
|
|
13
|
-
import { normalizeMapKey, uriToPath } from "./path-utils.js";
|
|
14
|
-
// --- Constants ---
|
|
15
|
-
const DIAGNOSTICS_DEBOUNCE_MS = 150; // ms — waits for follow-up semantic diagnostics
|
|
16
|
-
const INITIALIZE_TIMEOUT_MS = 120000; // 2 minutes (was 45s) - allows time for npx to download packages
|
|
17
|
-
// --- Client Factory ---
|
|
18
|
-
export async function createLSPClient(options) {
|
|
19
|
-
const { serverId, process: lspProcess, root, initialization } = options;
|
|
20
|
-
// Create JSON-RPC connection
|
|
21
|
-
const connection = createMessageConnection(new StreamMessageReader(lspProcess.stdout), new StreamMessageWriter(lspProcess.stdin));
|
|
22
|
-
// Track diagnostics per file
|
|
23
|
-
const diagnostics = new Map();
|
|
24
|
-
const pendingDiagnostics = new Map();
|
|
25
|
-
// Local event emitter — signals waitForDiagnostics when new diagnostics arrive.
|
|
26
|
-
// Scoped to this client instance; replaces global bus pub/sub.
|
|
27
|
-
// setMaxListeners guards against Node.js warning for concurrent waitForDiagnostics calls.
|
|
28
|
-
const diagnosticEmitter = new EventEmitter();
|
|
29
|
-
diagnosticEmitter.setMaxListeners(50);
|
|
30
|
-
// Handle incoming diagnostics with debouncing
|
|
31
|
-
connection.onNotification("textDocument/publishDiagnostics", (params) => {
|
|
32
|
-
const filePath = uriToPath(params.uri);
|
|
33
|
-
const newDiags = params.diagnostics || [];
|
|
34
|
-
// Debounce: clear existing timer and set new one
|
|
35
|
-
const existingTimer = pendingDiagnostics.get(filePath);
|
|
36
|
-
if (existingTimer)
|
|
37
|
-
clearTimeout(existingTimer);
|
|
38
|
-
const timer = setTimeout(() => {
|
|
39
|
-
diagnostics.set(filePath, newDiags);
|
|
40
|
-
pendingDiagnostics.delete(filePath);
|
|
41
|
-
// Signal any active waitForDiagnostics calls for this file.
|
|
42
|
-
diagnosticEmitter.emit("diagnostics", filePath);
|
|
43
|
-
}, DIAGNOSTICS_DEBOUNCE_MS);
|
|
44
|
-
pendingDiagnostics.set(filePath, timer);
|
|
45
|
-
});
|
|
46
|
-
// Handle server requests
|
|
47
|
-
connection.onRequest("workspace/workspaceFolders", () => [
|
|
48
|
-
{
|
|
49
|
-
name: "workspace",
|
|
50
|
-
uri: pathToFileURL(root).href,
|
|
51
|
-
},
|
|
52
|
-
]);
|
|
53
|
-
connection.onRequest("client/registerCapability", async () => { });
|
|
54
|
-
connection.onRequest("client/unregisterCapability", async () => { });
|
|
55
|
-
connection.onRequest("workspace/configuration", async () => [
|
|
56
|
-
initialization ?? {},
|
|
57
|
-
]);
|
|
58
|
-
connection.onRequest("window/workDoneProgress/create", async () => { });
|
|
59
|
-
// Start listening
|
|
60
|
-
connection.listen();
|
|
61
|
-
// Send initialize request
|
|
62
|
-
await withTimeout(connection.sendRequest("initialize", {
|
|
63
|
-
processId: process.pid,
|
|
64
|
-
rootUri: pathToFileURL(root).href,
|
|
65
|
-
workspaceFolders: [
|
|
66
|
-
{
|
|
67
|
-
name: "workspace",
|
|
68
|
-
uri: pathToFileURL(root).href,
|
|
69
|
-
},
|
|
70
|
-
],
|
|
71
|
-
capabilities: {
|
|
72
|
-
window: {
|
|
73
|
-
workDoneProgress: true,
|
|
74
|
-
},
|
|
75
|
-
workspace: {
|
|
76
|
-
workspaceFolders: true, // Simple boolean for broader compatibility
|
|
77
|
-
configuration: true,
|
|
78
|
-
didChangeWatchedFiles: {
|
|
79
|
-
dynamicRegistration: true,
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
textDocument: {
|
|
83
|
-
synchronization: {
|
|
84
|
-
didOpen: true,
|
|
85
|
-
didChange: true,
|
|
86
|
-
},
|
|
87
|
-
publishDiagnostics: {
|
|
88
|
-
versionSupport: true,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
initializationOptions: initialization,
|
|
93
|
-
}), INITIALIZE_TIMEOUT_MS);
|
|
94
|
-
// Send initialized notification
|
|
95
|
-
await connection.sendNotification("initialized", {});
|
|
96
|
-
// Send configuration if provided (helps pyright and other servers)
|
|
97
|
-
if (initialization) {
|
|
98
|
-
await connection.sendNotification("workspace/didChangeConfiguration", {
|
|
99
|
-
settings: initialization,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
// Track open documents with version numbers
|
|
103
|
-
const documentVersions = new Map();
|
|
104
|
-
return {
|
|
105
|
-
serverId,
|
|
106
|
-
root,
|
|
107
|
-
connection,
|
|
108
|
-
notify: {
|
|
109
|
-
async open(filePath, content, languageId) {
|
|
110
|
-
const uri = pathToFileURL(filePath).href;
|
|
111
|
-
// Normalize path for Windows case-insensitive lookup
|
|
112
|
-
const normalizedPath = normalizeMapKey(filePath);
|
|
113
|
-
documentVersions.set(normalizedPath, 0);
|
|
114
|
-
diagnostics.delete(normalizedPath); // Clear stale diagnostics
|
|
115
|
-
// Send workspace notification first (like opencode does)
|
|
116
|
-
await connection.sendNotification("workspace/didChangeWatchedFiles", {
|
|
117
|
-
changes: [
|
|
118
|
-
{
|
|
119
|
-
uri,
|
|
120
|
-
type: 1, // Created
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
});
|
|
124
|
-
await connection.sendNotification("textDocument/didOpen", {
|
|
125
|
-
textDocument: {
|
|
126
|
-
uri,
|
|
127
|
-
languageId,
|
|
128
|
-
version: 0,
|
|
129
|
-
text: content,
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
},
|
|
133
|
-
async change(filePath, content) {
|
|
134
|
-
const uri = pathToFileURL(filePath).href;
|
|
135
|
-
// Normalize path for Windows case-insensitive lookup
|
|
136
|
-
const normalizedPath = normalizeMapKey(filePath);
|
|
137
|
-
const version = (documentVersions.get(normalizedPath) ?? 0) + 1;
|
|
138
|
-
documentVersions.set(normalizedPath, version);
|
|
139
|
-
await connection.sendNotification("textDocument/didChange", {
|
|
140
|
-
textDocument: { uri, version },
|
|
141
|
-
contentChanges: [{ text: content }],
|
|
142
|
-
});
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
getDiagnostics(filePath) {
|
|
146
|
-
// Normalize path for Windows case-insensitive lookup
|
|
147
|
-
const normalizedPath = normalizeMapKey(filePath);
|
|
148
|
-
return diagnostics.get(normalizedPath) ?? [];
|
|
149
|
-
},
|
|
150
|
-
getAllDiagnostics() {
|
|
151
|
-
// Return copy of all tracked diagnostics (for cascade checking)
|
|
152
|
-
return new Map(diagnostics);
|
|
153
|
-
},
|
|
154
|
-
async waitForDiagnostics(filePath, timeoutMs = 10000) {
|
|
155
|
-
const normalizedPath = normalizeMapKey(filePath);
|
|
156
|
-
// Fast path: diagnostics already available
|
|
157
|
-
if (diagnostics.has(normalizedPath))
|
|
158
|
-
return;
|
|
159
|
-
return new Promise((resolve) => {
|
|
160
|
-
let debounceTimer;
|
|
161
|
-
// Listen on the local emitter for this client's diagnostic notifications.
|
|
162
|
-
// No runnerId filter needed — this emitter is scoped to this client instance.
|
|
163
|
-
const onDiagnostics = (fp) => {
|
|
164
|
-
if (normalizeMapKey(fp) !== normalizedPath)
|
|
165
|
-
return;
|
|
166
|
-
// Debounce: reset on each event to catch follow-up semantic diagnostics
|
|
167
|
-
// (LSP often sends syntax diagnostics first, semantic ones shortly after).
|
|
168
|
-
if (debounceTimer)
|
|
169
|
-
clearTimeout(debounceTimer);
|
|
170
|
-
debounceTimer = setTimeout(() => {
|
|
171
|
-
diagnosticEmitter.off("diagnostics", onDiagnostics);
|
|
172
|
-
clearTimeout(timeout);
|
|
173
|
-
resolve();
|
|
174
|
-
}, DIAGNOSTICS_DEBOUNCE_MS);
|
|
175
|
-
};
|
|
176
|
-
diagnosticEmitter.on("diagnostics", onDiagnostics);
|
|
177
|
-
// Timeout fallback: resolve even if no diagnostics arrive
|
|
178
|
-
// (some files have no errors, or the server may be slow)
|
|
179
|
-
const timeout = setTimeout(() => {
|
|
180
|
-
if (debounceTimer)
|
|
181
|
-
clearTimeout(debounceTimer);
|
|
182
|
-
diagnosticEmitter.off("diagnostics", onDiagnostics);
|
|
183
|
-
resolve();
|
|
184
|
-
}, timeoutMs);
|
|
185
|
-
});
|
|
186
|
-
},
|
|
187
|
-
async definition(filePath, line, character) {
|
|
188
|
-
const uri = pathToFileURL(filePath).href;
|
|
189
|
-
try {
|
|
190
|
-
const result = await connection.sendRequest("textDocument/definition", {
|
|
191
|
-
textDocument: { uri },
|
|
192
|
-
position: { line, character },
|
|
193
|
-
});
|
|
194
|
-
if (!result)
|
|
195
|
-
return [];
|
|
196
|
-
return Array.isArray(result) ? result : [result];
|
|
197
|
-
}
|
|
198
|
-
catch {
|
|
199
|
-
return [];
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
async references(filePath, line, character, includeDeclaration = true) {
|
|
203
|
-
const uri = pathToFileURL(filePath).href;
|
|
204
|
-
try {
|
|
205
|
-
const result = await connection.sendRequest("textDocument/references", {
|
|
206
|
-
textDocument: { uri },
|
|
207
|
-
position: { line, character },
|
|
208
|
-
context: { includeDeclaration },
|
|
209
|
-
});
|
|
210
|
-
return Array.isArray(result) ? result : [];
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
return [];
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
async hover(filePath, line, character) {
|
|
217
|
-
const uri = pathToFileURL(filePath).href;
|
|
218
|
-
try {
|
|
219
|
-
return (await connection.sendRequest("textDocument/hover", {
|
|
220
|
-
textDocument: { uri },
|
|
221
|
-
position: { line, character },
|
|
222
|
-
}));
|
|
223
|
-
}
|
|
224
|
-
catch {
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
async documentSymbol(filePath) {
|
|
229
|
-
const uri = pathToFileURL(filePath).href;
|
|
230
|
-
try {
|
|
231
|
-
const result = await connection.sendRequest("textDocument/documentSymbol", {
|
|
232
|
-
textDocument: { uri },
|
|
233
|
-
});
|
|
234
|
-
return Array.isArray(result) ? result : [];
|
|
235
|
-
}
|
|
236
|
-
catch {
|
|
237
|
-
return [];
|
|
238
|
-
}
|
|
239
|
-
},
|
|
240
|
-
async workspaceSymbol(query) {
|
|
241
|
-
try {
|
|
242
|
-
const result = await connection.sendRequest("workspace/symbol", {
|
|
243
|
-
query,
|
|
244
|
-
});
|
|
245
|
-
return Array.isArray(result) ? result : [];
|
|
246
|
-
}
|
|
247
|
-
catch {
|
|
248
|
-
return [];
|
|
249
|
-
}
|
|
250
|
-
},
|
|
251
|
-
async implementation(filePath, line, character) {
|
|
252
|
-
const uri = pathToFileURL(filePath).href;
|
|
253
|
-
try {
|
|
254
|
-
const result = await connection.sendRequest("textDocument/implementation", {
|
|
255
|
-
textDocument: { uri },
|
|
256
|
-
position: { line, character },
|
|
257
|
-
});
|
|
258
|
-
if (!result)
|
|
259
|
-
return [];
|
|
260
|
-
return Array.isArray(result) ? result : [result];
|
|
261
|
-
}
|
|
262
|
-
catch {
|
|
263
|
-
return [];
|
|
264
|
-
}
|
|
265
|
-
},
|
|
266
|
-
// --- Call Hierarchy Methods ---
|
|
267
|
-
async prepareCallHierarchy(filePath, line, character) {
|
|
268
|
-
const uri = pathToFileURL(filePath).href;
|
|
269
|
-
try {
|
|
270
|
-
const result = await connection.sendRequest("textDocument/prepareCallHierarchy", {
|
|
271
|
-
textDocument: { uri },
|
|
272
|
-
position: { line, character },
|
|
273
|
-
});
|
|
274
|
-
if (!result)
|
|
275
|
-
return [];
|
|
276
|
-
return Array.isArray(result) ? result : [result];
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
return [];
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
async incomingCalls(item) {
|
|
283
|
-
try {
|
|
284
|
-
const result = await connection.sendRequest("callHierarchy/incomingCalls", {
|
|
285
|
-
item,
|
|
286
|
-
});
|
|
287
|
-
if (!result)
|
|
288
|
-
return [];
|
|
289
|
-
return Array.isArray(result) ? result : [];
|
|
290
|
-
}
|
|
291
|
-
catch {
|
|
292
|
-
return [];
|
|
293
|
-
}
|
|
294
|
-
},
|
|
295
|
-
async outgoingCalls(item) {
|
|
296
|
-
try {
|
|
297
|
-
const result = await connection.sendRequest("callHierarchy/outgoingCalls", {
|
|
298
|
-
item,
|
|
299
|
-
});
|
|
300
|
-
if (!result)
|
|
301
|
-
return [];
|
|
302
|
-
return Array.isArray(result) ? result : [];
|
|
303
|
-
}
|
|
304
|
-
catch {
|
|
305
|
-
return [];
|
|
306
|
-
}
|
|
307
|
-
},
|
|
308
|
-
async shutdown() {
|
|
309
|
-
// Clear pending timers
|
|
310
|
-
for (const timer of pendingDiagnostics.values()) {
|
|
311
|
-
clearTimeout(timer);
|
|
312
|
-
}
|
|
313
|
-
pendingDiagnostics.clear();
|
|
314
|
-
// Remove all diagnostic listeners (cancels any in-flight waitForDiagnostics)
|
|
315
|
-
diagnosticEmitter.removeAllListeners();
|
|
316
|
-
// Graceful shutdown
|
|
317
|
-
try {
|
|
318
|
-
await connection.sendRequest("shutdown");
|
|
319
|
-
await connection.sendNotification("exit");
|
|
320
|
-
}
|
|
321
|
-
catch {
|
|
322
|
-
/* ignore */
|
|
323
|
-
}
|
|
324
|
-
connection.dispose();
|
|
325
|
-
lspProcess.process.kill();
|
|
326
|
-
},
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
// --- Utilities ---
|
|
330
|
-
// Using shared path utilities from path-utils.ts
|
|
331
|
-
function severityFromNumber(sev) {
|
|
332
|
-
switch (sev) {
|
|
333
|
-
case 1:
|
|
334
|
-
return "error";
|
|
335
|
-
case 2:
|
|
336
|
-
return "warning";
|
|
337
|
-
case 3:
|
|
338
|
-
return "info";
|
|
339
|
-
case 4:
|
|
340
|
-
return "hint";
|
|
341
|
-
default:
|
|
342
|
-
return "error";
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
async function withTimeout(promise, timeoutMs) {
|
|
346
|
-
return Promise.race([
|
|
347
|
-
promise,
|
|
348
|
-
new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout after ${timeoutMs}ms`)), timeoutMs)),
|
|
349
|
-
]);
|
|
350
|
-
}
|
package/clients/lsp/config.js
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* LSP Configuration for pi-lens
|
|
3
|
-
*
|
|
4
|
-
* Allows users to define custom LSP servers via configuration.
|
|
5
|
-
*
|
|
6
|
-
* Config file: .pi-lens/lsp.json
|
|
7
|
-
*
|
|
8
|
-
* Example:
|
|
9
|
-
* {
|
|
10
|
-
* "servers": {
|
|
11
|
-
* "my-server": {
|
|
12
|
-
* "name": "My Custom LSP",
|
|
13
|
-
* "extensions": [".myext"],
|
|
14
|
-
* "command": "my-lsp-server",
|
|
15
|
-
* "args": ["--stdio"],
|
|
16
|
-
* "rootMarkers": ["package.json"]
|
|
17
|
-
* }
|
|
18
|
-
* }
|
|
19
|
-
* }
|
|
20
|
-
*/
|
|
21
|
-
import fs from "node:fs/promises";
|
|
22
|
-
import path from "node:path";
|
|
23
|
-
import { fileURLToPath } from "node:url";
|
|
24
|
-
import { launchLSP } from "./launch.js";
|
|
25
|
-
import { createRootDetector, LSP_SERVERS, } from "./server.js";
|
|
26
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
27
|
-
// --- Config Loading ---
|
|
28
|
-
const CONFIG_PATHS = [".pi-lens/lsp.json", ".pi-lens.json", "pi-lsp.json"];
|
|
29
|
-
/**
|
|
30
|
-
* Load LSP configuration from file
|
|
31
|
-
*/
|
|
32
|
-
export async function loadLSPConfig(cwd) {
|
|
33
|
-
for (const configPath of CONFIG_PATHS) {
|
|
34
|
-
const fullPath = path.join(cwd, configPath);
|
|
35
|
-
try {
|
|
36
|
-
const content = await fs.readFile(fullPath, "utf-8");
|
|
37
|
-
const config = JSON.parse(content);
|
|
38
|
-
console.error(`[lsp-config] Loaded config from ${configPath}`);
|
|
39
|
-
return config;
|
|
40
|
-
}
|
|
41
|
-
catch {
|
|
42
|
-
// File doesn't exist or is invalid, try next
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return {};
|
|
46
|
-
}
|
|
47
|
-
// --- Custom Server Factory ---
|
|
48
|
-
/**
|
|
49
|
-
* Create LSPServerInfo from user configuration
|
|
50
|
-
*/
|
|
51
|
-
export function createCustomServer(config, id) {
|
|
52
|
-
return {
|
|
53
|
-
id,
|
|
54
|
-
name: config.name,
|
|
55
|
-
extensions: config.extensions,
|
|
56
|
-
root: config.rootMarkers
|
|
57
|
-
? createRootDetector(config.rootMarkers)
|
|
58
|
-
: async () => process.cwd(),
|
|
59
|
-
async spawn(root) {
|
|
60
|
-
const proc = await launchLSP(config.command, config.args ?? ["--stdio"], {
|
|
61
|
-
cwd: root,
|
|
62
|
-
env: config.env ? { ...process.env, ...config.env } : process.env,
|
|
63
|
-
});
|
|
64
|
-
return { process: proc };
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
// --- Registry Management ---
|
|
69
|
-
let customServers = [];
|
|
70
|
-
let disabledServerIds = new Set();
|
|
71
|
-
/**
|
|
72
|
-
* Initialize LSP configuration (call at session start)
|
|
73
|
-
*/
|
|
74
|
-
export async function initLSPConfig(cwd) {
|
|
75
|
-
const config = await loadLSPConfig(cwd);
|
|
76
|
-
// Clear previous custom servers
|
|
77
|
-
customServers = [];
|
|
78
|
-
disabledServerIds = new Set(config.disabledServers ?? []);
|
|
79
|
-
// Register custom servers from config
|
|
80
|
-
if (config.servers) {
|
|
81
|
-
for (const [id, serverConfig] of Object.entries(config.servers)) {
|
|
82
|
-
try {
|
|
83
|
-
const server = createCustomServer(serverConfig, id);
|
|
84
|
-
customServers.push(server);
|
|
85
|
-
console.error(`[lsp-config] Registered custom server: ${id} (${serverConfig.name})`);
|
|
86
|
-
}
|
|
87
|
-
catch (err) {
|
|
88
|
-
console.error(`[lsp-config] Failed to register server ${id}:`, err);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Get all available servers (built-in + custom, minus disabled)
|
|
95
|
-
*/
|
|
96
|
-
export function getAllServers() {
|
|
97
|
-
const all = [...LSP_SERVERS, ...customServers];
|
|
98
|
-
return all.filter((s) => !disabledServerIds.has(s.id));
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Check if a server is disabled
|
|
102
|
-
*/
|
|
103
|
-
export function isServerDisabled(serverId) {
|
|
104
|
-
return disabledServerIds.has(serverId);
|
|
105
|
-
}
|
|
106
|
-
// --- Override getServersForFile to include custom servers
|
|
107
|
-
export function getServersForFileWithConfig(filePath) {
|
|
108
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
109
|
-
return getAllServers().filter((server) => server.extensions.includes(ext));
|
|
110
|
-
}
|
|
111
|
-
// Re-export with config support
|
|
112
|
-
export { getAllServers as getServersForFile };
|