Файли
openidea/src/platform/jdk.test.ts
T
l0ng-ai 56fdc005a8 feat(java): Download JDK, and one-click "Download JDK N" where a JDK is missing (#61)
Root cause: the IDE only detected installed JDKs and had no way to get one, so any launch needing a newer JDK than the machine has (latest jdtls needs JDK 25) dead-ended in an error.

Fix: IDEA-style Download JDK (Eclipse Temurin via the Adoptium API, sha256-verified, reusing ide-tools' download/verify code; Windows zip, Linux tar.gz, macOS Contents/Home) into <app-data>/tools/jdks, registered with JDK discovery and rescanned after each download. "Download JDK…" in the Project SDK and Language Server JDK pickers; a one-click `java.downloadJdk` "Download JDK N" on "needs JDK N" errors, which also repoints a too-old language server JDK and restarts jdtls.

Siblings: language server status popup, jdtls launch notification, run console classpath error, debug launch, run configurations without a JDK ≥ the module's Java version, Maven/Gradle sync failures, single-file Java run without `java` on PATH.

Verified in the app on macOS: vendor/version/location queries, the Download JDK dialog from the Language Server JDK picker, a real Temurin 25.0.5 download that runs. Not verified on Windows/Linux.

Fixes #49

https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
2026-10-27 12:09:51 +08:00

64 рядки
2.8 KiB
TypeScript
Неформатований Анотація Історія

Цей файл містить неоднозначні символи Юнікоду
Цей файл містить символи Юнікоду, які можна сплутати з іншими символами. Якщо ви вважаєте, що це зроблено навмисно, можете сміливо ігнорувати це попередження. Щоб показати їх, скористайтеся кнопкою Escape.
import { afterEach, describe, expect, it, vi } from "vitest";
const executeAction = vi.fn(async () => true);
let registered = true;
vi.mock("./actions", async (orig) => ({
...(await orig<typeof import("./actions")>()),
executeAction,
getAction: (id: string) => (registered && id === "java.downloadJdk" ? { id } : undefined),
}));
const { downloadJdkActions, isDownloadJdkArgs, requiredJdk } = await import("./jdk");
afterEach(() => {
registered = true;
vi.clearAllMocks();
});
// Issue #49, verbatim from the run console (Windows, JDK 8 / 17 / 21 installed).
const ISSUE_49 =
"jdtls needs JDK 25 or newer to run (found JDK 8, 17, 21). Pick one in Settings › Languages & Frameworks › Java › Language Server › JDK (it restarts automatically), or install a newer JDK and restart the server; the project can still target an older Java version.";
describe("JDK requirements in launch / sync errors", () => {
it.each([
[ISSUE_49, { version: 25, languageServer: true }],
[
"The language server JDK (C:\\Java\\jdk-21, JDK 21) is too old: jdtls needs JDK 25 or newer. Download JDK 25, choose another one in Settings › Languages & Frameworks › Java › Language Server › JDK, or set it to Auto.",
{ version: 25, languageServer: true },
],
[
"This project targets Java 21: it needs JDK 21 or newer (found JDK 17). Download JDK 21, or choose a Project JDK in Settings › Languages & Frameworks › Java.",
{ version: 21, languageServer: false },
],
[
"This project targets Java 17: it needs JDK 17 or newer (no JDK was found). Download JDK 17, or choose a Project JDK in Settings › Languages & Frameworks › Java.\n[ERROR] Failed to execute goal",
{ version: 17, languageServer: false },
],
["The language server JDK /x is not a JDK home (Settings › Languages & Frameworks › Java).", null],
["`rust-analyzer` was not found on PATH", null],
[null, null],
])("%s", (message, expected) => {
expect(requiredJdk(message)).toEqual(expected);
});
it("offers Download JDK N, which runs the download action", () => {
const [fix, ...rest] = downloadJdkActions(ISSUE_49);
expect(rest).toEqual([]);
expect(fix!.label).toBe("Download JDK 25");
fix!.run();
expect(executeAction).toHaveBeenCalledWith("java.downloadJdk", { version: 25, languageServer: true });
expect(downloadJdkActions("jdtls crashed")).toEqual([]);
});
it("offers nothing where no window can download (e.g. without the tools feature)", () => {
registered = false;
expect(downloadJdkActions(ISSUE_49)).toEqual([]);
});
it("recognises the action's argument", () => {
expect(isDownloadJdkArgs({ version: 25 })).toBe(true);
expect(isDownloadJdkArgs({ version: "25" })).toBe(false);
expect(isDownloadJdkArgs(undefined)).toBe(false);
});
});