Merge pull request #3501 from jeremymcs/fix/upgrade-kotlin-lsp

fix: upgrade Kotlin LSP to official Kotlin/kotlin-lsp
This commit is contained in:
Jeremy McSpadden 2026-04-04 14:04:40 -05:00 committed by GitHub
commit 104d103d14
3 changed files with 79 additions and 3 deletions

View file

@ -12,6 +12,11 @@ import type { ServerConfig } from "./types.js";
const require = createRequire(import.meta.url);
const DEFAULTS = require("./defaults.json") as Record<string, Partial<ServerConfig>>;
/** Map legacy server keys to their current names so user overrides still merge. */
const LEGACY_ALIASES: Record<string, string> = {
"kotlin-language-server": "kotlin-lsp",
};
export interface LspConfig {
servers: Record<string, ServerConfig>;
/** Idle timeout in milliseconds. If set, LSP clients will be shutdown after this period of inactivity. Disabled by default. */
@ -109,7 +114,8 @@ function mergeServers(
overrides: Record<string, Partial<ServerConfig>>,
): Record<string, ServerConfig> {
const merged: Record<string, ServerConfig> = { ...base };
for (const [name, config] of Object.entries(overrides)) {
for (const [rawName, config] of Object.entries(overrides)) {
const name = LEGACY_ALIASES[rawName] ?? rawName;
if (merged[name]) {
const candidate = { ...merged[name], ...config };
const normalized = normalizeServerConfig(name, candidate);

View file

@ -189,8 +189,8 @@
"fileTypes": [".java"],
"rootMarkers": ["pom.xml", "build.gradle", "build.gradle.kts", "settings.gradle", ".project"]
},
"kotlin-language-server": {
"command": "kotlin-language-server",
"kotlin-lsp": {
"command": "kotlin-lsp",
"args": [],
"fileTypes": [".kt", ".kts"],
"rootMarkers": ["build.gradle", "build.gradle.kts", "pom.xml", "settings.gradle", "settings.gradle.kts"]

View file

@ -0,0 +1,70 @@
// GSD2 — Regression test for LSP legacy server key aliases
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
/**
* When a default server key is renamed (e.g., kotlin-language-server kotlin-lsp),
* user overrides referencing the old key must still merge correctly via LEGACY_ALIASES.
*
* This test exercises the merge path through loadConfig() with a temp project
* containing an lsp.json that uses the legacy key.
*/
import { describe, it, beforeEach, afterEach } from "node:test";
import assert from "node:assert/strict";
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { loadConfig } from "./config.js";
describe("LSP legacy server key aliases", () => {
let tmpDir: string;
beforeEach(() => {
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "lsp-alias-test-"));
});
afterEach(() => {
fs.rmSync(tmpDir, { recursive: true, force: true });
});
it("merges user override with legacy key 'kotlin-language-server' into 'kotlin-lsp'", () => {
// Write an lsp.json that uses the old key name with a command that exists (node)
// so resolveCommand doesn't filter it out.
const overrideConfig = {
servers: {
"kotlin-language-server": {
command: "node",
},
},
};
fs.writeFileSync(
path.join(tmpDir, "lsp.json"),
JSON.stringify(overrideConfig),
);
// Also add root markers so the server is detected
fs.writeFileSync(path.join(tmpDir, "build.gradle.kts"), "");
const config = loadConfig(tmpDir);
// The merged config should have kotlin-lsp (new key) with the user's command override
const kotlinServer = config.servers["kotlin-lsp"];
assert.ok(kotlinServer, "kotlin-lsp should exist in merged config");
assert.equal(
kotlinServer.command,
"node",
"command should be overridden from user config via legacy alias",
);
assert.ok(
kotlinServer.fileTypes.includes(".kt"),
"fileTypes should be inherited from defaults",
);
// The old key should NOT appear as a separate entry
assert.equal(
config.servers["kotlin-language-server"],
undefined,
"legacy key should not appear as separate server",
);
});
});