@theupsider/lsp-mcp 1.0.1 → 1.0.7
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/lsp/lifecycle-manager.js +22 -7
- package/dist/lsp/lsp-client.js +57 -4
- package/dist/lsp/server-supervisor.js +17 -18
- package/dist/mcp/__tests__/read-tools.test.js +354 -146
- package/dist/mcp/__tests__/write-tools.test.js +218 -104
- package/dist/mcp/formatters.js +109 -91
- package/dist/mcp/server.js +30 -14
- package/dist/mcp/tools/read-tools.js +104 -58
- package/dist/mcp/tools/shared.js +19 -11
- package/package.json +1 -1
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const promises_1 = require("node:fs/promises");
|
|
4
4
|
const write_tools_1 = require("../tools/write-tools");
|
|
5
|
-
jest.mock(
|
|
5
|
+
jest.mock("node:fs/promises", () => ({
|
|
6
6
|
access: jest.fn(),
|
|
7
7
|
readFile: jest.fn(),
|
|
8
|
-
writeFile: jest.fn()
|
|
8
|
+
writeFile: jest.fn(),
|
|
9
9
|
}));
|
|
10
10
|
class FakeRegistrar {
|
|
11
11
|
tools = new Map();
|
|
@@ -13,149 +13,230 @@ class FakeRegistrar {
|
|
|
13
13
|
this.tools.set(name, { handler });
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
describe(
|
|
16
|
+
describe("registerWriteTools", () => {
|
|
17
17
|
beforeEach(() => {
|
|
18
18
|
jest.clearAllMocks();
|
|
19
19
|
promises_1.access.mockResolvedValue(undefined);
|
|
20
20
|
promises_1.readFile.mockImplementation(async (filePath) => {
|
|
21
21
|
const pathText = String(filePath);
|
|
22
|
-
if (pathText.endsWith(
|
|
23
|
-
return
|
|
22
|
+
if (pathText.endsWith(".editorconfig")) {
|
|
23
|
+
return "root = true\n[*]\nindent_size = 2\nindent_style = space\n";
|
|
24
24
|
}
|
|
25
|
-
return
|
|
25
|
+
return "const foo = oldName\n";
|
|
26
26
|
});
|
|
27
27
|
promises_1.writeFile.mockResolvedValue(undefined);
|
|
28
28
|
});
|
|
29
|
-
it(
|
|
29
|
+
it("renames symbols when the server supports rename and saves the changed file", async () => {
|
|
30
30
|
const registrar = new FakeRegistrar();
|
|
31
31
|
const client = createClient({
|
|
32
32
|
changes: {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
"file:///workspace/src/index.ts": [
|
|
34
|
+
{
|
|
35
|
+
range: {
|
|
36
|
+
start: { line: 0, character: 12 },
|
|
37
|
+
end: { line: 0, character: 19 },
|
|
38
|
+
},
|
|
39
|
+
newText: "newName",
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
35
43
|
});
|
|
36
44
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
37
|
-
const result = await getHandler(registrar,
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
const result = await getHandler(registrar, "lsp_rename")({
|
|
46
|
+
file: "/workspace/src/index.ts",
|
|
47
|
+
line: 0,
|
|
48
|
+
character: 12,
|
|
49
|
+
newName: "newName",
|
|
50
|
+
});
|
|
51
|
+
expect(client.request).toHaveBeenCalledWith("textDocument/rename", {
|
|
52
|
+
textDocument: { uri: "file:///workspace/src/index.ts" },
|
|
40
53
|
position: { line: 0, character: 12 },
|
|
41
|
-
newName:
|
|
54
|
+
newName: "newName",
|
|
42
55
|
}, 15000);
|
|
43
|
-
expect(promises_1.writeFile).toHaveBeenCalledWith(
|
|
44
|
-
expect(client.notify).toHaveBeenCalledWith(
|
|
56
|
+
expect(promises_1.writeFile).toHaveBeenCalledWith("/workspace/src/index.ts", "const foo = newName\n", "utf8");
|
|
57
|
+
expect(client.notify).toHaveBeenCalledWith("textDocument/didSave", {
|
|
58
|
+
textDocument: { uri: "file:///workspace/src/index.ts" },
|
|
59
|
+
});
|
|
45
60
|
expect(result).toEqual({
|
|
46
|
-
content: [{ type:
|
|
47
|
-
raw: { changedFiles: [
|
|
61
|
+
content: [{ type: "text", text: "Applied workspace edit to 1 file(s)" }],
|
|
62
|
+
raw: { changedFiles: ["/workspace/src/index.ts"] },
|
|
48
63
|
});
|
|
49
64
|
});
|
|
50
|
-
it(
|
|
65
|
+
it("returns an error when rename is unsupported", async () => {
|
|
51
66
|
const registrar = new FakeRegistrar();
|
|
52
67
|
const client = createClient(null, { renameProvider: false });
|
|
53
68
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
54
|
-
await expect(getHandler(registrar,
|
|
55
|
-
|
|
69
|
+
await expect(getHandler(registrar, "lsp_rename")({
|
|
70
|
+
file: "/workspace/src/index.ts",
|
|
71
|
+
line: 0,
|
|
72
|
+
character: 0,
|
|
73
|
+
newName: "x",
|
|
74
|
+
})).resolves.toEqual({
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: "text",
|
|
78
|
+
text: "Rename is not supported by the active language server.",
|
|
79
|
+
},
|
|
80
|
+
],
|
|
56
81
|
error: true,
|
|
57
|
-
raw: null
|
|
82
|
+
raw: null,
|
|
58
83
|
});
|
|
59
84
|
});
|
|
60
|
-
it(
|
|
85
|
+
it("lists code actions without applying them", async () => {
|
|
61
86
|
const registrar = new FakeRegistrar();
|
|
62
|
-
const actions = [{ title:
|
|
87
|
+
const actions = [{ title: "Fix import", kind: "quickfix" }];
|
|
63
88
|
const client = createClient(actions);
|
|
64
89
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
65
|
-
await expect(getHandler(registrar,
|
|
66
|
-
content: [
|
|
67
|
-
|
|
90
|
+
await expect(getHandler(registrar, "lsp_code_action")({ file: "/workspace/src/index.ts", line: 0, character: 0 })).resolves.toEqual({
|
|
91
|
+
content: [
|
|
92
|
+
{ type: "text", text: "Available code actions:\n- [0] Fix import" },
|
|
93
|
+
],
|
|
94
|
+
raw: actions,
|
|
68
95
|
});
|
|
69
96
|
expect(promises_1.writeFile).not.toHaveBeenCalled();
|
|
70
97
|
});
|
|
71
|
-
it(
|
|
98
|
+
it("applies the selected code action edit and command", async () => {
|
|
72
99
|
const registrar = new FakeRegistrar();
|
|
73
100
|
const client = createClient([
|
|
74
101
|
{
|
|
75
|
-
title:
|
|
102
|
+
title: "Fix import",
|
|
76
103
|
edit: {
|
|
77
104
|
changes: {
|
|
78
|
-
|
|
79
|
-
|
|
105
|
+
"file:///workspace/src/index.ts": [
|
|
106
|
+
{
|
|
107
|
+
range: {
|
|
108
|
+
start: { line: 0, character: 0 },
|
|
109
|
+
end: { line: 0, character: 5 },
|
|
110
|
+
},
|
|
111
|
+
newText: "let",
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
},
|
|
80
115
|
},
|
|
81
|
-
command: { command:
|
|
82
|
-
}
|
|
116
|
+
command: { command: "workspace.applyFix", arguments: ["x"] },
|
|
117
|
+
},
|
|
83
118
|
]);
|
|
84
119
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
85
|
-
const result = await getHandler(registrar,
|
|
86
|
-
expect(client.request).toHaveBeenCalledWith(
|
|
120
|
+
const result = await getHandler(registrar, "lsp_code_action")({ file: "/workspace/src/index.ts", line: 0, character: 0, apply: true });
|
|
121
|
+
expect(client.request).toHaveBeenCalledWith("workspace/executeCommand", { command: "workspace.applyFix", arguments: ["x"] }, 15000);
|
|
87
122
|
expect(result).toEqual({
|
|
88
|
-
content: [{ type:
|
|
89
|
-
raw: { title:
|
|
123
|
+
content: [{ type: "text", text: "Applied code action: Fix import" }],
|
|
124
|
+
raw: { title: "Fix import", changedFiles: ["/workspace/src/index.ts"] },
|
|
90
125
|
});
|
|
91
126
|
});
|
|
92
|
-
it(
|
|
127
|
+
it("formats a file using editorconfig defaults", async () => {
|
|
93
128
|
const registrar = new FakeRegistrar();
|
|
94
|
-
const client = createClient([
|
|
129
|
+
const client = createClient([
|
|
130
|
+
{
|
|
131
|
+
range: {
|
|
132
|
+
start: { line: 0, character: 0 },
|
|
133
|
+
end: { line: 0, character: 21 },
|
|
134
|
+
},
|
|
135
|
+
newText: "const foo = oldName;\n",
|
|
136
|
+
},
|
|
137
|
+
]);
|
|
95
138
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
96
|
-
await getHandler(registrar,
|
|
97
|
-
expect(client.request).toHaveBeenCalledWith(
|
|
98
|
-
textDocument: { uri:
|
|
99
|
-
options: { tabSize: 2, insertSpaces: true }
|
|
139
|
+
await getHandler(registrar, "lsp_formatting")({ file: "/workspace/src/index.ts" });
|
|
140
|
+
expect(client.request).toHaveBeenCalledWith("textDocument/formatting", {
|
|
141
|
+
textDocument: { uri: "file:///workspace/src/index.ts" },
|
|
142
|
+
options: { tabSize: 2, insertSpaces: true },
|
|
100
143
|
}, 15000);
|
|
101
144
|
});
|
|
102
|
-
it(
|
|
145
|
+
it("formats a range with explicit options", async () => {
|
|
103
146
|
const registrar = new FakeRegistrar();
|
|
104
|
-
const client = createClient([
|
|
147
|
+
const client = createClient([
|
|
148
|
+
{
|
|
149
|
+
range: {
|
|
150
|
+
start: { line: 0, character: 0 },
|
|
151
|
+
end: { line: 0, character: 21 },
|
|
152
|
+
},
|
|
153
|
+
newText: "const foo = oldName;\n",
|
|
154
|
+
},
|
|
155
|
+
]);
|
|
105
156
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
106
|
-
await getHandler(registrar,
|
|
107
|
-
file:
|
|
108
|
-
range: {
|
|
109
|
-
|
|
157
|
+
await getHandler(registrar, "lsp_range_formatting")({
|
|
158
|
+
file: "/workspace/src/index.ts",
|
|
159
|
+
range: {
|
|
160
|
+
start: { line: 0, character: 0 },
|
|
161
|
+
end: { line: 0, character: 21 },
|
|
162
|
+
},
|
|
163
|
+
options: { tabSize: 4, insertSpaces: false },
|
|
110
164
|
});
|
|
111
|
-
expect(client.request).toHaveBeenCalledWith(
|
|
112
|
-
textDocument: { uri:
|
|
113
|
-
range: {
|
|
114
|
-
|
|
165
|
+
expect(client.request).toHaveBeenCalledWith("textDocument/rangeFormatting", {
|
|
166
|
+
textDocument: { uri: "file:///workspace/src/index.ts" },
|
|
167
|
+
range: {
|
|
168
|
+
start: { line: 0, character: 0 },
|
|
169
|
+
end: { line: 0, character: 21 },
|
|
170
|
+
},
|
|
171
|
+
options: { tabSize: 4, insertSpaces: false },
|
|
115
172
|
}, 15000);
|
|
116
173
|
});
|
|
117
|
-
it(
|
|
174
|
+
it("applies a raw workspace edit across files", async () => {
|
|
118
175
|
const registrar = new FakeRegistrar();
|
|
119
176
|
const client = createClient(null);
|
|
120
177
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
121
178
|
const edit = {
|
|
122
179
|
changes: {
|
|
123
|
-
|
|
124
|
-
|
|
180
|
+
"file:///workspace/src/index.ts": [
|
|
181
|
+
{
|
|
182
|
+
range: {
|
|
183
|
+
start: { line: 0, character: 6 },
|
|
184
|
+
end: { line: 0, character: 9 },
|
|
185
|
+
},
|
|
186
|
+
newText: "bar",
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
},
|
|
125
190
|
};
|
|
126
|
-
await expect(getHandler(registrar,
|
|
127
|
-
content: [{ type:
|
|
128
|
-
raw: { changedFiles: [
|
|
191
|
+
await expect(getHandler(registrar, "lsp_apply_workspace_edit")({ edit })).resolves.toEqual({
|
|
192
|
+
content: [{ type: "text", text: "Applied workspace edit to 1 file(s)" }],
|
|
193
|
+
raw: { changedFiles: ["/workspace/src/index.ts"] },
|
|
129
194
|
});
|
|
130
195
|
});
|
|
131
|
-
it(
|
|
196
|
+
it("supports indexed code actions, empty edits, and document changes", async () => {
|
|
132
197
|
const registrar = new FakeRegistrar();
|
|
133
198
|
const client = createClient([
|
|
134
|
-
{ title:
|
|
199
|
+
{ title: "Skip me" },
|
|
135
200
|
{
|
|
136
|
-
title:
|
|
201
|
+
title: "Apply me",
|
|
137
202
|
edit: {
|
|
138
203
|
documentChanges: [
|
|
139
204
|
{
|
|
140
|
-
textDocument: {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
205
|
+
textDocument: {
|
|
206
|
+
uri: "file:///workspace/src/index.ts",
|
|
207
|
+
version: 1,
|
|
208
|
+
},
|
|
209
|
+
edits: [
|
|
210
|
+
{
|
|
211
|
+
range: {
|
|
212
|
+
start: { line: 0, character: 6 },
|
|
213
|
+
end: { line: 0, character: 9 },
|
|
214
|
+
},
|
|
215
|
+
newText: "bar",
|
|
216
|
+
},
|
|
217
|
+
],
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
},
|
|
146
222
|
]);
|
|
147
223
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
148
|
-
await expect(getHandler(registrar,
|
|
149
|
-
|
|
150
|
-
|
|
224
|
+
await expect(getHandler(registrar, "lsp_code_action")({
|
|
225
|
+
file: "/workspace/src/index.ts",
|
|
226
|
+
line: 0,
|
|
227
|
+
character: 0,
|
|
228
|
+
apply: { index: 1 },
|
|
229
|
+
})).resolves.toEqual({
|
|
230
|
+
content: [{ type: "text", text: "Applied code action: Apply me" }],
|
|
231
|
+
raw: { title: "Apply me", changedFiles: ["/workspace/src/index.ts"] },
|
|
151
232
|
});
|
|
152
233
|
client.request.mockResolvedValueOnce(null);
|
|
153
|
-
await expect(getHandler(registrar,
|
|
154
|
-
content: [{ type:
|
|
155
|
-
raw: null
|
|
234
|
+
await expect(getHandler(registrar, "lsp_apply_workspace_edit")({ edit: null })).resolves.toEqual({
|
|
235
|
+
content: [{ type: "text", text: "No result" }],
|
|
236
|
+
raw: null,
|
|
156
237
|
});
|
|
157
238
|
});
|
|
158
|
-
it(
|
|
239
|
+
it("returns an error when no write-capable client is ready", async () => {
|
|
159
240
|
const registrar = new FakeRegistrar();
|
|
160
241
|
(0, write_tools_1.registerWriteTools)(registrar, {
|
|
161
242
|
getClientForFile: jest.fn(() => null),
|
|
@@ -164,15 +245,21 @@ describe('registerWriteTools', () => {
|
|
|
164
245
|
getWorkspaceDiagnostics: jest.fn(() => []),
|
|
165
246
|
getHealth: jest.fn(() => []),
|
|
166
247
|
ensureLanguageForFile: jest.fn().mockResolvedValue(undefined),
|
|
167
|
-
ensureSeedFilesOpen: jest.fn().mockResolvedValue(undefined)
|
|
248
|
+
ensureSeedFilesOpen: jest.fn().mockResolvedValue(undefined),
|
|
249
|
+
analyzeWorkspace: jest.fn().mockResolvedValue(undefined),
|
|
168
250
|
});
|
|
169
|
-
await expect(getHandler(registrar,
|
|
170
|
-
content: [
|
|
251
|
+
await expect(getHandler(registrar, "lsp_apply_workspace_edit")({ edit: {} })).resolves.toEqual({
|
|
252
|
+
content: [
|
|
253
|
+
{
|
|
254
|
+
type: "text",
|
|
255
|
+
text: "No language servers are ready. Run lsp_health for details.",
|
|
256
|
+
},
|
|
257
|
+
],
|
|
171
258
|
error: true,
|
|
172
|
-
raw: null
|
|
259
|
+
raw: null,
|
|
173
260
|
});
|
|
174
261
|
});
|
|
175
|
-
it(
|
|
262
|
+
it("handles missing clients, formatter defaults, and empty code actions", async () => {
|
|
176
263
|
const registrar = new FakeRegistrar();
|
|
177
264
|
const noClientLifecycle = {
|
|
178
265
|
getClientForFile: jest.fn(() => null),
|
|
@@ -181,45 +268,71 @@ describe('registerWriteTools', () => {
|
|
|
181
268
|
getWorkspaceDiagnostics: jest.fn(() => []),
|
|
182
269
|
getHealth: jest.fn(() => []),
|
|
183
270
|
ensureLanguageForFile: jest.fn().mockResolvedValue(undefined),
|
|
184
|
-
ensureSeedFilesOpen: jest.fn().mockResolvedValue(undefined)
|
|
271
|
+
ensureSeedFilesOpen: jest.fn().mockResolvedValue(undefined),
|
|
272
|
+
analyzeWorkspace: jest.fn().mockResolvedValue(undefined),
|
|
185
273
|
};
|
|
186
274
|
(0, write_tools_1.registerWriteTools)(registrar, noClientLifecycle);
|
|
187
|
-
await expect(getHandler(registrar,
|
|
188
|
-
content: [
|
|
275
|
+
await expect(getHandler(registrar, "lsp_rename")({ file: "/workspace/README.md", line: 0, character: 0, newName: "x" })).resolves.toEqual({
|
|
276
|
+
content: [
|
|
277
|
+
{
|
|
278
|
+
type: "text",
|
|
279
|
+
text: "No language server available for .md files. Run lsp_health for details.",
|
|
280
|
+
},
|
|
281
|
+
],
|
|
189
282
|
error: true,
|
|
190
|
-
raw: null
|
|
283
|
+
raw: null,
|
|
191
284
|
});
|
|
192
|
-
await expect(getHandler(registrar,
|
|
193
|
-
content: [
|
|
285
|
+
await expect(getHandler(registrar, "lsp_code_action")({ file: "/workspace/README.md", line: 0, character: 0 })).resolves.toEqual({
|
|
286
|
+
content: [
|
|
287
|
+
{
|
|
288
|
+
type: "text",
|
|
289
|
+
text: "No language server available for .md files. Run lsp_health for details.",
|
|
290
|
+
},
|
|
291
|
+
],
|
|
194
292
|
error: true,
|
|
195
|
-
raw: null
|
|
293
|
+
raw: null,
|
|
196
294
|
});
|
|
197
|
-
await expect(getHandler(registrar,
|
|
198
|
-
content: [
|
|
295
|
+
await expect(getHandler(registrar, "lsp_formatting")({ file: "/workspace/README.md" })).resolves.toEqual({
|
|
296
|
+
content: [
|
|
297
|
+
{
|
|
298
|
+
type: "text",
|
|
299
|
+
text: "No language server available for .md files. Run lsp_health for details.",
|
|
300
|
+
},
|
|
301
|
+
],
|
|
199
302
|
error: true,
|
|
200
|
-
raw: null
|
|
303
|
+
raw: null,
|
|
201
304
|
});
|
|
202
305
|
const secondRegistrar = new FakeRegistrar();
|
|
203
306
|
const client = createClient([]);
|
|
204
|
-
promises_1.access.mockRejectedValue(new Error(
|
|
307
|
+
promises_1.access.mockRejectedValue(new Error("missing"));
|
|
205
308
|
(0, write_tools_1.registerWriteTools)(secondRegistrar, createLifecycle(client));
|
|
206
|
-
await expect(getHandler(secondRegistrar,
|
|
207
|
-
content: [{ type:
|
|
208
|
-
raw: { changedFiles: [] }
|
|
309
|
+
await expect(getHandler(secondRegistrar, "lsp_formatting")({ file: "/workspace/src/index.ts" })).resolves.toEqual({
|
|
310
|
+
content: [{ type: "text", text: "Applied workspace edit to 0 file(s)" }],
|
|
311
|
+
raw: { changedFiles: [] },
|
|
209
312
|
});
|
|
210
|
-
await expect(getHandler(secondRegistrar,
|
|
211
|
-
content: [{ type:
|
|
212
|
-
raw: []
|
|
313
|
+
await expect(getHandler(secondRegistrar, "lsp_code_action")({ file: "/workspace/src/index.ts", line: 0, character: 0 })).resolves.toEqual({
|
|
314
|
+
content: [{ type: "text", text: "No result" }],
|
|
315
|
+
raw: [],
|
|
213
316
|
});
|
|
214
317
|
});
|
|
215
|
-
it(
|
|
318
|
+
it("maps write failures to timeout guidance", async () => {
|
|
216
319
|
const registrar = new FakeRegistrar();
|
|
217
|
-
const client = createClient(new Error(
|
|
320
|
+
const client = createClient(new Error("LSP request timed out: textDocument/rename"));
|
|
218
321
|
(0, write_tools_1.registerWriteTools)(registrar, createLifecycle(client));
|
|
219
|
-
await expect(getHandler(registrar,
|
|
220
|
-
|
|
322
|
+
await expect(getHandler(registrar, "lsp_rename")({
|
|
323
|
+
file: "/workspace/src/index.ts",
|
|
324
|
+
line: 0,
|
|
325
|
+
character: 0,
|
|
326
|
+
newName: "x",
|
|
327
|
+
})).resolves.toEqual({
|
|
328
|
+
content: [
|
|
329
|
+
{
|
|
330
|
+
type: "text",
|
|
331
|
+
text: "Operation timed out after 15s — try a more specific query or check the LSP server health",
|
|
332
|
+
},
|
|
333
|
+
],
|
|
221
334
|
error: true,
|
|
222
|
-
raw: null
|
|
335
|
+
raw: null,
|
|
223
336
|
});
|
|
224
337
|
});
|
|
225
338
|
});
|
|
@@ -238,13 +351,14 @@ function createLifecycle(client) {
|
|
|
238
351
|
getWorkspaceDiagnostics: jest.fn(() => []),
|
|
239
352
|
getHealth: jest.fn(() => []),
|
|
240
353
|
ensureLanguageForFile: jest.fn().mockResolvedValue(undefined),
|
|
241
|
-
ensureSeedFilesOpen: jest.fn().mockResolvedValue(undefined)
|
|
354
|
+
ensureSeedFilesOpen: jest.fn().mockResolvedValue(undefined),
|
|
355
|
+
analyzeWorkspace: jest.fn().mockResolvedValue(undefined),
|
|
242
356
|
};
|
|
243
357
|
}
|
|
244
358
|
function createClient(result, capabilities = { renameProvider: true }) {
|
|
245
359
|
return {
|
|
246
360
|
request: jest.fn().mockImplementation(async (method) => {
|
|
247
|
-
if (method ===
|
|
361
|
+
if (method === "workspace/executeCommand") {
|
|
248
362
|
return null;
|
|
249
363
|
}
|
|
250
364
|
if (result instanceof Error) {
|
|
@@ -256,6 +370,6 @@ function createClient(result, capabilities = { renameProvider: true }) {
|
|
|
256
370
|
getCapabilities: jest.fn(() => capabilities),
|
|
257
371
|
ensureDidOpen: jest.fn().mockResolvedValue(undefined),
|
|
258
372
|
waitForDiagnosticsPublish: jest.fn().mockResolvedValue(undefined),
|
|
259
|
-
ensureSeedFileOpen: jest.fn().mockResolvedValue(undefined)
|
|
373
|
+
ensureSeedFileOpen: jest.fn().mockResolvedValue(undefined),
|
|
260
374
|
};
|
|
261
375
|
}
|