Name the diagnostics resource parameter; make symbol lookup pure
This commit is contained in:
3 files changed
+22
-20
No files matched your search
+18
-16
@@ -4,7 +4,7 @@
|
|||||||
* forwarded as MCP log notifications.
|
* forwarded as MCP log notifications.
|
||||||
*/
|
*/
|
||||||
import { Effect, Layer, Schema, Stream } from "effect";
|
import { Effect, Layer, Schema, Stream } from "effect";
|
||||||
import { McpServer } from "effect/unstable/ai";
|
import { McpSchema, McpServer } from "effect/unstable/ai";
|
||||||
import { Diagnostics } from "./lsp/Diagnostics.ts";
|
import { Diagnostics } from "./lsp/Diagnostics.ts";
|
||||||
import { Documents } from "./lsp/Documents.ts";
|
import { Documents } from "./lsp/Documents.ts";
|
||||||
import * as Editor from "./lsp/Editor.ts";
|
import * as Editor from "./lsp/Editor.ts";
|
||||||
@@ -46,23 +46,25 @@ export const layer = Layer.effectDiscard(
|
|||||||
content: Effect.map(Editor.diagnostics({}), json),
|
content: Effect.map(Editor.diagnostics({}), json),
|
||||||
});
|
});
|
||||||
|
|
||||||
yield* McpServer.registerResource`lsp://diagnostics/${Schema.String}`({
|
yield* McpServer.registerResource`lsp://diagnostics/${McpSchema.param("file", Schema.String)}`(
|
||||||
name: "File diagnostics",
|
{
|
||||||
description:
|
name: "File diagnostics",
|
||||||
"Diagnostics of one file (path URL-encoded, relative to the workspace root)",
|
description:
|
||||||
mimeType: "application/json",
|
"Diagnostics of one file (path URL-encoded, relative to the workspace root)",
|
||||||
completion: {
|
mimeType: "application/json",
|
||||||
param0: (input) =>
|
completion: {
|
||||||
Effect.map(docs.opened, (uris) =>
|
file: (input) =>
|
||||||
uris.map(docs.file).filter((file) => file.startsWith(input)),
|
Effect.map(docs.opened, (uris) =>
|
||||||
|
uris.map(docs.file).filter((file) => file.startsWith(input)),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
content: (_, file) =>
|
||||||
|
Effect.map(
|
||||||
|
Editor.diagnostics({ file: decodeURIComponent(file) }),
|
||||||
|
json,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
content: (_, file) =>
|
);
|
||||||
Effect.map(
|
|
||||||
Editor.diagnostics({ file: decodeURIComponent(file) }),
|
|
||||||
json,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
const updated = (uri: string) =>
|
const updated = (uri: string) =>
|
||||||
mcp.notifications["notifications/resources/updated"]({ uri });
|
mcp.notifications["notifications/resources/updated"]({ uri });
|
||||||
|
|||||||
+3
-3
@@ -125,7 +125,7 @@ const locate = Effect.fn("Editor.locate")(function* (where: Model.Where) {
|
|||||||
where.column !== undefined
|
where.column !== undefined
|
||||||
? where.column - 1
|
? where.column - 1
|
||||||
: where.symbol !== undefined
|
: where.symbol !== undefined
|
||||||
? yield* Effect.orElseSucceed(findSymbol(text, where.symbol), () => -1)
|
? findSymbol(text, where.symbol)
|
||||||
: Math.max(0, text.search(/\S/));
|
: Math.max(0, text.search(/\S/));
|
||||||
if (character < 0) {
|
if (character < 0) {
|
||||||
return yield* new LspError({
|
return yield* new LspError({
|
||||||
@@ -140,13 +140,13 @@ const locate = Effect.fn("Editor.locate")(function* (where: Model.Where) {
|
|||||||
return { doc, position, textDocument: { uri: doc.uri } };
|
return { doc, position, textDocument: { uri: doc.uri } };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** Index of `symbol` as a whole word on the line, else its first occurrence, else -1. */
|
||||||
const findSymbol = (text: string, symbol: string) => {
|
const findSymbol = (text: string, symbol: string) => {
|
||||||
const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
const index = text.search(
|
const index = text.search(
|
||||||
new RegExp(`(?<![\\p{L}\\p{N}_$])${escaped}(?![\\p{L}\\p{N}_$])`, "u"),
|
new RegExp(`(?<![\\p{L}\\p{N}_$])${escaped}(?![\\p{L}\\p{N}_$])`, "u"),
|
||||||
);
|
);
|
||||||
const found = index >= 0 ? index : text.indexOf(symbol);
|
return index >= 0 ? index : text.indexOf(symbol);
|
||||||
return found >= 0 ? Effect.succeed(found) : Effect.fail(found);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const locations = Effect.fn("Editor.locations")(function* (
|
const locations = Effect.fn("Editor.locations")(function* (
|
||||||
|
|||||||
+1
-1
@@ -137,7 +137,7 @@ describe("MCP server", () => {
|
|||||||
const { resourceTemplates } = yield* mcp["resources/templates/list"]({});
|
const { resourceTemplates } = yield* mcp["resources/templates/list"]({});
|
||||||
assert.deepStrictEqual(
|
assert.deepStrictEqual(
|
||||||
resourceTemplates.map((t) => t.uriTemplate),
|
resourceTemplates.map((t) => t.uriTemplate),
|
||||||
["lsp://diagnostics/{param0}"],
|
["lsp://diagnostics/{file}"],
|
||||||
);
|
);
|
||||||
}).pipe(Effect.scoped),
|
}).pipe(Effect.scoped),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in new issue
Block a user