Skip to content

Support update project jdk #1263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,7 @@
"@iconify-icons/codicon": "1.2.8",
"@iconify/react": "^1.1.4",
"@reduxjs/toolkit": "^1.8.6",
"@vscode/codicons": "0.0.25",
"@vscode/codicons": "^0.0.35",
"@vscode/webview-ui-toolkit": "1.2.2",
"@xmldom/xmldom": "^0.8.3",
"axios": "^0.21.4",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import Sources from "./components/Sources";
import ReferencedLibraries from "./components/ReferencedLibraries";
import Header from "./components/Header";
import Exception from "./components/Exception";
import { ClasspathViewException, ProjectInfo } from "../../../types";
import { catchException, listProjects, loadClasspath } from "./classpathConfigurationViewSlice";
import { ClasspathViewException, ProjectInfo, VmInstall } from "../../../types";
import { catchException, listProjects, listVmInstalls, loadClasspath } from "./classpathConfigurationViewSlice";
import JdkRuntime from "./components/JdkRuntime";
import { onWillListProjects } from "../../utils";
import { onWillListProjects, onWillListVmInstalls } from "../../utils";
import { VSCodeProgressRing } from "@vscode/webview-ui-toolkit/react";

const ClasspathConfigurationView = (): JSX.Element => {
Expand Down Expand Up @@ -43,6 +43,8 @@ const ClasspathConfigurationView = (): JSX.Element => {
const {data} = event;
if (data.command === "onDidListProjects") {
dispatch(listProjects(data.projectInfo));
} else if (data.command === "onDidListVmInstalls") {
dispatch(listVmInstalls(data.vmInstalls))
} else if (data.command === "onDidLoadProjectClasspath") {
dispatch(loadClasspath(data));
} else if (data.command === "onException") {
Expand All @@ -53,6 +55,7 @@ const ClasspathConfigurationView = (): JSX.Element => {
useEffect(() => {
window.addEventListener("message", onInitialize);
onWillListProjects();
onWillListVmInstalls();
return () => window.removeEventListener("message", onInitialize);
}, []);

Expand All @@ -72,6 +75,7 @@ interface OnInitializeEvent {
rootPath: string;
projectType: string;
}[];
vmInstalls?: VmInstall[];
sources?: string[];
output?: string;
referencedLibraries?: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const classpathConfigurationViewSlice = createSlice({
initialState: {
activeProjectIndex: 0,
projects: [],
activeVmInstallPath: "",
vmInstalls: [],
projectType: undefined,
sources: [] as string[],
output: "",
Expand All @@ -20,12 +22,16 @@ export const classpathConfigurationViewSlice = createSlice({
state.projects = action.payload;
state.activeProjectIndex = 0;
},
listVmInstalls: (state, action) => {
state.vmInstalls = action.payload;
},
activeProjectChange: (state, action) => {
state.activeProjectIndex = action.payload;
},
loadClasspath: (state, action) => {
state.projectType = action.payload.projectType;
state.output = action.payload.output;
state.activeVmInstallPath = action.payload.activeVmInstallPath;
// Only update the array when they have different elements.
if (isDifferentStringArray(state.sources, action.payload.sources)) {
state.sources = action.payload.sources;
Expand All @@ -40,6 +46,13 @@ export const classpathConfigurationViewSlice = createSlice({
setOutputPath: (state, action) => {
state.output = action.payload;
},
setJdks: (state, action) => {
state.activeVmInstallPath = action.payload.activeVmInstallPath;
if (action.payload.vmInstalls &&
isDifferentStringArray(state.vmInstalls, action.payload.vmInstalls)) {
state.vmInstalls = action.payload.vmInstalls;
}
},
removeReferencedLibrary: (state, action) => {
const removedIndex: number = action.payload as number;
if (removedIndex > -1 && removedIndex < state.referencedLibraries.length) {
Expand All @@ -62,10 +75,12 @@ function isDifferentStringArray(a1: string[], a2: string[]): boolean {

export const {
listProjects,
listVmInstalls,
activeProjectChange,
loadClasspath,
updateSource,
setOutputPath,
setJdks,
removeReferencedLibrary,
addReferencedLibraries,
catchException,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,111 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import React from "react";
import React, { Dispatch, useEffect, useState } from "react";
import { encodeCommandUriWithTelemetry } from "../../../../../utils/webview";
import { WEBVIEW_ID } from "../../../utils";
import { VSCodeLink } from "@vscode/webview-ui-toolkit/react";
import { WEBVIEW_ID, onWillChangeJdk } from "../../../utils";
import { VSCodeDivider, VSCodeDropdown, VSCodeLink, VSCodeOption, } from "@vscode/webview-ui-toolkit/react";
import { useDispatch, useSelector } from "react-redux";
import { VmInstall } from "../../../../types";
import { setJdks } from "../classpathConfigurationViewSlice";
import SectionHeader from "./common/SectionHeader";

const JdkRuntime = (): JSX.Element => {

const vmInstalls: VmInstall[] = useSelector((state: any) => state.classpathConfig.vmInstalls);
const activeVmInstallPath: string = useSelector((state: any) => state.classpathConfig.activeVmInstallPath);

const [optionDescription, setOptionDescription] = useState<string | null>(null);

const dispatch: Dispatch<any> = useDispatch();

const handleSelectJdk = (path: string) => {
onWillChangeJdk(path);
if (path !== "add-new-jdk") {
// if the user selects a existing JDK, we directly update the activeVmInstallPath.
dispatch(setJdks({activeVmInstallPath: path}));
}
}

const onDidChangeJdk = (event: OnDidChangeJdkEvent) => {
const {data} = event;
if (data.command === "onDidChangeJdk") {
dispatch(setJdks(data));
}
}

const jdkSelections = vmInstalls.map((vmInstall) => {
return (
<VSCodeOption
className="setting-section-option"
key={vmInstall.path}
value={vmInstall.path}
selected={vmInstall.path === activeVmInstallPath}
onMouseEnter={() => setOptionDescription(vmInstall.path)}
onMouseLeave={() => setOptionDescription(activeVmInstallPath)}
onClick={() => handleSelectJdk(vmInstall.path)}
>
<span>{vmInstall.name}</span>
</VSCodeOption>
);
});

const addNewJdk = (
<VSCodeOption
className="setting-section-option"
key="add-new-jdk"
value="add-new-jdk"
onMouseEnter={() => setOptionDescription("Select a JDK from the file system.")}
onMouseLeave={() => setOptionDescription(activeVmInstallPath + 'asds')}
onClick={() => handleSelectJdk("add-new-jdk")}
>
<div className="setting-section-option-action">
<span className="codicon codicon-folder-opened"></span>
Add a new JDK...
</div>
</VSCodeOption>
);

useEffect(() => {
window.addEventListener("message", onDidChangeJdk);
// the dropdown list has a fixed height by default, which makes the list jitter
// when the jdk path changes. We set the max-height to initial to fix this issue.
// Note that the list box is rendered inside a shadow dom so this is the only way
// to change its style.
document.querySelector("#jdk-dropdown")?.shadowRoot
?.querySelector(".listbox")?.setAttribute("style", "max-height: initial;");
return () => window.removeEventListener("message", onDidChangeJdk);
}, []);

return (
<div className="setting-section">
<SectionHeader title="JDK Runtime" subTitle={undefined}/>
<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>
<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>
<div className="setting-section-target">
<VSCodeDropdown id="jdk-dropdown" value={activeVmInstallPath} className="setting-section-dropdown" position="below">
<div className="dropdown-description dropdown-above-description">
<p>{optionDescription ?? activeVmInstallPath}</p>
<VSCodeDivider></VSCodeDivider>
</div>
{jdkSelections}
<VSCodeDivider></VSCodeDivider>
{addNewJdk}
<div className="dropdown-description dropdown-below-description">
<VSCodeDivider></VSCodeDivider>
<p>{optionDescription ?? activeVmInstallPath}</p>
</div>
</VSCodeDropdown>
</div>
</div>
);
};

interface OnDidChangeJdkEvent {
data: {
command: string;
vmInstalls: VmInstall[];
activeVmInstallPath: string;
};
}

export default JdkRuntime;
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,19 @@ import { useSelector, useDispatch } from "react-redux";
import { ProjectInfo } from "../../../../types";
import { Dispatch } from "@reduxjs/toolkit";
import { activeProjectChange } from "../classpathConfigurationViewSlice";
import { onClickGotoProjectConfiguration, onWillLoadProjectClasspath, WEBVIEW_ID } from "../../../utils";
import { encodeCommandUriWithTelemetry, ProjectType } from "../../../../../utils/webview";
import { onClickGotoProjectConfiguration, onWillLoadProjectClasspath } from "../../../utils";
import { ProjectType } from "../../../../../utils/webview";
import { VSCodeDropdown, VSCodeLink, VSCodeOption } from "@vscode/webview-ui-toolkit/react";

const ProjectSelector = (): JSX.Element | null => {
const activeProjectIndex: number = useSelector((state: any) => state.classpathConfig.activeProjectIndex);
const projects: ProjectInfo[] = useSelector((state: any) => state.classpathConfig.projects);
const projectType: ProjectType = useSelector((state: any) => state.classpathConfig.projectType);
let buildFile: string = "";
let buildFileDocUrl: string = "";
if (projectType === ProjectType.Maven) {
buildFile = "pom.xml";
buildFileDocUrl = "https://maven.apache.org/pom.html#directories";
} else if (projectType === ProjectType.Gradle) {
buildFile = "build.gradle";
buildFileDocUrl = "https://docs.gradle.org/current/userguide/java_plugin.html#source_sets";
}

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

const projectSelections = projects.map((project, index) => {
return (
<VSCodeOption key={project.rootPath} onClick={() => handleActiveProjectChange(index)}>
<VSCodeOption className="setting-section-option" key={project.rootPath} onClick={() => handleActiveProjectChange(index)}>
{project.name}
</VSCodeOption>
);
});

return (
<div className="setting-section">
<span className="setting-section-description">Select the project folder.</span>
<span className="setting-section-description">Select the project.</span>
<div className="setting-section-target">
<VSCodeDropdown className="setting-section-dropdown">
{projectSelections}
Expand All @@ -58,7 +55,8 @@ const ProjectSelector = (): JSX.Element | null => {
{(projectType === ProjectType.Gradle || projectType === ProjectType.Maven) &&
<div className="setting-section-target">
<span className="setting-section-warning">
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>.
'{projects[activeProjectIndex].name}' is imported by {projectType}, changes made to the classpath might be lost after reloading.
To make permanent changes, please edit the <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink> file.
</span>
</div>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const ReferencedLibraries = (): JSX.Element => {

const onDidAddReferencedLibraries = (event: OnDidAddReferencedLibrariesEvent) => {
const {data} = event;
if (data.command === "onDidAddReferencedLibraries") {
dispatch(addReferencedLibraries(data.jars));
}
if (data.command === "onDidAddReferencedLibraries") {
dispatch(addReferencedLibraries(data.jars));
}
};

useEffect(() => {
Expand Down
5 changes: 5 additions & 0 deletions src/classpath/assets/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,16 @@

p {
word-break: break-all;
margin: 0;
padding: 4px;
}

.setting-section-option {
padding: 0 4px;
.setting-section-option-action {
display: flex;
align-items: flex-end;
}
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/classpath/assets/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ export function onWillListProjects() {
});
}

export function onWillListVmInstalls() {
vscode.postMessage({
command: "onWillListVmInstalls",
});
}

export function onWillLoadProjectClasspath(uri: string) {
vscode.postMessage({
command: "onWillLoadProjectClasspath",
Expand All @@ -41,6 +47,13 @@ export function onWillAddSourcePath() {
});
}

export function onWillChangeJdk(jdkPath: string) {
vscode.postMessage({
command: "onWillChangeJdk",
jdkPath,
});
}

export function onWillAddReferencedLibraries() {
vscode.postMessage({
command: "onWillAddReferencedLibraries"
Expand Down
Loading