|
| 1 | +// Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | +// Licensed under the MIT license. |
| 3 | + |
| 4 | +import { VSCodeCheckbox, VSCodeDivider, VSCodeDropdown, VSCodeOption } from "@vscode/webview-ui-toolkit/react"; |
| 5 | +import React, { Dispatch, useEffect } from "react"; |
| 6 | +import { useDispatch, useSelector } from "react-redux"; |
| 7 | +import { loadCompilerSettings, updateAvailableComplianceLevels, updateComplianceLevel, updateEnablePreview, updateGenerateDebugInfo, updateSourceLevel, updateStoreMethodParamNames, updateTargetLevel, updateUseRelease } from "./compilerConfigurationViewSlice"; |
| 8 | +import { CompilerRequest } from "../../vscode/utils"; |
| 9 | +import { VmInstall } from "../../../types"; |
| 10 | + |
| 11 | +const CompilerConfigurationView = (): JSX.Element | null => { |
| 12 | + const projects: any[] = useSelector((state: any) => state.commonConfig.data.projects); |
| 13 | + const activeProjectIndex: number = useSelector((state: any) => state.commonConfig.ui.activeProjectIndex); |
| 14 | + const useRelease: boolean = useSelector((state: any) => state.compilerConfig.data.useRelease[activeProjectIndex]); |
| 15 | + const enablePreview: boolean = useSelector((state: any) => state.compilerConfig.data.enablePreview[activeProjectIndex]); |
| 16 | + let complianceLevel: string = useSelector((state: any) => state.compilerConfig.data.complianceLevel[activeProjectIndex]); |
| 17 | + let sourceLevel: string = useSelector((state: any) => state.compilerConfig.data.sourceLevel[activeProjectIndex]); |
| 18 | + let targetLevel: string = useSelector((state: any) => state.compilerConfig.data.targetLevel[activeProjectIndex]); |
| 19 | + const generateDebugInfo: boolean = useSelector((state: any) => state.compilerConfig.data.generateDebugInfo[activeProjectIndex]); |
| 20 | + const storeMethodParamNames: boolean = useSelector((state: any) => state.compilerConfig.data.storeMethodParamNames[activeProjectIndex]); |
| 21 | + const availableComplianceLevels: string[] = useSelector((state: any) => state.compilerConfig.ui.availableComplianceLevels); |
| 22 | + |
| 23 | + // Find the version of current JDK to determine the max compliance level that can be set. |
| 24 | + const vmInstalls: VmInstall[] = useSelector((state: any) => state.classpathConfig.data.vmInstalls); |
| 25 | + const activeVmInstallPath: string = useSelector((state: any) => state.classpathConfig.data.activeVmInstallPath[activeProjectIndex]); |
| 26 | + const activeVmInstall: VmInstall | undefined = vmInstalls.find((vmInstall: VmInstall) => vmInstall.path === activeVmInstallPath); |
| 27 | + let currentJdkComplianceLevel: number = Number.MAX_SAFE_INTEGER; |
| 28 | + if (activeVmInstall?.version) { |
| 29 | + currentJdkComplianceLevel = parseJavaVersion(activeVmInstall.version); |
| 30 | + } |
| 31 | + |
| 32 | + // compliance/source/target level cannot be higher than current jdk level. |
| 33 | + if (Number(complianceLevel) > currentJdkComplianceLevel) { |
| 34 | + complianceLevel = currentJdkComplianceLevel.toString(); |
| 35 | + } |
| 36 | + if (Number(sourceLevel) > currentJdkComplianceLevel) { |
| 37 | + sourceLevel = currentJdkComplianceLevel.toString(); |
| 38 | + } |
| 39 | + if (Number(targetLevel) > currentJdkComplianceLevel) { |
| 40 | + targetLevel = currentJdkComplianceLevel.toString(); |
| 41 | + } |
| 42 | + |
| 43 | + // Release flag only supported on Java 9+. |
| 44 | + const showReleaseFlag: boolean = currentJdkComplianceLevel >= 9; |
| 45 | + |
| 46 | + // Hide the preview checkbox if the current JDK version is not latest & preview flag is already disabled. |
| 47 | + const showPreviewFlag: boolean = !!(availableComplianceLevels.find((level) => { |
| 48 | + return Number(level) > currentJdkComplianceLevel; |
| 49 | + }) === undefined) || enablePreview; |
| 50 | + |
| 51 | + const showSourceTargetWarning: boolean = !useRelease && (sourceLevel !== "" && targetLevel !== "" && Number(sourceLevel) > Number(targetLevel)); |
| 52 | + |
| 53 | + const dispatch: Dispatch<any> = useDispatch(); |
| 54 | + |
| 55 | + const onMessage = (event: any) => { |
| 56 | + const message = event.data; |
| 57 | + if (message.command === "compiler.onDidGetAvailableComplianceLevels") { |
| 58 | + dispatch(updateAvailableComplianceLevels({ |
| 59 | + availableComplianceLevels: message.complianceLevels |
| 60 | + })); |
| 61 | + } else if (message.command === "compiler.onDidGetCompilerSettings") { |
| 62 | + dispatch(loadCompilerSettings({ |
| 63 | + activeProjectIndex, |
| 64 | + useRelease: message.useRelease, |
| 65 | + enablePreview: message.enablePreview, |
| 66 | + complianceLevel: message.complianceLevel, |
| 67 | + sourceLevel: message.sourceLevel, |
| 68 | + targetLevel: message.targetLevel, |
| 69 | + generateDebugInfo: message.generateDebugInfo, |
| 70 | + storeMethodParamNames: message.storeMethodParamNames |
| 71 | + })); |
| 72 | + } |
| 73 | + }; |
| 74 | + |
| 75 | + useEffect(() => { |
| 76 | + window.addEventListener("message", onMessage); |
| 77 | + if (availableComplianceLevels?.length === 0) { |
| 78 | + CompilerRequest.onWillGetAvailableComplianceLevels(); |
| 79 | + } |
| 80 | + if (sourceLevel === "") { |
| 81 | + CompilerRequest.onWillGetCompilerSettings(projects[activeProjectIndex].rootPath); |
| 82 | + } |
| 83 | + return () => { |
| 84 | + window.removeEventListener("message", onMessage); |
| 85 | + } |
| 86 | + }, []); |
| 87 | + |
| 88 | + const jdkLevels = (selectedLevel: string, label: string, onClick: (value: string) => void) => { |
| 89 | + return availableComplianceLevels.map((level) => { |
| 90 | + if (Number(level) > currentJdkComplianceLevel) { |
| 91 | + return null; |
| 92 | + } |
| 93 | + |
| 94 | + return ( |
| 95 | + <VSCodeOption |
| 96 | + className="setting-section-option" |
| 97 | + key={`${label}-${level}`} |
| 98 | + value={level} |
| 99 | + selected={level === selectedLevel} |
| 100 | + onClick={() => onClick(level)} |
| 101 | + > |
| 102 | + <span>{level}</span> |
| 103 | + </VSCodeOption> |
| 104 | + ); |
| 105 | + }).filter((option) => option !== null); |
| 106 | + }; |
| 107 | + |
| 108 | + const onClickUseRelease = (e: any) => { |
| 109 | + dispatch(updateUseRelease({ |
| 110 | + activeProjectIndex, |
| 111 | + useRelease: e.target.checked |
| 112 | + })); |
| 113 | + }; |
| 114 | + |
| 115 | + const onClickEnablePreview = (e: any) => { |
| 116 | + dispatch(updateEnablePreview({ |
| 117 | + activeProjectIndex, |
| 118 | + enablePreview: e.target.checked |
| 119 | + })); |
| 120 | + }; |
| 121 | + |
| 122 | + const onClickComplianceLevel = (value: string) => { |
| 123 | + dispatch(updateComplianceLevel({ |
| 124 | + activeProjectIndex, |
| 125 | + complianceLevel: value |
| 126 | + })); |
| 127 | + }; |
| 128 | + |
| 129 | + const onClickSourceLevel = (value: string) => { |
| 130 | + dispatch(updateSourceLevel({ |
| 131 | + activeProjectIndex, |
| 132 | + sourceLevel: value |
| 133 | + })); |
| 134 | + }; |
| 135 | + |
| 136 | + const onClickTargetLevel = (value: string) => { |
| 137 | + dispatch(updateTargetLevel({ |
| 138 | + activeProjectIndex, |
| 139 | + targetLevel: value |
| 140 | + })); |
| 141 | + }; |
| 142 | + |
| 143 | + const onClickGenerateDebugInfo = (e: any) => { |
| 144 | + dispatch(updateGenerateDebugInfo({ |
| 145 | + activeProjectIndex, |
| 146 | + generateDebugInfo: e.target.checked |
| 147 | + })); |
| 148 | + }; |
| 149 | + |
| 150 | + const onClickStoreMethodParamNames = (e: any) => { |
| 151 | + dispatch(updateStoreMethodParamNames({ |
| 152 | + activeProjectIndex, |
| 153 | + storeMethodParamNames: e.target.checked |
| 154 | + })); |
| 155 | + }; |
| 156 | + |
| 157 | + return ( |
| 158 | + <div className="setting-section"> |
| 159 | + <h4 className="mt-3 mb-3">JDK Compliance</h4> |
| 160 | + <div className={showReleaseFlag ? "" : "invisible"}> |
| 161 | + <VSCodeCheckbox checked={useRelease} onClick={onClickUseRelease}>Use '--release' option</VSCodeCheckbox> |
| 162 | + </div> |
| 163 | + <div className={`flex-center mt-1 mb-2 ${showReleaseFlag && useRelease ? "" : "invisible"}`}> |
| 164 | + <span className="mr-1">Compliance level:</span> |
| 165 | + <VSCodeDropdown value={complianceLevel}> |
| 166 | + {jdkLevels(complianceLevel, "compliance", onClickComplianceLevel)} |
| 167 | + </VSCodeDropdown> |
| 168 | + </div> |
| 169 | + <div className={`flex-center mt-1 mb-2 ${showReleaseFlag && useRelease ? "invisible" : ""}`}> |
| 170 | + <span className="mr-1">Source compatibility:</span> |
| 171 | + <VSCodeDropdown value={sourceLevel}> |
| 172 | + {jdkLevels(sourceLevel, "source", onClickSourceLevel)} |
| 173 | + </VSCodeDropdown> |
| 174 | + </div> |
| 175 | + <div className={`flex-center mb-2 ${showReleaseFlag && useRelease ? "invisible" : ""}`}> |
| 176 | + <span className="mr-1">Target compatibility:</span> |
| 177 | + <VSCodeDropdown value={targetLevel}> |
| 178 | + {jdkLevels(targetLevel, "target", onClickTargetLevel)} |
| 179 | + </VSCodeDropdown> |
| 180 | + </div> |
| 181 | + <div className={`mb-2 ${showSourceTargetWarning ? "" : "invisible"}`}> |
| 182 | + <span className="setting-section-warning"> |
| 183 | + Target compatibility must be equal or greater than source compatibility. |
| 184 | + </span> |
| 185 | + </div> |
| 186 | + <div className={showPreviewFlag ? "" : "invisible"}> |
| 187 | + <VSCodeCheckbox checked={enablePreview} onClick={onClickEnablePreview}>Enable preview features</VSCodeCheckbox> |
| 188 | + </div> |
| 189 | + <VSCodeDivider className="mt-3"/> |
| 190 | + <h4 className="mt-3 mb-3">Class File Generation</h4> |
| 191 | + <div> |
| 192 | + <VSCodeCheckbox checked={generateDebugInfo} onClick={onClickGenerateDebugInfo}>Generate debugging information</VSCodeCheckbox> |
| 193 | + </div> |
| 194 | + <div> |
| 195 | + <VSCodeCheckbox checked={storeMethodParamNames} onClick={onClickStoreMethodParamNames}>Store information about method parameters</VSCodeCheckbox> |
| 196 | + </div> |
| 197 | + </div>) |
| 198 | +} |
| 199 | + |
| 200 | +function parseJavaVersion(version: string): number { |
| 201 | + if (!version.includes(".")) { |
| 202 | + return Number(version); |
| 203 | + } else if (version.startsWith("1.")) { |
| 204 | + return Number("1." + version.split(".")[1]); |
| 205 | + } else { |
| 206 | + return Number(version.split(".")[0]); |
| 207 | + } |
| 208 | +} |
| 209 | + |
| 210 | +export default CompilerConfigurationView; |
0 commit comments