@kenkaiiii/ggcoder 4.8.7 → 4.9.1
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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +12 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/lsp/client.d.ts +63 -0
- package/dist/core/lsp/client.d.ts.map +1 -0
- package/dist/core/lsp/client.js +215 -0
- package/dist/core/lsp/client.js.map +1 -0
- package/dist/core/lsp/format.d.ts +12 -0
- package/dist/core/lsp/format.d.ts.map +1 -0
- package/dist/core/lsp/format.js +30 -0
- package/dist/core/lsp/format.js.map +1 -0
- package/dist/core/lsp/format.test.d.ts +2 -0
- package/dist/core/lsp/format.test.d.ts.map +1 -0
- package/dist/core/lsp/format.test.js +56 -0
- package/dist/core/lsp/format.test.js.map +1 -0
- package/dist/core/lsp/integration.test.d.ts +2 -0
- package/dist/core/lsp/integration.test.d.ts.map +1 -0
- package/dist/core/lsp/integration.test.js +60 -0
- package/dist/core/lsp/integration.test.js.map +1 -0
- package/dist/core/lsp/jsonrpc.d.ts +32 -0
- package/dist/core/lsp/jsonrpc.d.ts.map +1 -0
- package/dist/core/lsp/jsonrpc.js +141 -0
- package/dist/core/lsp/jsonrpc.js.map +1 -0
- package/dist/core/lsp/jsonrpc.test.d.ts +2 -0
- package/dist/core/lsp/jsonrpc.test.d.ts.map +1 -0
- package/dist/core/lsp/jsonrpc.test.js +127 -0
- package/dist/core/lsp/jsonrpc.test.js.map +1 -0
- package/dist/core/lsp/manager.d.ts +40 -0
- package/dist/core/lsp/manager.d.ts.map +1 -0
- package/dist/core/lsp/manager.js +135 -0
- package/dist/core/lsp/manager.js.map +1 -0
- package/dist/core/lsp/manager.test.d.ts +2 -0
- package/dist/core/lsp/manager.test.d.ts.map +1 -0
- package/dist/core/lsp/manager.test.js +119 -0
- package/dist/core/lsp/manager.test.js.map +1 -0
- package/dist/core/lsp/servers.d.ts +45 -0
- package/dist/core/lsp/servers.d.ts.map +1 -0
- package/dist/core/lsp/servers.js +247 -0
- package/dist/core/lsp/servers.js.map +1 -0
- package/dist/core/settings-manager.d.ts +1 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +3 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/interactive.d.ts.map +1 -1
- package/dist/interactive.js +5 -2
- package/dist/interactive.js.map +1 -1
- package/dist/tools/edit.d.ts +3 -1
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +15 -3
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/edit.test.js +70 -0
- package/dist/tools/edit.test.js.map +1 -1
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +13 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/write.d.ts +3 -1
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +13 -2
- package/dist/tools/write.js.map +1 -1
- package/dist/tools/write.test.js +33 -0
- package/dist/tools/write.test.js.map +1 -1
- package/dist/ui/live-area-clamp.test.js +37 -0
- package/dist/ui/live-area-clamp.test.js.map +1 -1
- package/dist/ui/live-area-height.d.ts.map +1 -1
- package/dist/ui/live-area-height.js +10 -4
- package/dist/ui/live-area-height.js.map +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
import { JsonRpcConnection, JsonRpcRequestError } from "./jsonrpc.js";
|
|
4
|
+
import { getSafeToolEnv } from "../../tools/safe-env.js";
|
|
5
|
+
const SERVER_CANCELLED = -32802;
|
|
6
|
+
const METHOD_NOT_FOUND = -32601;
|
|
7
|
+
const PULL_POLL_INTERVAL_MS = 300;
|
|
8
|
+
const SHUTDOWN_TIMEOUT_MS = 2000;
|
|
9
|
+
const KILL_GRACE_MS = 1500;
|
|
10
|
+
function sleep(ms) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
setTimeout(resolve, ms).unref();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* One language-server process bound to one project root. Owns document sync
|
|
17
|
+
* (didOpen / didChange / didSave with per-uri version counters), the
|
|
18
|
+
* push-diagnostics cache, and LSP 3.17 pull diagnostics with the
|
|
19
|
+
* push-vs-pull race that the POC proved necessary for rust-analyzer.
|
|
20
|
+
*/
|
|
21
|
+
export class LspClient {
|
|
22
|
+
spec;
|
|
23
|
+
rootPath;
|
|
24
|
+
proc;
|
|
25
|
+
conn;
|
|
26
|
+
versions = new Map();
|
|
27
|
+
published = new Map();
|
|
28
|
+
waiters = [];
|
|
29
|
+
hasPullDiagnostics = false;
|
|
30
|
+
alive = true;
|
|
31
|
+
initializationOptions;
|
|
32
|
+
constructor(spec, rootPath, command) {
|
|
33
|
+
this.spec = spec;
|
|
34
|
+
this.rootPath = rootPath;
|
|
35
|
+
this.initializationOptions = command.initializationOptions ?? {};
|
|
36
|
+
this.proc = spawn(command.command, command.args, {
|
|
37
|
+
cwd: rootPath,
|
|
38
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
39
|
+
env: getSafeToolEnv(),
|
|
40
|
+
});
|
|
41
|
+
this.proc.on("error", () => this.markDead());
|
|
42
|
+
this.proc.on("exit", () => this.markDead());
|
|
43
|
+
const { stdout, stdin } = this.proc;
|
|
44
|
+
if (!stdout || !stdin) {
|
|
45
|
+
// Cannot happen with "pipe" stdio, but guard instead of asserting.
|
|
46
|
+
this.proc.kill("SIGKILL");
|
|
47
|
+
throw new Error(`failed to open stdio pipes for ${spec.id} language server`);
|
|
48
|
+
}
|
|
49
|
+
this.conn = new JsonRpcConnection(stdout, stdin);
|
|
50
|
+
this.conn.onNotification("textDocument/publishDiagnostics", (params) => {
|
|
51
|
+
const publish = params;
|
|
52
|
+
this.published.set(publish.uri, publish.diagnostics);
|
|
53
|
+
this.waiters = this.waiters.filter((waiter) => {
|
|
54
|
+
if (waiter.uri !== publish.uri)
|
|
55
|
+
return true;
|
|
56
|
+
waiter.resolve(publish.diagnostics);
|
|
57
|
+
return false;
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
get isAlive() {
|
|
62
|
+
return this.alive;
|
|
63
|
+
}
|
|
64
|
+
async initialize(timeoutMs) {
|
|
65
|
+
const rootUri = pathToFileURL(this.rootPath).href;
|
|
66
|
+
const result = (await this.conn.request("initialize", {
|
|
67
|
+
processId: process.pid,
|
|
68
|
+
rootUri,
|
|
69
|
+
workspaceFolders: [{ uri: rootUri, name: "ggcoder" }],
|
|
70
|
+
initializationOptions: this.initializationOptions,
|
|
71
|
+
capabilities: {
|
|
72
|
+
textDocument: {
|
|
73
|
+
synchronization: { didSave: true },
|
|
74
|
+
publishDiagnostics: { relatedInformation: false },
|
|
75
|
+
diagnostic: { dynamicRegistration: false, relatedDocumentSupport: false },
|
|
76
|
+
},
|
|
77
|
+
workspace: { configuration: true, workspaceFolders: true },
|
|
78
|
+
},
|
|
79
|
+
}, timeoutMs));
|
|
80
|
+
this.hasPullDiagnostics = Boolean(result?.capabilities?.diagnosticProvider);
|
|
81
|
+
this.conn.notify("initialized", {});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sync `content` into the server's overlay for `filePath` — didOpen the
|
|
85
|
+
* first time, didChange (full text) + didSave afterwards. Clears the
|
|
86
|
+
* push-diagnostics cache for the uri so a subsequent collect waits for a
|
|
87
|
+
* report computed against THIS content rather than a stale one.
|
|
88
|
+
*/
|
|
89
|
+
syncDocument(filePath, content) {
|
|
90
|
+
const uri = pathToFileURL(filePath).href;
|
|
91
|
+
this.published.delete(uri);
|
|
92
|
+
const previousVersion = this.versions.get(uri);
|
|
93
|
+
if (previousVersion === undefined) {
|
|
94
|
+
this.versions.set(uri, 1);
|
|
95
|
+
this.conn.notify("textDocument/didOpen", {
|
|
96
|
+
textDocument: {
|
|
97
|
+
uri,
|
|
98
|
+
languageId: this.spec.languageIdFor(extensionOf(filePath)),
|
|
99
|
+
version: 1,
|
|
100
|
+
text: content,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const version = previousVersion + 1;
|
|
106
|
+
this.versions.set(uri, version);
|
|
107
|
+
this.conn.notify("textDocument/didChange", {
|
|
108
|
+
textDocument: { uri, version },
|
|
109
|
+
contentChanges: [{ text: content }],
|
|
110
|
+
});
|
|
111
|
+
this.conn.notify("textDocument/didSave", { textDocument: { uri }, text: content });
|
|
112
|
+
}
|
|
113
|
+
return uri;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Current diagnostics for `uri`, racing the push channel (next
|
|
117
|
+
* publishDiagnostics after the last sync) against a pull-diagnostics poll
|
|
118
|
+
* loop when the server supports LSP 3.17 pull. Returns null on timeout.
|
|
119
|
+
*/
|
|
120
|
+
async collectDiagnostics(uri, timeoutMs) {
|
|
121
|
+
const push = this.waitForPublish(uri, timeoutMs);
|
|
122
|
+
if (!this.hasPullDiagnostics)
|
|
123
|
+
return push;
|
|
124
|
+
let stopped = false;
|
|
125
|
+
const pull = (async () => {
|
|
126
|
+
const deadline = Date.now() + timeoutMs;
|
|
127
|
+
while (!stopped && this.alive && Date.now() < deadline) {
|
|
128
|
+
const items = await this.pullDiagnostics(uri, Math.max(1, deadline - Date.now()));
|
|
129
|
+
if (items === "unsupported")
|
|
130
|
+
return push;
|
|
131
|
+
if (items !== "retry")
|
|
132
|
+
return items;
|
|
133
|
+
await sleep(PULL_POLL_INTERVAL_MS);
|
|
134
|
+
}
|
|
135
|
+
return push;
|
|
136
|
+
})();
|
|
137
|
+
try {
|
|
138
|
+
return await Promise.race([push, pull]);
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
stopped = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Graceful shutdown/exit handshake with SIGKILL fallback. Synchronous so it
|
|
146
|
+
* is safe inside `process.on("exit")` handlers: the shutdown request and
|
|
147
|
+
* exit notification are written immediately; the SIGKILL timer covers
|
|
148
|
+
* servers that ignore them (and stdin EOF reaps them when we die first).
|
|
149
|
+
*/
|
|
150
|
+
shutdown() {
|
|
151
|
+
if (!this.alive)
|
|
152
|
+
return;
|
|
153
|
+
void this.conn.request("shutdown", null, SHUTDOWN_TIMEOUT_MS).catch(() => { });
|
|
154
|
+
this.conn.notify("exit");
|
|
155
|
+
const killTimer = setTimeout(() => {
|
|
156
|
+
if (this.alive)
|
|
157
|
+
this.proc.kill("SIGKILL");
|
|
158
|
+
}, KILL_GRACE_MS);
|
|
159
|
+
killTimer.unref();
|
|
160
|
+
}
|
|
161
|
+
markDead() {
|
|
162
|
+
this.alive = false;
|
|
163
|
+
this.conn.dispose();
|
|
164
|
+
const waiters = this.waiters;
|
|
165
|
+
this.waiters = [];
|
|
166
|
+
for (const waiter of waiters)
|
|
167
|
+
waiter.resolve([]);
|
|
168
|
+
}
|
|
169
|
+
waitForPublish(uri, timeoutMs) {
|
|
170
|
+
const cached = this.published.get(uri);
|
|
171
|
+
if (cached !== undefined)
|
|
172
|
+
return Promise.resolve(cached);
|
|
173
|
+
if (!this.alive)
|
|
174
|
+
return Promise.resolve(null);
|
|
175
|
+
return new Promise((resolve) => {
|
|
176
|
+
const waiter = {
|
|
177
|
+
uri,
|
|
178
|
+
resolve: (diagnostics) => {
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
resolve(diagnostics);
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
const timer = setTimeout(() => {
|
|
184
|
+
this.waiters = this.waiters.filter((w) => w !== waiter);
|
|
185
|
+
resolve(null);
|
|
186
|
+
}, timeoutMs);
|
|
187
|
+
timer.unref();
|
|
188
|
+
this.waiters.push(waiter);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
async pullDiagnostics(uri, timeoutMs) {
|
|
192
|
+
try {
|
|
193
|
+
const report = (await this.conn.request("textDocument/diagnostic", { textDocument: { uri } }, timeoutMs));
|
|
194
|
+
if (report?.kind === "full")
|
|
195
|
+
return report.items ?? [];
|
|
196
|
+
if (report?.kind === "unchanged")
|
|
197
|
+
return this.published.get(uri) ?? [];
|
|
198
|
+
return "unsupported";
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
if (error instanceof JsonRpcRequestError) {
|
|
202
|
+
if (error.code === SERVER_CANCELLED)
|
|
203
|
+
return "retry";
|
|
204
|
+
if (error.code === METHOD_NOT_FOUND)
|
|
205
|
+
return "unsupported";
|
|
206
|
+
}
|
|
207
|
+
return "unsupported";
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
function extensionOf(filePath) {
|
|
212
|
+
const dot = filePath.lastIndexOf(".");
|
|
213
|
+
return dot === -1 ? "" : filePath.slice(dot).toLowerCase();
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/core/lsp/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { LspDiagnostic } from "./client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Render error-severity diagnostics for appending to an edit/write tool
|
|
4
|
+
* result. Empty string when the file has no errors — clean edits stay
|
|
5
|
+
* byte-identical to today's tool output.
|
|
6
|
+
*
|
|
7
|
+
* The header frames the list as informational so the model isn't baited into
|
|
8
|
+
* premature fixes mid-way through a multi-file change (a cross-file error can
|
|
9
|
+
* legitimately resolve once the related edit lands).
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatDiagnostics(relPath: string, diagnostics: LspDiagnostic[]): string;
|
|
12
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,MAAM,CAqBvF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const SEVERITY_ERROR = 1;
|
|
2
|
+
const MAX_DIAGNOSTICS = 5;
|
|
3
|
+
/**
|
|
4
|
+
* Render error-severity diagnostics for appending to an edit/write tool
|
|
5
|
+
* result. Empty string when the file has no errors — clean edits stay
|
|
6
|
+
* byte-identical to today's tool output.
|
|
7
|
+
*
|
|
8
|
+
* The header frames the list as informational so the model isn't baited into
|
|
9
|
+
* premature fixes mid-way through a multi-file change (a cross-file error can
|
|
10
|
+
* legitimately resolve once the related edit lands).
|
|
11
|
+
*/
|
|
12
|
+
export function formatDiagnostics(relPath, diagnostics) {
|
|
13
|
+
const errors = diagnostics.filter((d) => (d.severity ?? SEVERITY_ERROR) === SEVERITY_ERROR);
|
|
14
|
+
if (errors.length === 0)
|
|
15
|
+
return "";
|
|
16
|
+
const lines = errors.slice(0, MAX_DIAGNOSTICS).map((d) => {
|
|
17
|
+
const line = d.range.start.line + 1;
|
|
18
|
+
const character = d.range.start.character + 1;
|
|
19
|
+
const message = d.message.split("\n")[0];
|
|
20
|
+
const source = d.source ? ` (${d.source})` : "";
|
|
21
|
+
return `L${line}:${character} ${message}${source}`;
|
|
22
|
+
});
|
|
23
|
+
const overflow = errors.length > MAX_DIAGNOSTICS
|
|
24
|
+
? `\n…and ${errors.length - MAX_DIAGNOSTICS} more error${errors.length - MAX_DIAGNOSTICS === 1 ? "" : "s"}`
|
|
25
|
+
: "";
|
|
26
|
+
return (`\n\nDiagnostics in ${relPath} (informational — may resolve after related edits):\n` +
|
|
27
|
+
lines.join("\n") +
|
|
28
|
+
overflow);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/core/lsp/format.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,CAAC,CAAC;AACzB,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,WAA4B;IAC7E,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,cAAc,CAAC,KAAK,cAAc,CAAC,CAAC;IAC5F,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,IAAI,IAAI,SAAS,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;IACH,MAAM,QAAQ,GACZ,MAAM,CAAC,MAAM,GAAG,eAAe;QAC7B,CAAC,CAAC,UAAU,MAAM,CAAC,MAAM,GAAG,eAAe,cAAc,MAAM,CAAC,MAAM,GAAG,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE;QAC3G,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,CACL,sBAAsB,OAAO,uDAAuD;QACpF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAChB,QAAQ,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/format.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { formatDiagnostics } from "./format.js";
|
|
3
|
+
function diag(overrides) {
|
|
4
|
+
return {
|
|
5
|
+
range: { start: { line: 0, character: 0 }, end: { line: 0, character: 1 } },
|
|
6
|
+
severity: 1,
|
|
7
|
+
...overrides,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
describe("formatDiagnostics", () => {
|
|
11
|
+
it("returns empty string for a clean file", () => {
|
|
12
|
+
expect(formatDiagnostics("src/a.ts", [])).toBe("");
|
|
13
|
+
});
|
|
14
|
+
it("filters out warnings, info, and hints", () => {
|
|
15
|
+
const diagnostics = [
|
|
16
|
+
diag({ message: "warn", severity: 2 }),
|
|
17
|
+
diag({ message: "info", severity: 3 }),
|
|
18
|
+
diag({ message: "hint", severity: 4 }),
|
|
19
|
+
];
|
|
20
|
+
expect(formatDiagnostics("src/a.ts", diagnostics)).toBe("");
|
|
21
|
+
});
|
|
22
|
+
it("renders errors with 1-based line:column, message, and source", () => {
|
|
23
|
+
const diagnostics = [
|
|
24
|
+
diag({
|
|
25
|
+
message: "Type 'string' is not assignable to type 'number'.",
|
|
26
|
+
range: { start: { line: 41, character: 6 }, end: { line: 41, character: 10 } },
|
|
27
|
+
source: "typescript",
|
|
28
|
+
}),
|
|
29
|
+
];
|
|
30
|
+
const result = formatDiagnostics("src/a.ts", diagnostics);
|
|
31
|
+
expect(result).toContain("Diagnostics in src/a.ts (informational — may resolve after related edits):");
|
|
32
|
+
expect(result).toContain("L42:7 Type 'string' is not assignable to type 'number'. (typescript)");
|
|
33
|
+
expect(result.startsWith("\n\n")).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
it("treats missing severity as an error", () => {
|
|
36
|
+
const result = formatDiagnostics("a.py", [diag({ message: "boom", severity: undefined })]);
|
|
37
|
+
expect(result).toContain("L1:1 boom");
|
|
38
|
+
});
|
|
39
|
+
it("keeps only the first line of multi-line messages", () => {
|
|
40
|
+
const result = formatDiagnostics("a.rs", [diag({ message: "first line\nsecond line" })]);
|
|
41
|
+
expect(result).toContain("first line");
|
|
42
|
+
expect(result).not.toContain("second line");
|
|
43
|
+
});
|
|
44
|
+
it("caps output at 5 errors and reports the overflow count", () => {
|
|
45
|
+
const diagnostics = Array.from({ length: 8 }, (_, i) => diag({ message: `error ${i}` }));
|
|
46
|
+
const result = formatDiagnostics("src/a.ts", diagnostics);
|
|
47
|
+
expect(result).toContain("error 4");
|
|
48
|
+
expect(result).not.toContain("error 5");
|
|
49
|
+
expect(result).toContain("…and 3 more errors");
|
|
50
|
+
});
|
|
51
|
+
it("uses singular overflow wording for exactly one extra error", () => {
|
|
52
|
+
const diagnostics = Array.from({ length: 6 }, (_, i) => diag({ message: `error ${i}` }));
|
|
53
|
+
expect(formatDiagnostics("src/a.ts", diagnostics)).toContain("…and 1 more error");
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=format.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.test.js","sourceRoot":"","sources":["../../../src/core/lsp/format.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/integration.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from "vitest";
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import { LspManager } from "./manager.js";
|
|
7
|
+
import { findExecutable } from "./servers.js";
|
|
8
|
+
/**
|
|
9
|
+
* Opt-in integration test against a REAL typescript-language-server:
|
|
10
|
+
*
|
|
11
|
+
* GG_LSP_INTEGRATION=1 npx vitest run src/core/lsp/integration.test.ts
|
|
12
|
+
*
|
|
13
|
+
* Skipped in CI and normal runs. Self-contained: when the server binary isn't
|
|
14
|
+
* already on PATH it is npm-installed into the throwaway temp project (this
|
|
15
|
+
* is a local, explicitly opted-in test — the production runtime NEVER
|
|
16
|
+
* installs anything).
|
|
17
|
+
*/
|
|
18
|
+
const enabled = process.env.GG_LSP_INTEGRATION === "1";
|
|
19
|
+
describe.skipIf(!enabled)("LspManager + real typescript-language-server", () => {
|
|
20
|
+
let tmpDir;
|
|
21
|
+
let manager;
|
|
22
|
+
beforeAll(async () => {
|
|
23
|
+
tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "lsp-integration-"));
|
|
24
|
+
await fs.writeFile(path.join(tmpDir, "tsconfig.json"), JSON.stringify({
|
|
25
|
+
compilerOptions: {
|
|
26
|
+
strict: true,
|
|
27
|
+
module: "esnext",
|
|
28
|
+
moduleResolution: "bundler",
|
|
29
|
+
target: "es2022",
|
|
30
|
+
},
|
|
31
|
+
include: ["src"],
|
|
32
|
+
}));
|
|
33
|
+
await fs.mkdir(path.join(tmpDir, "src"));
|
|
34
|
+
await fs.writeFile(path.join(tmpDir, "package.json"), JSON.stringify({ name: "lsp-it", private: true }));
|
|
35
|
+
const install = spawnSync("npm", ["install", "--no-audit", "--no-fund", "typescript", "typescript-language-server"], { cwd: tmpDir, stdio: "pipe", timeout: 110_000 });
|
|
36
|
+
expect(install.status).toBe(0);
|
|
37
|
+
expect(findExecutable("typescript-language-server", tmpDir)).not.toBeNull();
|
|
38
|
+
manager = new LspManager(tmpDir, { firstBudgetMs: 30_000, warmBudgetMs: 10_000 });
|
|
39
|
+
}, 120_000);
|
|
40
|
+
afterAll(async () => {
|
|
41
|
+
manager.shutdownAll();
|
|
42
|
+
await fs.rm(tmpDir, { recursive: true, force: true });
|
|
43
|
+
});
|
|
44
|
+
it("reports a type error, clears on fix, and reports a re-break", async () => {
|
|
45
|
+
const filePath = path.join(tmpDir, "src", "main.ts");
|
|
46
|
+
const broken = 'export const n: number = "not a number";\n';
|
|
47
|
+
await fs.writeFile(filePath, broken);
|
|
48
|
+
const first = await manager.diagnosticsAfterWrite(filePath, broken);
|
|
49
|
+
expect(first).toContain("Diagnostics in");
|
|
50
|
+
expect(first).toMatch(/not assignable to type 'number'/);
|
|
51
|
+
const fixed = "export const n: number = 42;\n";
|
|
52
|
+
await fs.writeFile(filePath, fixed);
|
|
53
|
+
expect(await manager.diagnosticsAfterWrite(filePath, fixed)).toBe("");
|
|
54
|
+
const rebroken = "export const n: number = 42;\nexport const x = n.doesNotExist;\n";
|
|
55
|
+
await fs.writeFile(filePath, rebroken);
|
|
56
|
+
const third = await manager.diagnosticsAfterWrite(filePath, rebroken);
|
|
57
|
+
expect(third).toMatch(/doesNotExist/);
|
|
58
|
+
}, 60_000);
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration.test.js","sourceRoot":"","sources":["../../../src/core/lsp/integration.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Readable, Writable } from "node:stream";
|
|
2
|
+
export declare class JsonRpcRequestError extends Error {
|
|
3
|
+
readonly code: number;
|
|
4
|
+
constructor(method: string, code: number, message: string);
|
|
5
|
+
}
|
|
6
|
+
export type NotificationHandler = (params: unknown) => void;
|
|
7
|
+
/**
|
|
8
|
+
* JSON-RPC connection speaking Content-Length framed messages.
|
|
9
|
+
*
|
|
10
|
+
* Server→client REQUESTS are auto-replied with safe defaults so language
|
|
11
|
+
* servers never stall waiting on us: `workspace/configuration` gets one null
|
|
12
|
+
* per requested item; everything else (`client/registerCapability`,
|
|
13
|
+
* `window/workDoneProgress/create`, …) gets a plain null result.
|
|
14
|
+
*/
|
|
15
|
+
export declare class JsonRpcConnection {
|
|
16
|
+
private readonly output;
|
|
17
|
+
private buffer;
|
|
18
|
+
private nextId;
|
|
19
|
+
private readonly pending;
|
|
20
|
+
private readonly notificationHandlers;
|
|
21
|
+
private disposed;
|
|
22
|
+
constructor(input: Readable, output: Writable);
|
|
23
|
+
onNotification(method: string, handler: NotificationHandler): void;
|
|
24
|
+
request(method: string, params: unknown, timeoutMs: number): Promise<unknown>;
|
|
25
|
+
notify(method: string, params?: unknown): void;
|
|
26
|
+
/** Reject all in-flight requests and stop accepting new work. */
|
|
27
|
+
dispose(): void;
|
|
28
|
+
private send;
|
|
29
|
+
private onData;
|
|
30
|
+
private onMessage;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=jsonrpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/jsonrpc.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAkBtD,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAEV,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK1D;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;AAI5D;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAS1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IARzB,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoD;IAC5E,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA4C;IACjF,OAAO,CAAC,QAAQ,CAAS;gBAGvB,KAAK,EAAE,QAAQ,EACE,MAAM,EAAE,QAAQ;IAOnC,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAMlE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB7E,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAI9C,iEAAiE;IACjE,OAAO,IAAI,IAAI;IASf,OAAO,CAAC,IAAI;IAUZ,OAAO,CAAC,MAAM;IA0Bd,OAAO,CAAC,SAAS;CA4BlB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export class JsonRpcRequestError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(method, code, message) {
|
|
4
|
+
super(`${method}: ${message} (code ${code})`);
|
|
5
|
+
this.name = "JsonRpcRequestError";
|
|
6
|
+
this.code = code;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const HEADER_SEPARATOR = "\r\n\r\n";
|
|
10
|
+
/**
|
|
11
|
+
* JSON-RPC connection speaking Content-Length framed messages.
|
|
12
|
+
*
|
|
13
|
+
* Server→client REQUESTS are auto-replied with safe defaults so language
|
|
14
|
+
* servers never stall waiting on us: `workspace/configuration` gets one null
|
|
15
|
+
* per requested item; everything else (`client/registerCapability`,
|
|
16
|
+
* `window/workDoneProgress/create`, …) gets a plain null result.
|
|
17
|
+
*/
|
|
18
|
+
export class JsonRpcConnection {
|
|
19
|
+
output;
|
|
20
|
+
buffer = Buffer.alloc(0);
|
|
21
|
+
nextId = 1;
|
|
22
|
+
pending = new Map();
|
|
23
|
+
notificationHandlers = new Map();
|
|
24
|
+
disposed = false;
|
|
25
|
+
constructor(input, output) {
|
|
26
|
+
this.output = output;
|
|
27
|
+
input.on("data", (chunk) => this.onData(chunk));
|
|
28
|
+
// Writing to a dead server's stdin must never crash the host process.
|
|
29
|
+
output.on("error", () => { });
|
|
30
|
+
}
|
|
31
|
+
onNotification(method, handler) {
|
|
32
|
+
const handlers = this.notificationHandlers.get(method) ?? [];
|
|
33
|
+
handlers.push(handler);
|
|
34
|
+
this.notificationHandlers.set(method, handlers);
|
|
35
|
+
}
|
|
36
|
+
request(method, params, timeoutMs) {
|
|
37
|
+
if (this.disposed) {
|
|
38
|
+
return Promise.reject(new JsonRpcRequestError(method, -32099, "connection disposed"));
|
|
39
|
+
}
|
|
40
|
+
const id = this.nextId++;
|
|
41
|
+
return new Promise((resolve, reject) => {
|
|
42
|
+
const timer = setTimeout(() => {
|
|
43
|
+
this.pending.delete(id);
|
|
44
|
+
reject(new JsonRpcRequestError(method, -32803, `timed out after ${timeoutMs}ms`));
|
|
45
|
+
}, timeoutMs);
|
|
46
|
+
timer.unref();
|
|
47
|
+
this.pending.set(id, (msg) => {
|
|
48
|
+
clearTimeout(timer);
|
|
49
|
+
if (msg.error) {
|
|
50
|
+
reject(new JsonRpcRequestError(method, msg.error.code, msg.error.message));
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
resolve(msg.result);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
this.send({ jsonrpc: "2.0", id, method, params });
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
notify(method, params) {
|
|
60
|
+
this.send({ jsonrpc: "2.0", method, params });
|
|
61
|
+
}
|
|
62
|
+
/** Reject all in-flight requests and stop accepting new work. */
|
|
63
|
+
dispose() {
|
|
64
|
+
if (this.disposed)
|
|
65
|
+
return;
|
|
66
|
+
this.disposed = true;
|
|
67
|
+
for (const [id, settle] of this.pending) {
|
|
68
|
+
this.pending.delete(id);
|
|
69
|
+
settle({ error: { code: -32099, message: "connection disposed" } });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
send(msg) {
|
|
73
|
+
if (this.disposed)
|
|
74
|
+
return;
|
|
75
|
+
const body = JSON.stringify(msg);
|
|
76
|
+
try {
|
|
77
|
+
this.output.write(`Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Server stdin already closed — degradation is handled by the caller.
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
onData(chunk) {
|
|
84
|
+
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
85
|
+
for (;;) {
|
|
86
|
+
const headerEnd = this.buffer.indexOf(HEADER_SEPARATOR);
|
|
87
|
+
if (headerEnd === -1)
|
|
88
|
+
return;
|
|
89
|
+
const header = this.buffer.subarray(0, headerEnd).toString();
|
|
90
|
+
const match = /Content-Length: (\d+)/i.exec(header);
|
|
91
|
+
if (!match) {
|
|
92
|
+
this.buffer = this.buffer.subarray(headerEnd + HEADER_SEPARATOR.length);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const length = Number(match[1]);
|
|
96
|
+
const bodyStart = headerEnd + HEADER_SEPARATOR.length;
|
|
97
|
+
if (this.buffer.length < bodyStart + length)
|
|
98
|
+
return;
|
|
99
|
+
const body = this.buffer.subarray(bodyStart, bodyStart + length).toString();
|
|
100
|
+
this.buffer = this.buffer.subarray(bodyStart + length);
|
|
101
|
+
let msg;
|
|
102
|
+
try {
|
|
103
|
+
msg = JSON.parse(body);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
this.onMessage(msg);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
onMessage(msg) {
|
|
112
|
+
// Response to one of our requests.
|
|
113
|
+
if (msg.id !== undefined && msg.method === undefined) {
|
|
114
|
+
const settle = typeof msg.id === "number" ? this.pending.get(msg.id) : undefined;
|
|
115
|
+
if (settle && typeof msg.id === "number") {
|
|
116
|
+
this.pending.delete(msg.id);
|
|
117
|
+
settle(msg);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
// Server→client request: auto-reply with safe defaults.
|
|
122
|
+
if (msg.id !== undefined && msg.method !== undefined) {
|
|
123
|
+
let result = null;
|
|
124
|
+
if (msg.method === "workspace/configuration") {
|
|
125
|
+
const items = msg.params?.items ?? [];
|
|
126
|
+
result = items.map(() => null);
|
|
127
|
+
}
|
|
128
|
+
this.send({ jsonrpc: "2.0", id: msg.id, result });
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// Notification.
|
|
132
|
+
if (msg.method !== undefined) {
|
|
133
|
+
const handlers = this.notificationHandlers.get(msg.method);
|
|
134
|
+
if (handlers) {
|
|
135
|
+
for (const handler of handlers)
|
|
136
|
+
handler(msg.params);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=jsonrpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.js","sourceRoot":"","sources":["../../../src/core/lsp/jsonrpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.test.d.ts","sourceRoot":"","sources":["../../../src/core/lsp/jsonrpc.test.ts"],"names":[],"mappings":""}
|