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
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-27 12:09:51 +08:00
1 джерело beab7992f9
коміт 56fdc005a8
29 files changed
+1592 -111

No files matched your search

+4 -1
Переглянути файл
@@ -1,6 +1,7 @@
/** Debugger actions (ids match `keymaps/intellij-macos.ts`). */
import { registerActions, type Action } from "@/platform/actions";
import { call, commands, isCancelled, isTauri, nextRequestId, type RunConfig, type RunId } from "@/platform/ipc";
import { downloadJdkActions } from "@/platform/jdk";
import { useProject } from "@/platform/project";
import { activeEditor } from "@/editor/api";
import { maybeEditorService, notifications, toolWindowService } from "@/workbench/contributions";
@@ -55,7 +56,9 @@ async function report(title: string, p: Promise<unknown>) {
try {
await p;
} catch (e) {
notifications().notify({ group: "run", level: "error", title, body: errorText(e), key: "debug.action" });
// A Java launch without a JDK new enough (for jdtls or the project) offers to download one.
const actions = downloadJdkActions(errorText(e));
notifications().notify({ group: "run", level: "error", title, body: errorText(e), key: "debug.action", actions });
}
}