дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(java): share JDT LS across builds in a project window (#2272)
* feat(java): share JDT LS across builds in a project window * fix(java): wait for JDT restart before launch requests * fix(host): give relay final replies ten seconds of EOF grace relay::tests::final_responses_keep_flowing_after_input_eof flakes on Windows CI: the target writes one byte per second for seven seconds after input EOF, but the relay only waits five idle seconds, so a slow first byte makes the relay return with nothing received. Raise EOF_GRACE to ten seconds and update the companion test's server wait and elapsed bound to match. Refs #2272 (Windows CI failure) --------- Co-authored-by: arookieofc <[email protected]>
Цей коміт міститься в:
1 джерело
5d3432a000
коміт
a46d873f6c
16 files changed
+1034
-79
No files matched your search
@@ -5271,6 +5271,8 @@ export type JavaSettings = {
|
||||
* (VS Code's `java.jdt.ls.vmargs`).
|
||||
*/
|
||||
jdtlsVmArgs?: string,
|
||||
/** Share one JDT LS across builds in an ordinary project window; other windows remain separate. */
|
||||
jdtlsShared?: boolean,
|
||||
/** Build Tools › Maven. */
|
||||
maven?: MavenSettings,
|
||||
/** Build Tools › Gradle. */
|
||||
|
||||
@@ -514,6 +514,94 @@ describe("Settings dialog", () => {
|
||||
expect(settingsSet.mock.calls).toEqual([["global", "languages.java.jdtlsVmArgs", '"-Xmx2g"']]);
|
||||
});
|
||||
|
||||
it("stages shared JDT LS in the project and writes it on Apply", async () => {
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
const checkbox = within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" });
|
||||
expect(checkbox).not.toBeChecked();
|
||||
fireEvent.click(checkbox);
|
||||
expect(checkbox).toBeChecked();
|
||||
expect(settingsSet).not.toHaveBeenCalled();
|
||||
await act(async () => fireEvent.click(within(dialog).getByRole("button", { name: "Apply" })));
|
||||
expect(settingsSet.mock.calls).toEqual([["project", "languages.java.jdtlsShared", "true"]]);
|
||||
});
|
||||
|
||||
it("keeps the global shared JDT LS preference separate from the project's override", async () => {
|
||||
global = setAt(global, "languages.java.jdtlsShared", true);
|
||||
current = setAt(global, "languages.java.jdtlsShared", false);
|
||||
useProject.setState({ settings: current });
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
expect(within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" })).not.toBeChecked();
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "Global" }));
|
||||
const checkbox = within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" });
|
||||
expect(checkbox).toBeChecked();
|
||||
fireEvent.click(checkbox);
|
||||
await act(async () => fireEvent.click(within(dialog).getByRole("button", { name: "Apply" })));
|
||||
expect(settingsSet.mock.calls).toEqual([["global", "languages.java.jdtlsShared", "false"]]);
|
||||
});
|
||||
|
||||
it("discards a shared JDT LS toggle on Cancel", async () => {
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
fireEvent.click(within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" }));
|
||||
fireEvent.click(within(dialog).getByRole("button", { name: "Cancel" }));
|
||||
expect(settingsSet).not.toHaveBeenCalled();
|
||||
expect(current.languages?.java?.jdtlsShared).toBe(false);
|
||||
});
|
||||
|
||||
it("disables shared JDT LS only in a native Workspace's project scope", async () => {
|
||||
useProject.setState((s) => ({
|
||||
project: { ...s.project!, workspace: { version: 1, name: "Workspace", projects: ["/p/member"] } },
|
||||
}));
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
expect(within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" })).toBeDisabled();
|
||||
expect(within(dialog).getByText(/Open a workspace member as a project/)).toBeInTheDocument();
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "Global" }));
|
||||
const checkbox = within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" });
|
||||
expect(checkbox).toBeEnabled();
|
||||
fireEvent.click(checkbox);
|
||||
await act(async () => fireEvent.click(within(dialog).getByRole("button", { name: "Apply" })));
|
||||
expect(settingsSet.mock.calls).toEqual([["global", "languages.java.jdtlsShared", "true"]]);
|
||||
});
|
||||
|
||||
it("disables sharing for a Java language server target only in project scope", async () => {
|
||||
current = setAt(current, "languageServerTargets", { java: { target: "docker:java", server: "jdtls" } });
|
||||
useProject.setState({ settings: current });
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
const checkbox = within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" });
|
||||
expect(checkbox).toBeDisabled();
|
||||
expect(within(dialog).getByText(/Select Local machine for the Java language server/)).toBeInTheDocument();
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "Global" }));
|
||||
expect(checkbox).toBeEnabled();
|
||||
fireEvent.click(checkbox);
|
||||
await act(async () => fireEvent.click(within(dialog).getByRole("button", { name: "Apply" })));
|
||||
expect(settingsSet.mock.calls).toEqual([["global", "languages.java.jdtlsShared", "true"]]);
|
||||
});
|
||||
|
||||
it.each([{ java: { target: "", server: "jdtls" } }, { python: { target: "docker:python" } }])(
|
||||
"keeps sharing available when Java runs locally: %j",
|
||||
async (targets) => {
|
||||
current = setAt(current, "languageServerTargets", targets);
|
||||
useProject.setState({ settings: current });
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
expect(within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" })).toBeEnabled();
|
||||
},
|
||||
);
|
||||
|
||||
it("uses a staged project Java language server target before Apply", async () => {
|
||||
const dialog = await openDialog("languages.java");
|
||||
fireEvent.click(within(dialog).getByRole("radio", { name: "This project" }));
|
||||
const checkbox = within(dialog).getByRole("checkbox", { name: "Share JDT LS across builds" });
|
||||
expect(checkbox).toBeEnabled();
|
||||
act(() => stage("languages.servers", "project", "languageServerTargets.java.target", "docker:java"));
|
||||
expect(checkbox).toBeDisabled();
|
||||
expect(settingsSet).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("Settings for New Projects edits the global layer on every page", async () => {
|
||||
render(<SettingsDialog />);
|
||||
await act(async () => {
|
||||
|
||||
@@ -192,6 +192,15 @@ describe("languages settings", () => {
|
||||
expect(folderRole(ps, "src")).toBeNull();
|
||||
});
|
||||
|
||||
it("defaults shared JDT LS to off and accepts only boolean values", () => {
|
||||
expect(DEFAULT_LANGUAGES.java.jdtlsShared).toBe(false);
|
||||
expect(validateLanguages({}).java.jdtlsShared).toBe(false);
|
||||
expect(validateSettings({ languages: { java: { jdtlsShared: true } } }).languages.java.jdtlsShared).toBe(true);
|
||||
expect(validateLanguages({ java: { jdtlsShared: false } }).java.jdtlsShared).toBe(false);
|
||||
for (const invalid of ["true", 1, null, []])
|
||||
expect(validateLanguages({ java: { jdtlsShared: invalid } }).java.jdtlsShared).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults Java language level to SDK default and keeps only supported levels", () => {
|
||||
expect(validateLanguages({}).java.languageLevel).toBe("");
|
||||
expect(validateLanguages({ java: { languageLevel: "8" } }).java.languageLevel).toBe("8");
|
||||
|
||||
@@ -4,15 +4,16 @@
|
||||
* use (applied by `ide-sdk` when language servers start and when run configurations load).
|
||||
*/
|
||||
import { LanguageServerTargetRows, LanguageServerTargetsPage } from "./LanguageServerTarget";
|
||||
import { useProject } from "@/platform/project";
|
||||
import { useRunTargets } from "@/platform/pluginRunTargets";
|
||||
import { tx } from "@/platform/i18n";
|
||||
import { useEffect, useId, useMemo, useState } from "react";
|
||||
import { call, commands, type Sdk } from "@/platform/ipc";
|
||||
import { call, commands, type LanguageServerTarget, type Sdk } from "@/platform/ipc";
|
||||
import { IconButton, Input, type SelectOption, T } from "@/ui";
|
||||
import { JAVA_LANGUAGE_LEVELS, PHP_LANGUAGE_LEVELS } from "@/platform/languageSettings";
|
||||
import { GlobListEditor, Row, Section, Select, Toggle } from "../components/Form";
|
||||
import { choosePath } from "./api";
|
||||
import { useSetting } from "../components/context";
|
||||
import { usePageContext, useSetting } from "../components/context";
|
||||
import { SdkField, tildify, useDetected } from "./components";
|
||||
import styles from "./Sdk.module.css";
|
||||
|
||||
@@ -387,6 +388,11 @@ export const JAVA_LEVEL_OPTIONS: SelectOption[] = JAVA_LANGUAGE_LEVELS.map((leve
|
||||
);
|
||||
|
||||
export function JavaPage() {
|
||||
const [shared, setShared] = useSetting<boolean>("languages.java.jdtlsShared");
|
||||
const [serverTargets] = useSetting<Record<string, LanguageServerTarget>>("languageServerTargets", "project");
|
||||
const { scope } = usePageContext();
|
||||
const workspace = useProject((s) => !!s.project?.workspace);
|
||||
const sharedDisabled = scope === "project" && (workspace || !!serverTargets?.java?.target);
|
||||
const [vmArgs, setVmArgs] = useSetting<string>("languages.java.jdtlsVmArgs");
|
||||
const [languageLevel, setLanguageLevel] = useSetting<string>("languages.java.languageLevel");
|
||||
const id = useId();
|
||||
@@ -417,6 +423,19 @@ export function JavaPage() {
|
||||
</Row>
|
||||
</Section>
|
||||
<Section title="Language Server">
|
||||
<Toggle
|
||||
label="Share JDT LS across builds"
|
||||
checked={shared}
|
||||
onChange={setShared}
|
||||
disabled={sharedDisabled}
|
||||
hint={
|
||||
sharedDisabled
|
||||
? workspace
|
||||
? "Shared JDT LS is available only in local ordinary project windows. Open a workspace member as a project to change this setting for it."
|
||||
: "Shared JDT LS is available only in local ordinary project windows. Select Local machine for the Java language server to use it."
|
||||
: "Uses one JDT LS process for linked builds in each local ordinary project window. Other project windows use separate processes."
|
||||
}
|
||||
/>
|
||||
<SdkRow
|
||||
k="languages.java.jdtlsJdk"
|
||||
label="JDK"
|
||||
|
||||
@@ -132,6 +132,9 @@ export const LANGUAGE_PAGES: PageSpec[] = [
|
||||
"lombok",
|
||||
"javaagent",
|
||||
"eclipse jdt",
|
||||
"shared jdtls",
|
||||
"linked builds",
|
||||
"server process",
|
||||
],
|
||||
component: JavaPage,
|
||||
},
|
||||
|
||||
@@ -164,6 +164,7 @@ export interface LanguagesValid {
|
||||
languageLevel: (typeof JAVA_LANGUAGE_LEVELS)[number];
|
||||
jdtlsJdk: string;
|
||||
jdtlsVmArgs: string;
|
||||
jdtlsShared: boolean;
|
||||
gradle: {
|
||||
linkedProjects: string[] | null;
|
||||
jvm: string;
|
||||
@@ -243,6 +244,7 @@ export const DEFAULT_LANGUAGES: LanguagesValid = {
|
||||
languageLevel: "",
|
||||
jdtlsJdk: "",
|
||||
jdtlsVmArgs: "",
|
||||
jdtlsShared: false,
|
||||
gradle: { linkedProjects: null, jvm: "", distribution: "wrapper", home: "", userHome: "", runUsing: "gradle" },
|
||||
maven: {
|
||||
runnerJre: "",
|
||||
@@ -401,6 +403,7 @@ export function validateLanguages(raw: unknown): LanguagesValid {
|
||||
languageLevel: oneOf(java.languageLevel, JAVA_LANGUAGE_LEVELS, d.java.languageLevel),
|
||||
jdtlsJdk: text(java.jdtlsJdk, d.java.jdtlsJdk),
|
||||
jdtlsVmArgs: text(java.jdtlsVmArgs, d.java.jdtlsVmArgs),
|
||||
jdtlsShared: bool(java.jdtlsShared, d.java.jdtlsShared),
|
||||
gradle: {
|
||||
linkedProjects: Array.isArray(gradle.linkedProjects)
|
||||
? gradle.linkedProjects.filter((p): p is string => typeof p === "string")
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"Shared JDT LS is available only in local ordinary project windows. Select Local machine for the Java language server to use it.": "Shared JDT LS is available only in local ordinary project windows. Select Local machine for the Java language server to use it.",
|
||||
"Share JDT LS across builds": "Share JDT LS across builds",
|
||||
"Shared JDT LS is available only in local ordinary project windows. Open a workspace member as a project to change this setting for it.": "Shared JDT LS is available only in local ordinary project windows. Open a workspace member as a project to change this setting for it.",
|
||||
"Uses one JDT LS process for linked builds in each local ordinary project window. Other project windows use separate processes.": "Uses one JDT LS process for linked builds in each local ordinary project window. Other project windows use separate processes.",
|
||||
"Finder": "Finder",
|
||||
"Explorer": "Explorer",
|
||||
"Files": "Files",
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
{
|
||||
"Shared JDT LS is available only in local ordinary project windows. Select Local machine for the Java language server to use it.": "共享 JDT LS 仅适用于本机的普通项目窗口。请将 Java 语言服务器的运行位置设为本机后再使用。",
|
||||
"Share JDT LS across builds": "在构建间共享 JDT LS",
|
||||
"Shared JDT LS is available only in local ordinary project windows. Open a workspace member as a project to change this setting for it.": "共享 JDT LS 仅适用于本机的普通项目窗口。请将工作区成员作为项目打开,再修改其此项设置。",
|
||||
"Uses one JDT LS process for linked builds in each local ordinary project window. Other project windows use separate processes.": "在每个本机普通项目窗口中,已关联的构建共用一个 JDT LS 进程。其他项目窗口使用各自独立的进程。",
|
||||
"Finder": "访达",
|
||||
"Explorer": "资源管理器",
|
||||
"Reveal in Finder": "在访达中显示",
|
||||
|
||||
Reference in new issue
Заблокувати користувача