fix(lsp): support server workspace configuration
This commit is contained in:
43
server.ts
43
server.ts
@@ -3,8 +3,42 @@
|
|||||||
//
|
//
|
||||||
// Add new servers here. `match` is a list of file extensions (no dot) OR
|
// Add new servers here. `match` is a list of file extensions (no dot) OR
|
||||||
// language ids; either matches.
|
// language ids; either matches.
|
||||||
|
import * as fs from "node:fs";
|
||||||
|
import * as path from "node:path";
|
||||||
import type { ServerConfig } from "./src/types.ts";
|
import type { ServerConfig } from "./src/types.ts";
|
||||||
|
|
||||||
|
// Resolve Python Path - Prefer the project's virtualenv when present so
|
||||||
|
// Pyright sees the same interpreter/dependencies as project commands.
|
||||||
|
function resolvePythonPath(rootDir: string): string | undefined {
|
||||||
|
const candidates = [
|
||||||
|
path.join(rootDir, ".venv", "bin", "python"),
|
||||||
|
path.join(rootDir, "venv", "bin", "python"),
|
||||||
|
];
|
||||||
|
return candidates.find((candidate) => fs.existsSync(candidate));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pyright Settings - Minimal editor settings needed for diagnostics and import
|
||||||
|
// resolution. Shared by workspace/configuration and didChangeConfiguration.
|
||||||
|
function pyrightSettings(rootDir: string): {
|
||||||
|
pythonPath: string | undefined;
|
||||||
|
analysis: {
|
||||||
|
diagnosticMode: string;
|
||||||
|
typeCheckingMode: string;
|
||||||
|
autoSearchPaths: boolean;
|
||||||
|
useLibraryCodeForTypes: boolean;
|
||||||
|
};
|
||||||
|
} {
|
||||||
|
return {
|
||||||
|
pythonPath: resolvePythonPath(rootDir),
|
||||||
|
analysis: {
|
||||||
|
diagnosticMode: "openFilesOnly",
|
||||||
|
typeCheckingMode: "basic",
|
||||||
|
autoSearchPaths: true,
|
||||||
|
useLibraryCodeForTypes: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Global Root Markers — appended to every server's rootMarkers list
|
// Global Root Markers — appended to every server's rootMarkers list
|
||||||
export const globalRootMarkers = [".git"];
|
export const globalRootMarkers = [".git"];
|
||||||
|
|
||||||
@@ -32,6 +66,15 @@ export const servers: ServerConfig[] = [
|
|||||||
args: ["--stdio"],
|
args: ["--stdio"],
|
||||||
rootMarkers: ["pyproject.toml", "setup.py", "setup.cfg"],
|
rootMarkers: ["pyproject.toml", "setup.py", "setup.cfg"],
|
||||||
languageId: "python",
|
languageId: "python",
|
||||||
|
workspaceConfiguration: {
|
||||||
|
initialSettings: ({ rootDir }) => ({ python: pyrightSettings(rootDir) }),
|
||||||
|
getSection: (section, { rootDir }) => {
|
||||||
|
const settings = pyrightSettings(rootDir);
|
||||||
|
if (section === "python") return settings;
|
||||||
|
if (section === "python.analysis") return settings.analysis;
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "lua-language-server",
|
id: "lua-language-server",
|
||||||
|
|||||||
@@ -102,9 +102,19 @@ export class LspClient {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
// Accept Common Server Requests - Return empty/null so servers don't
|
// Accept Common Server Requests - Return one configuration response per
|
||||||
// stall. Good enough for a CLI; a real client would answer properly.
|
// requested item. Server-specific settings live in server.ts so adding
|
||||||
this.conn.onRequest("workspace/configuration", () => []);
|
// another picky server doesn't grow conditionals in this transport layer.
|
||||||
|
this.conn.onRequest(
|
||||||
|
"workspace/configuration",
|
||||||
|
(params: { items?: { section?: string }[] }) => {
|
||||||
|
const items = params.items ?? [];
|
||||||
|
const config = this.server.workspaceConfiguration;
|
||||||
|
return items.map((item) =>
|
||||||
|
config?.getSection?.(item.section, { rootDir, env }) ?? null,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
this.conn.onRequest("client/registerCapability", () => null);
|
this.conn.onRequest("client/registerCapability", () => null);
|
||||||
this.conn.onRequest("client/unregisterCapability", () => null);
|
this.conn.onRequest("client/unregisterCapability", () => null);
|
||||||
|
|
||||||
@@ -136,6 +146,16 @@ export class LspClient {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.conn.sendNotification("initialized", {});
|
this.conn.sendNotification("initialized", {});
|
||||||
|
|
||||||
|
// Push Configuration - Some servers do not always request workspace/configuration,
|
||||||
|
// but still consume settings delivered through didChangeConfiguration.
|
||||||
|
const settings = this.server.workspaceConfiguration?.initialSettings?.({
|
||||||
|
rootDir,
|
||||||
|
env,
|
||||||
|
});
|
||||||
|
if (settings !== undefined && settings !== null) {
|
||||||
|
this.conn.sendNotification("workspace/didChangeConfiguration", { settings });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait For Ready - Resolves when there are no outstanding progress
|
// Wait For Ready - Resolves when there are no outstanding progress
|
||||||
|
|||||||
19
src/types.ts
19
src/types.ts
@@ -17,6 +17,22 @@ export class ServerNotFoundError extends Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface WorkspaceConfigurationContext {
|
||||||
|
rootDir: string;
|
||||||
|
env: NodeJS.ProcessEnv;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerWorkspaceConfiguration {
|
||||||
|
// Initial Settings - Optional payload pushed via workspace/didChangeConfiguration
|
||||||
|
// after initialize/initialized for servers that don't always request config.
|
||||||
|
initialSettings?: (ctx: WorkspaceConfigurationContext) => unknown;
|
||||||
|
// Section Settings - Optional handler for workspace/configuration requests.
|
||||||
|
getSection?: (
|
||||||
|
section: string | undefined,
|
||||||
|
ctx: WorkspaceConfigurationContext,
|
||||||
|
) => unknown;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ServerConfig {
|
export interface ServerConfig {
|
||||||
// Stable identifier (useful for logs and future daemon cache keys).
|
// Stable identifier (useful for logs and future daemon cache keys).
|
||||||
id: string;
|
id: string;
|
||||||
@@ -38,6 +54,9 @@ export interface ServerConfig {
|
|||||||
// hover/definition/references/completion/documentSymbol but included
|
// hover/definition/references/completion/documentSymbol but included
|
||||||
// in lsp_diagnostics and auto-check.
|
// in lsp_diagnostics and auto-check.
|
||||||
diagnosticsOnly?: boolean;
|
diagnosticsOnly?: boolean;
|
||||||
|
// Workspace Configuration - Optional server-specific settings exposed through
|
||||||
|
// workspace/configuration and workspace/didChangeConfiguration.
|
||||||
|
workspaceConfiguration?: ServerWorkspaceConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Supported high-level commands exposed via the CLI. Extend this union
|
// Supported high-level commands exposed via the CLI. Extend this union
|
||||||
|
|||||||
Reference in New Issue
Block a user