Skip to content

Commit 613de16

Browse files
authored
Display the warning message when necessary (#1340)
- For all the states of the project setting page, effective values are introduced so that we know if a setting is changed. Thus the warning that reloading project will lose the changes can be displayed only when necessary.
1 parent df19a62 commit 613de16

File tree

12 files changed

+363
-158
lines changed

12 files changed

+363
-158
lines changed

src/project-settings/assets/classpath/features/classpathConfigurationViewSlice.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@ export const classpathConfigurationViewSlice = createSlice({
1212
activeTab: "",
1313
},
1414
data: {
15-
activeVmInstallPath: [] as string[],
1615
vmInstalls: [],
16+
effective: { // the effective classpath in LS.
17+
activeVmInstallPath: [] as string[],
18+
sources: [] as ClasspathEntry[][],
19+
output: [] as string[],
20+
libraries: [] as ClasspathEntry[][],
21+
},
22+
// below are the classpath data in the UI.
23+
activeVmInstallPath: [] as string[],
1724
sources: [] as ClasspathEntry[][],
1825
output: [] as string[],
1926
libraries: [] as ClasspathEntry[][],
@@ -31,27 +38,45 @@ export const classpathConfigurationViewSlice = createSlice({
3138
state.data.sources = Array(projectNum).fill([]);
3239
state.data.output = Array(projectNum).fill("");
3340
state.data.libraries = Array(projectNum).fill([]);
41+
42+
state.data.effective.activeVmInstallPath = Array(projectNum).fill("");
43+
state.data.effective.sources = Array(projectNum).fill([]);
44+
state.data.effective.output = Array(projectNum).fill("");
45+
state.data.effective.libraries = Array(projectNum).fill([]);
3446
},
3547
listVmInstalls: (state, action) => {
3648
state.data.vmInstalls = action.payload;
3749
},
3850
loadClasspath: (state, action) => {
3951
const activeProjectIndex = action.payload.activeProjectIndex;
4052
state.data.output[activeProjectIndex] = action.payload.output;
53+
state.data.effective.output[activeProjectIndex] = action.payload.output;
54+
4155
state.data.activeVmInstallPath[activeProjectIndex] = action.payload.activeVmInstallPath;
56+
state.data.effective.activeVmInstallPath[activeProjectIndex] = action.payload.activeVmInstallPath;
57+
4258
// Only update the array when they have different elements.
4359
const currentSources = _.sortBy(state.data.sources[activeProjectIndex], ["path", "output"]);
4460
const newSources = _.sortBy(action.payload.sources, ["path", "output"]);
4561
if (!_.isEqual(currentSources, newSources)) {
4662
state.data.sources[activeProjectIndex] = action.payload.sources;
63+
state.data.effective.sources[activeProjectIndex] = action.payload.sources;
4764
}
4865

4966
const currentLibs = _.sortBy(state.data.libraries[activeProjectIndex], ["path"]);
5067
const newLibs = _.sortBy(action.payload.libraries, ["path"]);
5168
if (!_.isEqual(currentLibs, newLibs)) {
5269
state.data.libraries[activeProjectIndex] = action.payload.libraries;
70+
state.data.effective.libraries[activeProjectIndex] = action.payload.libraries;
5371
}
5472
},
73+
flushClasspathToEffective: (state, action) => {
74+
const activeProjectIndex = action.payload.activeProjectIndex;
75+
state.data.effective.output[activeProjectIndex] = state.data.output[activeProjectIndex];
76+
state.data.effective.activeVmInstallPath[activeProjectIndex] = state.data.activeVmInstallPath[activeProjectIndex];
77+
state.data.effective.sources[activeProjectIndex] = [...state.data.sources[activeProjectIndex]];
78+
state.data.effective.libraries[activeProjectIndex] = [...state.data.libraries[activeProjectIndex]];
79+
},
5580
updateSource: (state, action) => {
5681
const activeProjectIndex = action.payload.activeProjectIndex;
5782
state.data.sources[activeProjectIndex] = _.uniqBy(action.payload.sources as ClasspathEntry[], "path");
@@ -107,6 +132,7 @@ export const {
107132
addLibraries,
108133
catchException,
109134
updateLoadingState,
135+
flushClasspathToEffective,
110136
} = classpathConfigurationViewSlice.actions;
111137

112138
export default classpathConfigurationViewSlice.reducer;

src/project-settings/assets/classpath/features/components/Hint.tsx

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,45 @@
33

44
import { VSCodeLink} from "@vscode/webview-ui-toolkit/react";
55
import React, { useEffect } from "react";
6-
import { ProjectInfo } from "../../../../types";
6+
import { ClasspathEntry, ProjectInfo } from "../../../../types";
77
import { useSelector } from "react-redux";
88
import { ProjectType } from "../../../../../utils/webview";
99
import { updateMaxHeight } from "../../utils";
1010
import { ClasspathRequest } from "../../../vscode/utils";
11+
import _ from "lodash";
1112

12-
const Hint = (): JSX.Element => {
13+
const Hint = (): JSX.Element | null => {
1314

14-
const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
1515
const projects: ProjectInfo[] = useSelector((state: any) => state.commonConfig.data.projects);
1616
const projectType: ProjectType[] = useSelector((state: any) => state.commonConfig.data.projectType);
17+
const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex);
18+
const sources: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.sources[activeProjectIndex]);
19+
const effectiveSources: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.effective.sources[activeProjectIndex]);
20+
const defaultOutput: string = useSelector((state: any) => state.classpathConfig.data.output[activeProjectIndex]);
21+
const effectiveOutput: string = useSelector((state: any) => state.classpathConfig.data.effective.output[activeProjectIndex]);
22+
const activeVmInstallPath: string = useSelector((state: any) => state.classpathConfig.data.activeVmInstallPath[activeProjectIndex]);
23+
const effectiveVmInstallPath: string = useSelector((state: any) => state.classpathConfig.data.effective.activeVmInstallPath[activeProjectIndex]);
24+
const libraries: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.libraries[activeProjectIndex]);
25+
const effectiveLibraries: ClasspathEntry[] = useSelector((state: any) => state.classpathConfig.data.effective.libraries[activeProjectIndex]);
26+
const classpathModified: boolean = !_.isEqual(sources, effectiveSources) ||
27+
defaultOutput !== effectiveOutput ||
28+
activeVmInstallPath !== effectiveVmInstallPath ||
29+
!_.isEqual(libraries, effectiveLibraries);
30+
31+
useEffect(() => {
32+
updateMaxHeight();
33+
}, [projectType, libraries, effectiveLibraries]);
34+
35+
useEffect(() => {
36+
window.addEventListener('resize', updateMaxHeight);
37+
return () => {
38+
window.removeEventListener("resize", updateMaxHeight);
39+
}
40+
}, []);
41+
42+
if (!classpathModified) {
43+
return null;
44+
}
1745

1846
let buildFile: string = "";
1947
if (projectType[activeProjectIndex] === ProjectType.Maven) {
@@ -26,23 +54,13 @@ const Hint = (): JSX.Element => {
2654
ClasspathRequest.onClickGotoProjectConfiguration(projects[activeProjectIndex].rootPath, projectType[activeProjectIndex]);
2755
};
2856

29-
useEffect(() => {
30-
updateMaxHeight();
31-
window.addEventListener('resize', updateMaxHeight);
32-
return () => {
33-
window.removeEventListener("resize", updateMaxHeight);
34-
}
35-
}, [projectType]);
36-
3757
return (
3858
<div id="hint" className="setting-footer pb-2">
3959
{(projectType[activeProjectIndex] === ProjectType.Gradle || projectType[activeProjectIndex] === ProjectType.Maven) &&
40-
<div className="mt-1">
41-
<span className="setting-section-warning">
42-
'{projects[activeProjectIndex].name}' is imported by {projectType[activeProjectIndex]}, changes made to the classpath might be lost after reloading.
43-
To make permanent changes, please edit the <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink> file.
44-
</span>
45-
</div>
60+
<span className="setting-section-warning">
61+
'{projects[activeProjectIndex].name}' is imported by {projectType[activeProjectIndex]}, changes made to the classpath might be lost after reloading.
62+
To make permanent changes, please edit the <VSCodeLink href="" onClick={() => handleOpenBuildFile()}>{buildFile}</VSCodeLink> file.
63+
</span>
4664
}
4765
</div>
4866
);

src/project-settings/assets/classpath/style.scss

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
.root {
2-
display: flex;
3-
flex-direction: column;
4-
justify-content: space-between;
5-
flex: 1;
6-
}
7-
81
.setting-header {
92
color: var(--vscode-settings-headerForeground);
103
}

src/project-settings/assets/compiler/features/CompilerConfigurationView.tsx

Lines changed: 70 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
import { VSCodeCheckbox, VSCodeDataGrid, VSCodeDataGridCell, VSCodeDataGridRow, VSCodeDivider, VSCodeDropdown, VSCodeLink, VSCodeOption } from "@vscode/webview-ui-toolkit/react";
55
import React, { Dispatch, useEffect } from "react";
66
import { useDispatch, useSelector } from "react-redux";
7-
import { updateCompilerSettings, updateAvailableComplianceLevels } from "./compilerConfigurationViewSlice";
7+
import { updateCompilerSettings, updateAvailableComplianceLevels, flushCompilerSettingsToEffective } from "./compilerConfigurationViewSlice";
88
import { CompilerRequest } from "../../vscode/utils";
99
import { VmInstall } from "../../../types";
1010
import { updateActiveSection } from "../../mainpage/features/commonSlice";
1111
import { updateActiveTab } from "../../classpath/features/classpathConfigurationViewSlice";
12+
import Hint from "./components/Hint";
1213

1314
const CompilerConfigurationView = (): JSX.Element | null => {
1415

@@ -65,6 +66,9 @@ const CompilerConfigurationView = (): JSX.Element | null => {
6566
generateDebugInfo: message.generateDebugInfo,
6667
storeMethodParamNames: message.storeMethodParamNames
6768
}));
69+
dispatch(flushCompilerSettingsToEffective({
70+
activeProjectIndex,
71+
}));
6872
}
6973
};
7074

@@ -99,14 +103,14 @@ const CompilerConfigurationView = (): JSX.Element | null => {
99103
};
100104

101105
const onClickUseRelease = (e: any) => {
102-
dispatch(updateCompilerSettings({
106+
dispatch(updateCompilerSettings({
103107
activeProjectIndex,
104108
useRelease: e.target.checked
105109
}));
106110
};
107111

108112
const onClickEnablePreview = (e: any) => {
109-
dispatch(updateCompilerSettings({
113+
dispatch(updateCompilerSettings({
110114
activeProjectIndex,
111115
enablePreview: e.target.checked
112116
}));
@@ -153,66 +157,70 @@ const CompilerConfigurationView = (): JSX.Element | null => {
153157
};
154158

155159
return (
156-
<div className="setting-section">
157-
<div className={showReleaseFlag ? "" : "invisible"}>
158-
<VSCodeCheckbox checked={useRelease} onClick={onClickUseRelease}>Use '--release' option for cross-compilation (Java 9 and later)</VSCodeCheckbox>
159-
</div>
160-
<div>
161-
<VSCodeDataGrid gridTemplateColumns="40% 60%">
162-
<VSCodeDataGridRow className={showReleaseFlag && useRelease ? "" : "invisible"}>
163-
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="1">
164-
<span>Bytecode version:</span>
165-
</VSCodeDataGridCell>
166-
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="2">
167-
<VSCodeDropdown value={complianceLevel}>
168-
{jdkLevels(complianceLevel, "compliance", onClickComplianceLevel)}
169-
</VSCodeDropdown>
170-
</VSCodeDataGridCell>
171-
</VSCodeDataGridRow>
172-
<VSCodeDataGridRow className={showReleaseFlag && useRelease ? "invisible" : ""}>
173-
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="1">
174-
<span>Source compatibility:</span>
175-
</VSCodeDataGridCell>
176-
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="2">
177-
<VSCodeDropdown value={sourceLevel}>
178-
{jdkLevels(sourceLevel, "source", onClickSourceLevel)}
179-
</VSCodeDropdown>
180-
</VSCodeDataGridCell>
181-
</VSCodeDataGridRow>
182-
<VSCodeDataGridRow className={showReleaseFlag && useRelease ? "invisible" : ""}>
183-
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="1">
184-
<span>Target compatibility:</span>
185-
</VSCodeDataGridCell>
186-
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="2">
187-
<VSCodeDropdown value={targetLevel}>
188-
{jdkLevels(targetLevel, "target", onClickTargetLevel)}
189-
</VSCodeDropdown>
190-
</VSCodeDataGridCell>
191-
</VSCodeDataGridRow>
192-
</VSCodeDataGrid>
193-
</div>
194-
<div className={`mt-2 mb-2 ${showSourceTargetWarning ? "" : "invisible"}`}>
195-
<span className="setting-section-warning">
196-
Target compatibility must be equal or greater than source compatibility.
197-
</span>
198-
</div>
199-
<div className={`mt-2 mb-2 ${showJdkLevelWarning ? "" : "invisible"}`}>
200-
<span className="setting-section-warning">
201-
Please make sure to have a compatible JDK configured (currently {currentJdkComplianceLevel}). You can change the JDK under the <VSCodeLink href="" onClick={() => onClickChangeJdk()}>JDK Runtime</VSCodeLink> tab.
202-
</span>
203-
</div>
204-
<div className={showPreviewFlag ? "" : "invisible"}>
205-
<VSCodeCheckbox checked={enablePreview} onClick={onClickEnablePreview}>Enable preview features</VSCodeCheckbox>
206-
</div>
207-
<VSCodeDivider className="mt-3"/>
208-
<h4 className="mt-3 mb-3">Class File Generation</h4>
209-
<div>
210-
<VSCodeCheckbox checked={generateDebugInfo} onClick={onClickGenerateDebugInfo}>Generate debugging information</VSCodeCheckbox>
211-
</div>
212-
<div>
213-
<VSCodeCheckbox checked={storeMethodParamNames} onClick={onClickStoreMethodParamNames}>Store information about method parameters</VSCodeCheckbox>
160+
<div className="root">
161+
<div className="setting-section">
162+
<div className={showReleaseFlag ? "" : "invisible"}>
163+
<VSCodeCheckbox checked={useRelease} onClick={onClickUseRelease}>Use '--release' option for cross-compilation (Java 9 and later)</VSCodeCheckbox>
164+
</div>
165+
<div>
166+
<VSCodeDataGrid gridTemplateColumns="40% 60%">
167+
<VSCodeDataGridRow className={showReleaseFlag && useRelease ? "" : "invisible"}>
168+
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="1">
169+
<span>Bytecode version:</span>
170+
</VSCodeDataGridCell>
171+
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="2">
172+
<VSCodeDropdown value={complianceLevel}>
173+
{jdkLevels(complianceLevel, "compliance", onClickComplianceLevel)}
174+
</VSCodeDropdown>
175+
</VSCodeDataGridCell>
176+
</VSCodeDataGridRow>
177+
<VSCodeDataGridRow className={showReleaseFlag && useRelease ? "invisible" : ""}>
178+
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="1">
179+
<span>Source compatibility:</span>
180+
</VSCodeDataGridCell>
181+
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="2">
182+
<VSCodeDropdown value={sourceLevel}>
183+
{jdkLevels(sourceLevel, "source", onClickSourceLevel)}
184+
</VSCodeDropdown>
185+
</VSCodeDataGridCell>
186+
</VSCodeDataGridRow>
187+
<VSCodeDataGridRow className={showReleaseFlag && useRelease ? "invisible" : ""}>
188+
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="1">
189+
<span>Target compatibility:</span>
190+
</VSCodeDataGridCell>
191+
<VSCodeDataGridCell className="flex-center pl-0 pr-0" gridColumn="2">
192+
<VSCodeDropdown value={targetLevel}>
193+
{jdkLevels(targetLevel, "target", onClickTargetLevel)}
194+
</VSCodeDropdown>
195+
</VSCodeDataGridCell>
196+
</VSCodeDataGridRow>
197+
</VSCodeDataGrid>
198+
</div>
199+
<div className={`mt-2 mb-2 ${showSourceTargetWarning ? "" : "invisible"}`}>
200+
<span className="setting-section-warning">
201+
Target compatibility must be equal or greater than source compatibility.
202+
</span>
203+
</div>
204+
<div className={`mt-2 mb-2 ${showJdkLevelWarning ? "" : "invisible"}`}>
205+
<span className="setting-section-warning">
206+
Please make sure to have a compatible JDK configured (currently {currentJdkComplianceLevel}). You can change the JDK under the <VSCodeLink href="" onClick={() => onClickChangeJdk()}>JDK Runtime</VSCodeLink> tab.
207+
</span>
208+
</div>
209+
<div className={showPreviewFlag ? "" : "invisible"}>
210+
<VSCodeCheckbox checked={enablePreview} onClick={onClickEnablePreview}>Enable preview features</VSCodeCheckbox>
211+
</div>
212+
<VSCodeDivider className="mt-3" />
213+
<h4 className="mt-3 mb-3">Class File Generation</h4>
214+
<div>
215+
<VSCodeCheckbox checked={generateDebugInfo} onClick={onClickGenerateDebugInfo}>Generate debugging information</VSCodeCheckbox>
216+
</div>
217+
<div>
218+
<VSCodeCheckbox checked={storeMethodParamNames} onClick={onClickStoreMethodParamNames}>Store information about method parameters</VSCodeCheckbox>
219+
</div>
214220
</div>
215-
</div>)
221+
<Hint />
222+
</div>
223+
)
216224
}
217225

218226
function parseJavaVersion(version: string): number {

src/project-settings/assets/compiler/features/compilerConfigurationViewSlice.tsx

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ export const compilerConfigurationViewSlice = createSlice({
1010
availableComplianceLevels: [] as string[],
1111
},
1212
data: {
13+
effective: {
14+
useRelease: [] as boolean[],
15+
enablePreview: [] as boolean[],
16+
complianceLevel: [] as string[],
17+
sourceLevel: [] as string[],
18+
targetLevel: [] as string[],
19+
generateDebugInfo: [] as boolean[],
20+
storeMethodParamNames: [] as boolean[],
21+
},
1322
useRelease: [] as boolean[],
1423
enablePreview: [] as boolean[],
1524
complianceLevel: [] as string[],
@@ -21,6 +30,8 @@ export const compilerConfigurationViewSlice = createSlice({
2130
},
2231
reducers: {
2332
initializeCompilerData: (state, action) => {
33+
state.ui.availableComplianceLevels = [];
34+
2435
const projectNum = action.payload.projectsNum;
2536
state.data.useRelease = Array(projectNum).fill(false);
2637
state.data.enablePreview = Array(projectNum).fill(false);
@@ -29,7 +40,14 @@ export const compilerConfigurationViewSlice = createSlice({
2940
state.data.targetLevel = Array(projectNum).fill("");
3041
state.data.generateDebugInfo = Array(projectNum).fill(false);
3142
state.data.storeMethodParamNames = Array(projectNum).fill(false);
32-
state.ui.availableComplianceLevels = [];
43+
44+
state.data.effective.useRelease = Array(projectNum).fill(false);
45+
state.data.effective.enablePreview = Array(projectNum).fill(false);
46+
state.data.effective.complianceLevel = Array(projectNum).fill("");
47+
state.data.effective.sourceLevel = Array(projectNum).fill("");
48+
state.data.effective.targetLevel = Array(projectNum).fill("");
49+
state.data.effective.generateDebugInfo = Array(projectNum).fill(false);
50+
state.data.effective.storeMethodParamNames = Array(projectNum).fill(false);
3351
},
3452
updateAvailableComplianceLevels: (state, action) => {
3553
state.ui.availableComplianceLevels = action.payload.availableComplianceLevels;
@@ -58,13 +76,24 @@ export const compilerConfigurationViewSlice = createSlice({
5876
state.data.storeMethodParamNames[activeProjectIndex] = action.payload.storeMethodParamNames;
5977
}
6078
},
79+
flushCompilerSettingsToEffective: (state, action) => {
80+
const activeProjectIndex = action.payload.activeProjectIndex;
81+
state.data.effective.useRelease[activeProjectIndex] = state.data.useRelease[activeProjectIndex];
82+
state.data.effective.enablePreview[activeProjectIndex] = state.data.enablePreview[activeProjectIndex];
83+
state.data.effective.complianceLevel[activeProjectIndex] = state.data.complianceLevel[activeProjectIndex];
84+
state.data.effective.sourceLevel[activeProjectIndex] = state.data.sourceLevel[activeProjectIndex];
85+
state.data.effective.targetLevel[activeProjectIndex] = state.data.targetLevel[activeProjectIndex];
86+
state.data.effective.generateDebugInfo[activeProjectIndex] = state.data.generateDebugInfo[activeProjectIndex];
87+
state.data.effective.storeMethodParamNames[activeProjectIndex] = state.data.storeMethodParamNames[activeProjectIndex];
88+
},
6189
},
6290
});
6391

6492
export const {
6593
initializeCompilerData,
6694
updateAvailableComplianceLevels,
6795
updateCompilerSettings,
96+
flushCompilerSettingsToEffective,
6897
} = compilerConfigurationViewSlice.actions;
6998

7099
export default compilerConfigurationViewSlice.reducer;

0 commit comments

Comments
 (0)