mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
fix(maven): unlink modules of a reactor so jdtls stops importing them (#1059)
Only root Maven projects could be unlinked, and jdtls imports an aggregator with all of its modules whatever java.import.exclusions say. A module of a reactor can now be unlinked from the Maven tool window; when one is, jdtls gets initializationOptions.projectConfigurations listing the linked POMs except the aggregators above the unlinked module (plus the Gradle build file if there is one), and a Maven sync only names the POMs jdtls imported. Unlinking whole roots keeps using exclusions. Fixes #767
This commit is contained in:
@@ -306,8 +306,7 @@ function BuildToolView({ tool }: { tool: BuildTool }) {
|
||||
else items.push({ label: "Create Run Configuration…", icon: "edit", run: () => void createRunConfig(config) });
|
||||
}
|
||||
if (node.kind === "mavenProject") {
|
||||
if (!node.project.aggregated)
|
||||
items.push({ kind: "action", action: "maven.unlinkProjects", arg: { pom: node.project.pom } });
|
||||
items.push({ kind: "action", action: "maven.unlinkProjects", arg: { pom: node.project.pom } });
|
||||
items.push(
|
||||
{
|
||||
label: "Open pom.xml",
|
||||
|
||||
@@ -34,7 +34,10 @@ vi.mock("@/platform/ipc", async (original) => {
|
||||
});
|
||||
vi.mock("@tauri-apps/plugin-dialog", () => ({ open: mocks.open }));
|
||||
vi.mock("@/workbench/messages", () => ({ confirm: mocks.confirm }));
|
||||
vi.mock("@/ui", async (original) => ({ ...(await original<typeof import("@/ui")>()), showContextMenu: mocks.menu }));
|
||||
vi.mock("@/ui", async (original) => ({
|
||||
...(await original<typeof import("@/ui")>()),
|
||||
showContextMenu: mocks.menu,
|
||||
}));
|
||||
|
||||
const model: BuildModel = {
|
||||
gradle: null,
|
||||
@@ -69,7 +72,9 @@ const model: BuildModel = {
|
||||
let dispose: () => void;
|
||||
beforeEach(async () => {
|
||||
vi.clearAllMocks();
|
||||
mocks.get.mockResolvedValue({ languages: { java: { maven: { unlinkedProjects: [] } } } });
|
||||
mocks.get.mockResolvedValue({
|
||||
languages: { java: { maven: { unlinkedProjects: [] } } },
|
||||
});
|
||||
mocks.set.mockResolvedValue({});
|
||||
mocks.model.mockResolvedValue(model);
|
||||
mocks.configs.mockResolvedValue([]);
|
||||
@@ -91,7 +96,12 @@ it("offers unlink on a root's context menu and persists a confirmed project sett
|
||||
fireEvent.contextMenu(screen.getByText("project-a"));
|
||||
expect(mocks.menu).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.arrayContaining([expect.objectContaining({ action: "maven.unlinkProjects", arg: { pom: "a/pom.xml" } })]),
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
action: "maven.unlinkProjects",
|
||||
arg: { pom: "a/pom.xml" },
|
||||
}),
|
||||
]),
|
||||
);
|
||||
await act(async () => {
|
||||
await executeAction("maven.unlinkProjects", { pom: "a/pom.xml" });
|
||||
@@ -101,24 +111,83 @@ it("offers unlink on a root's context menu and persists a confirmed project sett
|
||||
expect(mocks.model).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("does not unlink modules or write after cancelled confirmation", async () => {
|
||||
it("does not write after cancelled confirmation", async () => {
|
||||
mocks.confirm.mockResolvedValue(false);
|
||||
await executeAction("maven.unlinkProjects", { pom: "a/pom.xml" });
|
||||
expect(mocks.confirm).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.set).not.toHaveBeenCalled();
|
||||
act(() =>
|
||||
useBuild.setState({
|
||||
model: { ...model, maven: { ...model.maven!, projects: [{ ...model.maven!.projects[0]!, aggregated: true }] } },
|
||||
});
|
||||
|
||||
it("unlinks a module of a linked reactor so only the modules in use are imported", async () => {
|
||||
const root = model.maven!.projects[0]!;
|
||||
const child = {
|
||||
...root,
|
||||
pom: "a/child/pom.xml",
|
||||
dir: "a/child",
|
||||
artifactId: "child",
|
||||
displayName: "child-module",
|
||||
packaging: "jar",
|
||||
parent: "a/pom.xml",
|
||||
aggregated: true,
|
||||
};
|
||||
const reactor: BuildModel = {
|
||||
...model,
|
||||
maven: {
|
||||
...model.maven!,
|
||||
projects: [{ ...root, modules: ["a/child/pom.xml"] }, child],
|
||||
},
|
||||
};
|
||||
mocks.model.mockResolvedValue(reactor);
|
||||
mocks.get.mockResolvedValue({
|
||||
languages: { java: { maven: { unlinkedProjects: ["b/pom.xml"] } } },
|
||||
});
|
||||
await act(async () => {
|
||||
useBuild.setState({ model: reactor });
|
||||
});
|
||||
render(<MavenView />);
|
||||
fireEvent.contextMenu(await screen.findByText("child-module"));
|
||||
expect(mocks.menu).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
action: "maven.unlinkProjects",
|
||||
arg: { pom: "a/child/pom.xml" },
|
||||
}),
|
||||
]),
|
||||
);
|
||||
await act(async () => {
|
||||
await executeAction("maven.unlinkProjects", { pom: "a/child/pom.xml" });
|
||||
});
|
||||
expect(mocks.confirm).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
message: expect.stringContaining("Java language server stops importing them"),
|
||||
}),
|
||||
);
|
||||
render(<MavenView />);
|
||||
await executeAction("maven.unlinkProjects", { pom: "a/pom.xml" });
|
||||
expect(mocks.confirm).toHaveBeenCalledTimes(1);
|
||||
expect(mocks.set).toHaveBeenCalledWith(
|
||||
"project",
|
||||
"languages.java.maven.unlinkedProjects",
|
||||
'["b/pom.xml","a/child/pom.xml"]',
|
||||
);
|
||||
});
|
||||
|
||||
it("ignores a POM that is not in the Maven model", async () => {
|
||||
await executeAction("maven.unlinkProjects", { pom: "missing/pom.xml" });
|
||||
expect(mocks.confirm).not.toHaveBeenCalled();
|
||||
expect(mocks.set).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("re-adds a picked POM using the plus button and preserves other unlinked roots", async () => {
|
||||
mocks.get.mockResolvedValue({ languages: { java: { maven: { unlinkedProjects: ["a/pom.xml", "b/pom.xml"] } } } });
|
||||
mocks.get.mockResolvedValue({
|
||||
languages: {
|
||||
java: { maven: { unlinkedProjects: ["a/pom.xml", "b/pom.xml"] } },
|
||||
},
|
||||
});
|
||||
mocks.open.mockResolvedValue("/p/a/pom.xml");
|
||||
act(() => useBuild.setState({ model: { ...model, maven: { ...model.maven!, projects: [] } } }));
|
||||
act(() =>
|
||||
useBuild.setState({
|
||||
model: { ...model, maven: { ...model.maven!, projects: [] } },
|
||||
}),
|
||||
);
|
||||
render(<MavenView />);
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByRole("button", { name: "Add Maven Projects" }));
|
||||
|
||||
@@ -255,11 +255,14 @@ async function setLinked(root: string, pom: string, linked: boolean) {
|
||||
|
||||
export async function unlinkProjects(pom: string | null) {
|
||||
const { root, model } = useBuild.getState();
|
||||
if (!root || !pom || !model?.maven?.projects.some((p) => p.pom === pom && !p.aggregated)) return;
|
||||
const project = model?.maven?.projects.find((p) => p.pom === pom);
|
||||
if (!root || !pom || !project) return;
|
||||
if (
|
||||
!(await confirm({
|
||||
title: "Unlink Maven projects?",
|
||||
message: "Remove this project and its modules from Maven? Files will remain in the Project view.",
|
||||
message: project.aggregated
|
||||
? "Remove this module and its submodules from Maven? The Java language server stops importing them, so they no longer use memory. Files will remain in the Project view; add the pom.xml again to restore them."
|
||||
: "Remove this project and its modules from Maven? Files will remain in the Project view.",
|
||||
ok: "Unlink",
|
||||
}))
|
||||
)
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
"Unlink Maven Projects": "取消链接 Maven 项目",
|
||||
"Unlink Maven projects?": "取消链接 Maven 项目?",
|
||||
"Remove this project and its modules from Maven? Files will remain in the Project view.": "从 Maven 中移除此项目及其模块?文件将保留在项目视图中。",
|
||||
"Remove this module and its submodules from Maven? The Java language server stops importing them, so they no longer use memory. Files will remain in the Project view; add the pom.xml again to restore them.": "从 Maven 中移除此模块及其子模块?Java 语言服务器将不再导入它们,也就不再为它们占用内存。文件将保留在项目视图中;重新添加其 pom.xml 即可恢复。",
|
||||
"Unlink": "取消链接",
|
||||
"(does not exist)": "(不存在)",
|
||||
", e.g.": ",例如",
|
||||
|
||||
Reference in New Issue
Block a user