Skip to content

Commit 9c706cd

Browse files
authored
Support update project jdk (#1263)
Signed-off-by: Sheng Chen <[email protected]>
1 parent 7e6d62d commit 9c706cd

File tree

11 files changed

+283
-58
lines changed

11 files changed

+283
-58
lines changed

package-lock.json

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@
359359
"@iconify-icons/codicon": "1.2.8",
360360
"@iconify/react": "^1.1.4",
361361
"@reduxjs/toolkit": "^1.8.6",
362-
"@vscode/codicons": "0.0.25",
362+
"@vscode/codicons": "^0.0.35",
363363
"@vscode/webview-ui-toolkit": "1.2.2",
364364
"@xmldom/xmldom": "^0.8.3",
365365
"axios": "^1.6.0",

src/classpath/assets/features/classpathConfiguration/ClasspathConfigurationView.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ import Sources from "./components/Sources";
1010
import ReferencedLibraries from "./components/ReferencedLibraries";
1111
import Header from "./components/Header";
1212
import Exception from "./components/Exception";
13-
import { ClasspathViewException, ProjectInfo } from "../../../types";
14-
import { catchException, listProjects, loadClasspath } from "./classpathConfigurationViewSlice";
13+
import { ClasspathViewException, ProjectInfo, VmInstall } from "../../../types";
14+
import { catchException, listProjects, listVmInstalls, loadClasspath } from "./classpathConfigurationViewSlice";
1515
import JdkRuntime from "./components/JdkRuntime";
16-
import { onWillListProjects } from "../../utils";
16+
import { onWillListProjects, onWillListVmInstalls } from "../../utils";
1717
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";
1818

1919
const ClasspathConfigurationView = (): JSX.Element => {
@@ -43,6 +43,8 @@ const ClasspathConfigurationView = (): JSX.Element => {
4343
const {data} = event;
4444
if (data.command === "onDidListProjects") {
4545
dispatch(listProjects(data.projectInfo));
46+
} else if (data.command === "onDidListVmInstalls") {
47+
dispatch(listVmInstalls(data.vmInstalls))
4648
} else if (data.command === "onDidLoadProjectClasspath") {
4749
dispatch(loadClasspath(data));
4850
} else if (data.command === "onException") {
@@ -53,6 +55,7 @@ const ClasspathConfigurationView = (): JSX.Element => {
5355
useEffect(() => {
5456
window.addEventListener("message", onInitialize);
5557
onWillListProjects();
58+
onWillListVmInstalls();
5659
return () => window.removeEventListener("message", onInitialize);
5760
}, []);
5861

@@ -72,6 +75,7 @@ interface OnInitializeEvent {
7275
rootPath: string;
7376
projectType: string;
7477
}[];
78+
vmInstalls?: VmInstall[];
7579
sources?: string[];
7680
output?: string;
7781
referencedLibraries?: string[];

src/classpath/assets/features/classpathConfiguration/classpathConfigurationViewSlice.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ export const classpathConfigurationViewSlice = createSlice({
99
initialState: {
1010
activeProjectIndex: 0,
1111
projects: [],
12+
activeVmInstallPath: "",
13+
vmInstalls: [],
1214
projectType: undefined,
1315
sources: [] as string[],
1416
output: "",
@@ -20,12 +22,16 @@ export const classpathConfigurationViewSlice = createSlice({
2022
state.projects = action.payload;
2123
state.activeProjectIndex = 0;
2224
},
25+
listVmInstalls: (state, action) => {
26+
state.vmInstalls = action.payload;
27+
},
2328
activeProjectChange: (state, action) => {
2429
state.activeProjectIndex = action.payload;
2530
},
2631
loadClasspath: (state, action) => {
2732
state.projectType = action.payload.projectType;
2833
state.output = action.payload.output;
34+
state.activeVmInstallPath = action.payload.activeVmInstallPath;
2935
// Only update the array when they have different elements.
3036
if (isDifferentStringArray(state.sources, action.payload.sources)) {
3137
state.sources = action.payload.sources;
@@ -40,6 +46,13 @@ export const classpathConfigurationViewSlice = createSlice({
4046
setOutputPath: (state, action) => {
4147
state.output = action.payload;
4248
},
49+
setJdks: (state, action) => {
50+
state.activeVmInstallPath = action.payload.activeVmInstallPath;
51+
if (action.payload.vmInstalls &&
52+
isDifferentStringArray(state.vmInstalls, action.payload.vmInstalls)) {
53+
state.vmInstalls = action.payload.vmInstalls;
54+
}
55+
},
4356
removeReferencedLibrary: (state, action) => {
4457
const removedIndex: number = action.payload as number;
4558
if (removedIndex > -1 && removedIndex < state.referencedLibraries.length) {
@@ -62,10 +75,12 @@ function isDifferentStringArray(a1: string[], a2: string[]): boolean {
6275

6376
export const {
6477
listProjects,
78+
listVmInstalls,
6579
activeProjectChange,
6680
loadClasspath,
6781
updateSource,
6882
setOutputPath,
83+
setJdks,
6984
removeReferencedLibrary,
7085
addReferencedLibraries,
7186
catchException,
Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,111 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4-
import React from "react";
4+
import React, { Dispatch, useEffect, useState } from "react";
55
import { encodeCommandUriWithTelemetry } from "../../../../../utils/webview";
6-
import { WEBVIEW_ID } from "../../../utils";
7-
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react";
6+
import { WEBVIEW_ID, onWillChangeJdk } from "../../../utils";
7+
import { VSCodeDivider, VSCodeDropdown, VSCodeLink, VSCodeOption, } from "@vscode/webview-ui-toolkit/react";
8+
import { useDispatch, useSelector } from "react-redux";
9+
import { VmInstall } from "../../../../types";
10+
import { setJdks } from "../classpathConfigurationViewSlice";
811
import SectionHeader from "./common/SectionHeader";
912

1013
const JdkRuntime = (): JSX.Element => {
14+
15+
const vmInstalls: VmInstall[] = useSelector((state: any) => state.classpathConfig.vmInstalls);
16+
const activeVmInstallPath: string = useSelector((state: any) => state.classpathConfig.activeVmInstallPath);
17+
18+
const [optionDescription, setOptionDescription] = useState<string | null>(null);
19+
20+
const dispatch: Dispatch<any> = useDispatch();
21+
22+
const handleSelectJdk = (path: string) => {
23+
onWillChangeJdk(path);
24+
if (path !== "add-new-jdk") {
25+
// if the user selects a existing JDK, we directly update the activeVmInstallPath.
26+
dispatch(setJdks({activeVmInstallPath: path}));
27+
}
28+
}
29+
30+
const onDidChangeJdk = (event: OnDidChangeJdkEvent) => {
31+
const {data} = event;
32+
if (data.command === "onDidChangeJdk") {
33+
dispatch(setJdks(data));
34+
}
35+
}
36+
37+
const jdkSelections = vmInstalls.map((vmInstall) => {
38+
return (
39+
<VSCodeOption
40+
className="setting-section-option"
41+
key={vmInstall.path}
42+
value={vmInstall.path}
43+
selected={vmInstall.path === activeVmInstallPath}
44+
onMouseEnter={() => setOptionDescription(vmInstall.path)}
45+
onMouseLeave={() => setOptionDescription(activeVmInstallPath)}
46+
onClick={() => handleSelectJdk(vmInstall.path)}
47+
>
48+
<span>{vmInstall.name}</span>
49+
</VSCodeOption>
50+
);
51+
});
52+
53+
const addNewJdk = (
54+
<VSCodeOption
55+
className="setting-section-option"
56+
key="add-new-jdk"
57+
value="add-new-jdk"
58+
onMouseEnter={() => setOptionDescription("Select a JDK from the file system.")}
59+
onMouseLeave={() => setOptionDescription(activeVmInstallPath + 'asds')}
60+
onClick={() => handleSelectJdk("add-new-jdk")}
61+
>
62+
<div className="setting-section-option-action">
63+
<span className="codicon codicon-folder-opened"></span>
64+
Add a new JDK...
65+
</div>
66+
</VSCodeOption>
67+
);
68+
69+
useEffect(() => {
70+
window.addEventListener("message", onDidChangeJdk);
71+
// the dropdown list has a fixed height by default, which makes the list jitter
72+
// when the jdk path changes. We set the max-height to initial to fix this issue.
73+
// Note that the list box is rendered inside a shadow dom so this is the only way
74+
// to change its style.
75+
document.querySelector("#jdk-dropdown")?.shadowRoot
76+
?.querySelector(".listbox")?.setAttribute("style", "max-height: initial;");
77+
return () => window.removeEventListener("message", onDidChangeJdk);
78+
}, []);
79+
1180
return (
1281
<div className="setting-section">
1382
<SectionHeader title="JDK Runtime" subTitle={undefined}/>
14-
<span className="setting-section-description">To configure JDK runtimes, please edit in <VSCodeLink href={encodeCommandUriWithTelemetry(WEBVIEW_ID, "classpath.runtime", "java.runtime")}>Configure Java Runtime</VSCodeLink>.</span>
83+
<span className="setting-section-description">Specify the JDK runtime of the project. Or <VSCodeLink href={encodeCommandUriWithTelemetry(WEBVIEW_ID, "classpath.jdk", "java.installJdk")}>install a new JDK</VSCodeLink>.</span>
84+
<div className="setting-section-target">
85+
<VSCodeDropdown id="jdk-dropdown" value={activeVmInstallPath} className="setting-section-dropdown" position="below">
86+
<div className="dropdown-description dropdown-above-description">
87+
<p>{optionDescription ?? activeVmInstallPath}</p>
88+
<VSCodeDivider></VSCodeDivider>
89+
</div>
90+
{jdkSelections}
91+
<VSCodeDivider></VSCodeDivider>
92+
{addNewJdk}
93+
<div className="dropdown-description dropdown-below-description">
94+
<VSCodeDivider></VSCodeDivider>
95+
<p>{optionDescription ?? activeVmInstallPath}</p>
96+
</div>
97+
</VSCodeDropdown>
98+
</div>
1599
</div>
16100
);
17101
};
18102

103+
interface OnDidChangeJdkEvent {
104+
data: {
105+
command: string;
106+
vmInstalls: VmInstall[];
107+
activeVmInstallPath: string;
108+
};
109+
}
110+
19111
export default JdkRuntime;

src/classpath/assets/features/classpathConfiguration/components/ProjectSelector.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,19 @@ import { useSelector, useDispatch } from "react-redux";
66
import { ProjectInfo } from "../../../../types";
77
import { Dispatch } from "@reduxjs/toolkit";
88
import { activeProjectChange } from "../classpathConfigurationViewSlice";
9-
import { onClickGotoProjectConfiguration, onWillLoadProjectClasspath, WEBVIEW_ID } from "../../../utils";
10-
import { encodeCommandUriWithTelemetry, ProjectType } from "../../../../../utils/webview";
9+
import { onClickGotoProjectConfiguration, onWillLoadProjectClasspath } from "../../../utils";
10+
import { ProjectType } from "../../../../../utils/webview";
1111
import { VSCodeDropdown, VSCodeLink, VSCodeOption } from "@vscode/webview-ui-toolkit/react";
1212

1313
const ProjectSelector = (): JSX.Element | null => {
1414
const activeProjectIndex: number = useSelector((state: any) => state.classpathConfig.activeProjectIndex);
1515
const projects: ProjectInfo[] = useSelector((state: any) => state.classpathConfig.projects);
1616
const projectType: ProjectType = useSelector((state: any) => state.classpathConfig.projectType);
1717
let buildFile: string = "";
18-
let buildFileDocUrl: string = "";
1918
if (projectType === ProjectType.Maven) {
2019
buildFile = "pom.xml";
21-
buildFileDocUrl = "https://maven.apache.org/pom.html#directories";
2220
} else if (projectType === ProjectType.Gradle) {
2321
buildFile = "build.gradle";
24-
buildFileDocUrl = "https://docs.gradle.org/current/userguide/java_plugin.html#source_sets";
2522
}
2623

2724
const dispatch: Dispatch<any> = useDispatch();
@@ -40,15 +37,15 @@ const ProjectSelector = (): JSX.Element | null => {
4037

4138
const projectSelections = projects.map((project, index) => {
4239
return (
43-
<VSCodeOption key={project.rootPath} onClick={() => handleActiveProjectChange(index)}>
40+
<VSCodeOption className="setting-section-option" key={project.rootPath} onClick={() => handleActiveProjectChange(index)}>
4441
{project.name}
4542
</VSCodeOption>
4643
);
4744
});
4845

4946
return (
5047
<div className="setting-section">
51-
<span className="setting-section-description">Select the project folder.</span>
48+
<span className="setting-section-description">Select the project.</span>
5249
<div className="setting-section-target">
5350
<VSCodeDropdown className="setting-section-dropdown">
5451
{projectSelections}
@@ -58,7 +55,8 @@ const ProjectSelector = (): JSX.Element | null => {
5855
{(projectType === ProjectType.Gradle || projectType === ProjectType.Maven) &&
5956
<div className="setting-section-target">
6057
<span className="setting-section-warning">
61-
Below settings are only editable for projects without build tools. For {projectType} project, please edit the <VSCodeLink href={encodeCommandUriWithTelemetry(WEBVIEW_ID, `classpath.open${projectType}Doc`, "java.helper.openUrl", [buildFileDocUrl])}>entries</VSCodeLink> in <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink>.
58+
'{projects[activeProjectIndex].name}' is imported by {projectType}, changes made to the classpath might be lost after reloading.
59+
To make permanent changes, please edit the <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink> file.
6260
</span>
6361
</div>
6462
}

src/classpath/assets/features/classpathConfiguration/components/ReferencedLibraries.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ const ReferencedLibraries = (): JSX.Element => {
2929

3030
const onDidAddReferencedLibraries = (event: OnDidAddReferencedLibrariesEvent) => {
3131
const {data} = event;
32-
if (data.command === "onDidAddReferencedLibraries") {
33-
dispatch(addReferencedLibraries(data.jars));
34-
}
32+
if (data.command === "onDidAddReferencedLibraries") {
33+
dispatch(addReferencedLibraries(data.jars));
34+
}
3535
};
3636

3737
useEffect(() => {

src/classpath/assets/style.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,16 @@
5858

5959
p {
6060
word-break: break-all;
61+
margin: 0;
62+
padding: 4px;
6163
}
6264

6365
.setting-section-option {
66+
padding: 0 4px;
67+
.setting-section-option-action {
6468
display: flex;
6569
align-items: flex-end;
70+
}
6671
}
6772
}
6873

src/classpath/assets/utils.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ export function onWillListProjects() {
1515
});
1616
}
1717

18+
export function onWillListVmInstalls() {
19+
vscode.postMessage({
20+
command: "onWillListVmInstalls",
21+
});
22+
}
23+
1824
export function onWillLoadProjectClasspath(uri: string) {
1925
vscode.postMessage({
2026
command: "onWillLoadProjectClasspath",
@@ -41,6 +47,13 @@ export function onWillAddSourcePath() {
4147
});
4248
}
4349

50+
export function onWillChangeJdk(jdkPath: string) {
51+
vscode.postMessage({
52+
command: "onWillChangeJdk",
53+
jdkPath,
54+
});
55+
}
56+
4457
export function onWillAddReferencedLibraries() {
4558
vscode.postMessage({
4659
command: "onWillAddReferencedLibraries"

0 commit comments

Comments
 (0)