Skip to content

Commit 25e4819

Browse files
committed
pickup notifications that were being missed
1 parent 84d4f47 commit 25e4819

File tree

4 files changed

+103
-11
lines changed

4 files changed

+103
-11
lines changed

lib/capabilities.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
export const notification2capability = {
1+
export const method2capability = {
2+
// notifications
3+
"initialized": "*",
4+
"workspace/didChangeConfiguration": "*",
5+
26
"textDocument/didOpen": "textDocumentSync",
37
"textDocument/didChange": "textDocumentSync",
48
"textDocument/willSave": "textDocumentSync.willSave",
@@ -11,14 +15,11 @@ export const notification2capability = {
1115
"workspace/willDeleteFiles": "workspace.fileOperations.willDelete",
1216
"workspace/didDeleteFiles": "workspace.fileOperations.didDelete",
1317

14-
"workspace/didChangeConfiguration": "*",
15-
1618
"workspace/didChangeWorkspaceFolders":
1719
"workspace.workspaceFolders.changeNotifications",
1820
"workspace/willCreateFiles": "workspace.fileOperations.willCreate",
19-
} as const;
2021

21-
export const request2capability = {
22+
// requsets
2223
"textDocument/willSaveWaitUntil": "textDocumentSync.willSaveWaitUntil",
2324
"textDocument/declaration": "declarationProvider",
2425
"textDocument/definition": "definitionProvider",

lib/dispatch.ts

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { all, type Operation } from "effection";
22
import type { LSPAgent, NotificationParams, RequestParams } from "./types.ts";
33
import deepmerge from "deepmerge";
44
import { get, optic } from "optics-ts";
5-
import { request2capability } from "./capabilities.ts";
5+
import { method2capability } from "./capabilities.ts";
66
import { responseError } from "./json-rpc-connection.ts";
77
import {
88
type CompletionParams,
@@ -37,9 +37,7 @@ export function* request(options: RequestOptions): Operation<unknown> {
3737
handler.agents.map((agent) => agent.request(params)),
3838
);
3939

40-
let merge = handler.merge ??
41-
((responses) =>
42-
responses.reduce((sum, response) => deepmerge(sum, response)));
40+
let merge = handler.merge ?? defaultMerge;
4341

4442
return merge(responses);
4543
}
@@ -63,7 +61,7 @@ export function* notification(options: NotificationOptions): Operation<void> {
6361
}
6462

6563
export function match(agents: LSPAgent[], params: RequestParams): Match {
66-
let method = params[0] as keyof typeof request2capability;
64+
let method = params[0] as keyof typeof method2capability;
6765
switch (method) {
6866
case "textDocument/completion":
6967
return completion({ agents, params });
@@ -110,10 +108,27 @@ interface Match {
110108
*/
111109
function defaultMatch(canddidates: LSPAgent[], method: string): Match {
112110
let capabilityPath =
113-
request2capability[method as keyof typeof request2capability];
111+
method2capability[method as keyof typeof method2capability];
112+
if (capabilityPath === "*") {
113+
return { agents: canddidates };
114+
}
115+
if (!capabilityPath) {
116+
console.error(`nothing matches ${method}`);
117+
return { agents: canddidates };
118+
}
114119
let path = optic().path(capabilityPath);
115120
let agents = canddidates.filter((agent) => {
116121
return !!get(path)(agent.capabilities);
117122
});
118123
return { agents };
119124
}
125+
126+
function defaultMerge(responses: unknown[]): unknown {
127+
return responses.reduce((sum, response) => {
128+
if (response === null) {
129+
return sum;
130+
} else {
131+
return deepmerge(sum as Partial<unknown>, response as Partial<unknown>);
132+
}
133+
});
134+
}

test/lspx.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,28 @@ describe("lspx", function () {
117117
});
118118
});
119119

120+
describe("hover", () => {
121+
beforeEach(function* () {
122+
yield* initServer({
123+
commands: [
124+
"deno -A test/sim/hover.ts",
125+
"deno -A test/sim/hover.ts",
126+
],
127+
});
128+
yield* initialize({ textDocument: { hover: {} } });
129+
});
130+
131+
it("can handle a null response from all the servers", function* () {
132+
let result = yield* request("textDocument/hover", {
133+
textDocument: {
134+
uri: "file:///Users/cowboyd/Code/@cowboyd/lsps/test/lspx.test.ts",
135+
},
136+
position: { line: 126, character: 12 },
137+
});
138+
expect(result).toEqual({ ok: true, value: null });
139+
});
140+
});
141+
120142
describe("client/registerCapability", () => {
121143
it("forwards dynamic registrations requests to the client");
122144
it("forwards dynamic unregistrations requests to the client");

test/sim/hover.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import type { Operation } from "effection";
2+
import { each, main } from "effection";
3+
import { responseError, useConnection } from "../../lib/json-rpc-connection.ts";
4+
import type {
5+
InitializeParams,
6+
InitializeResult,
7+
} from "vscode-languageserver-protocol";
8+
import { ErrorCodes } from "vscode-jsonrpc";
9+
import { parser } from "zod-opts";
10+
11+
await main(function* (args) {
12+
parser()
13+
.name("hover simulator")
14+
.parse(args);
15+
16+
let client = yield* useConnection({
17+
read: Deno.stdin.readable,
18+
write: Deno.stdout.writable,
19+
});
20+
21+
// deno-lint-ignore no-explicit-any
22+
const routes: Record<string, (...params: any[]) => Operation<any>> = {
23+
*initialize(_params: InitializeParams): Operation<InitializeResult> {
24+
return {
25+
capabilities: {
26+
hoverProvider: true,
27+
},
28+
serverInfo: {
29+
name: "lspx hover simulator",
30+
version: "1.0",
31+
},
32+
};
33+
},
34+
*["textDocument/hover"](): Operation<null> {
35+
return null;
36+
},
37+
};
38+
39+
for (let respondWith of yield* each(client.requests)) {
40+
yield* respondWith(function* (params) {
41+
let [method] = params;
42+
let operation = routes[method];
43+
if (operation) {
44+
return yield* operation(...[params].flat());
45+
} else {
46+
return yield* responseError(
47+
ErrorCodes.InvalidRequest,
48+
`method not handled`,
49+
);
50+
}
51+
});
52+
yield* each.next();
53+
}
54+
});

0 commit comments

Comments
 (0)