From 0a10bd37e25849872a2a435522ee695172768141 Mon Sep 17 00:00:00 2001 From: Louis Vignier Date: Mon, 18 Mar 2024 18:24:45 +0100 Subject: [PATCH] [compiler] Use UI DSL in CompilerConfigurable GitOrigin-RevId: 8e337ec0932da57c78ce124816e4641459235cee --- .../options/CompilerConfigurable.java | 9 +- .../options/CompilerOptionsPanel.form | 228 ------------- .../options/CompilerUIConfigurable.java | 307 +----------------- .../options/CompilerUIConfigurableKt.kt | 276 ++++++++++++++++ .../messages/JavaCompilerBundle.properties | 35 +- 5 files changed, 312 insertions(+), 543 deletions(-) delete mode 100644 java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form create mode 100644 java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurableKt.kt diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java index 1dc1d6ffaf41..ea14d628e3b7 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerConfigurable.java @@ -10,13 +10,13 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; -public class CompilerConfigurable implements SearchableConfigurable.Parent, Configurable.NoScroll { +public class CompilerConfigurable implements SearchableConfigurable.Parent { static final String CONFIGURABLE_ID = "project.propCompiler"; - private final CompilerUIConfigurable myCompilerUIConfigurable; + private final CompilerUIConfigurableKt myCompilerUIConfigurable; public CompilerConfigurable(Project project) { - myCompilerUIConfigurable = new CompilerUIConfigurable(project); + myCompilerUIConfigurable = new CompilerUIConfigurableKt(project); } @Override @@ -70,7 +70,8 @@ public class CompilerConfigurable implements SearchableConfigurable.Parent, Conf return new Configurable[0]; } - @NotNull CompilerUIConfigurable getCompilerUIConfigurable() { + @NotNull + CompilerUIConfigurableKt getCompilerUIConfigurable() { return myCompilerUIConfigurable; } } diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form b/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form deleted file mode 100644 index 82f1b81b0196..000000000000 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerOptionsPanel.form +++ /dev/null @@ -1,228 +0,0 @@ - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java index 209a10c38277..93b45d24c735 100644 --- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java @@ -1,194 +1,23 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.compiler.options; -import com.intellij.codeInsight.NullableNotNullDialog; -import com.intellij.codeInsight.NullableNotNullManager; -import com.intellij.compiler.CompilerConfiguration; import com.intellij.compiler.CompilerConfigurationImpl; -import com.intellij.compiler.CompilerWorkspaceConfiguration; import com.intellij.compiler.MalformedPatternException; -import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration; -import com.intellij.compiler.server.BuildManager; -import com.intellij.ide.PowerSaveMode; import com.intellij.openapi.compiler.JavaCompilerBundle; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.SearchableConfigurable; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.ui.DocumentAdapter; -import com.intellij.ui.Gray; -import com.intellij.ui.JBColor; -import com.intellij.ui.RawCommandLineEditor; -import com.intellij.ui.components.JBLabel; -import com.intellij.ui.components.fields.ExpandableTextField; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.execution.ParametersListUtil; -import com.intellij.util.ui.UIUtil; -import com.intellij.xml.util.XmlStringUtil; -import org.jetbrains.annotations.NotNull; -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import java.awt.*; -import java.util.List; import java.util.*; import static com.intellij.compiler.options.CompilerOptionsFilter.Setting; -public class CompilerUIConfigurable implements SearchableConfigurable, Configurable.NoScroll { - private static final Logger LOG = Logger.getInstance(CompilerUIConfigurable.class); +public final class CompilerUIConfigurable { static final Set EXTERNAL_BUILD_SETTINGS = EnumSet.of( Setting.EXTERNAL_BUILD, Setting.AUTO_MAKE, Setting.PARALLEL_COMPILATION, Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE, Setting.HEAP_SIZE, Setting.COMPILER_VM_OPTIONS ); - private final Set myDisabledSettings = EnumSet.noneOf(Setting.class); - - private JPanel myPanel; - private final Project myProject; - - private RawCommandLineEditor myResourcePatternsField; - private JCheckBox myCbClearOutputDirectory; - private JCheckBox myCbAssertNotNull; - private JBLabel myPatternLegendLabel; - private JCheckBox myCbAutoShowFirstError; - private JCheckBox myCbDisplayNotificationPopup; - private JCheckBox myCbEnableAutomake; - private JCheckBox myCbParallelCompilation; - private JTextField mySharedHeapSizeField; - private ExpandableTextField mySharedVMOptionsField; - private JTextField myHeapSizeField; - private ExpandableTextField myVMOptionsField; - private JLabel mySharedHeapSizeLabel; - private JLabel mySharedVMOptionsLabel; - private JLabel myHeapSizeLabel; - private JLabel myVMOptionsLabel; - private JCheckBox myCbRebuildOnDependencyChange; - private JLabel myResourcePatternsLabel; - private JLabel myEnableAutomakeLegendLabel; - private JLabel myParallelCompilationLegendLabel; - private JButton myConfigureAnnotations; - private JLabel myWarningLabel; - private JPanel myAssertNotNullPanel; - - public CompilerUIConfigurable(@NotNull final Project project) { - myProject = project; - - myPatternLegendLabel.setText(XmlStringUtil.wrapInHtml(JavaCompilerBundle.message("compiler.ui.pattern.legend.text"))); - - /*"All source files located in the generated sources output directory WILL BE EXCLUDED from annotation processing. " +*/ - myWarningLabel.setText(JavaCompilerBundle.message("settings.warning")); - myWarningLabel.setFont(myWarningLabel.getFont().deriveFont(Font.BOLD)); - - myPatternLegendLabel.setForeground(new JBColor(Gray._50, Gray._130)); - tweakControls(project); - DocumentAdapter updateStateListener = new DocumentAdapter() { - @Override - protected void textChanged(@NotNull DocumentEvent e) { - mySharedVMOptionsField.setEditable(myVMOptionsField.getDocument().getLength() == 0); - mySharedVMOptionsField.setBackground(myVMOptionsField.getDocument().getLength() == 0 ? - UIUtil.getTextFieldBackground() : UIUtil.getTextFieldDisabledBackground()); - mySharedHeapSizeField.setEnabled( - myHeapSizeField.getDocument().getLength() == 0 && - ContainerUtil.find(ParametersListUtil.parse(myVMOptionsField.getText()), - s -> StringUtil.startsWithIgnoreCase(s, "-Xmx")) == null - ); - } - }; - myVMOptionsField.getDocument().addDocumentListener(updateStateListener); - myHeapSizeField.getDocument().addDocumentListener(updateStateListener); - myConfigureAnnotations.addActionListener(e -> { - NullableNotNullDialog.showDialogWithInstrumentationOptions(myProject); - myCbAssertNotNull.setSelected(!NullableNotNullManager.getInstance(myProject).getInstrumentedNotNulls().isEmpty()); - }); - } - - private void tweakControls(@NotNull Project project) { - List managers = CompilerOptionsFilter.EP_NAME.getExtensionList(); - boolean showExternalBuildSetting = true; - for (CompilerOptionsFilter manager : managers) { - showExternalBuildSetting = manager.isAvailable(Setting.EXTERNAL_BUILD, project); - if (!showExternalBuildSetting) { - myDisabledSettings.add(Setting.EXTERNAL_BUILD); - break; - } - } - - for (Setting setting : Setting.values()) { - if (!showExternalBuildSetting && EXTERNAL_BUILD_SETTINGS.contains(setting)) { - // Disable all nested external compiler settings if 'use external build' is unavailable. - myDisabledSettings.add(setting); - } - else { - for (CompilerOptionsFilter manager : managers) { - if (!manager.isAvailable(setting, project)) { - myDisabledSettings.add(setting); - break; - } - } - } - } - - Map> controls = Map.ofEntries( - Map.entry(Setting.RESOURCE_PATTERNS, List.of(myResourcePatternsLabel, myResourcePatternsField, myPatternLegendLabel)), - Map.entry(Setting.CLEAR_OUTPUT_DIR_ON_REBUILD, Collections.singleton(myCbClearOutputDirectory)), - Map.entry(Setting.ADD_NOT_NULL_ASSERTIONS, Collections.singleton(myAssertNotNullPanel)), - Map.entry(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR, Collections.singleton(myCbAutoShowFirstError)), - Map.entry(Setting.DISPLAY_NOTIFICATION_POPUP, Collections.singleton(myCbDisplayNotificationPopup)), - Map.entry(Setting.AUTO_MAKE, List.of(myCbEnableAutomake, myEnableAutomakeLegendLabel)), - Map.entry(Setting.PARALLEL_COMPILATION, List.of(myCbParallelCompilation, myParallelCompilationLegendLabel)), - Map.entry(Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE, List.of(myCbRebuildOnDependencyChange)), - Map.entry(Setting.HEAP_SIZE, List.of(myHeapSizeLabel, myHeapSizeField, mySharedHeapSizeLabel, mySharedHeapSizeField)), - Map.entry(Setting.COMPILER_VM_OPTIONS, List.of(myVMOptionsLabel, myVMOptionsField, mySharedVMOptionsLabel, mySharedVMOptionsField))); - - for (Setting setting : myDisabledSettings) { - Collection components = controls.get(setting); - if (components != null) { - for (JComponent component : components) { - component.setVisible(false); - } - } - } - } - - @Override - public void reset() { - - final CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject); - final CompilerWorkspaceConfiguration workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(myProject); - myCbAutoShowFirstError.setSelected(workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR); - myCbDisplayNotificationPopup.setSelected(workspaceConfiguration.DISPLAY_NOTIFICATION_POPUP); - myCbClearOutputDirectory.setSelected(workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY); - myCbAssertNotNull.setSelected(configuration.isAddNotNullAssertions()); - myCbEnableAutomake.setSelected(workspaceConfiguration.MAKE_PROJECT_ON_SAVE); - myCbParallelCompilation.setSelected(configuration.isParallelCompilationEnabled()); - myCbRebuildOnDependencyChange.setSelected(workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE); - int heapSize = workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE; - myHeapSizeField.setText(heapSize > 0 ? String.valueOf(heapSize) : ""); - final int javacPreferred = JavacConfiguration.getOptions(myProject, JavacConfiguration.class).MAXIMUM_HEAP_SIZE; // for compatibility with older projects - mySharedHeapSizeField.setText(String.valueOf(configuration.getBuildProcessHeapSize(javacPreferred))); - final String options = workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS; - myVMOptionsField.setText(options == null ? "" : options.trim()); - mySharedVMOptionsField.setText(configuration.getBuildProcessVMOptions()); - - configuration.convertPatterns(); - - myResourcePatternsField.setText(patternsToString(configuration.getResourceFilePatterns())); - - if (PowerSaveMode.isEnabled()) { - myEnableAutomakeLegendLabel.setText(JavaCompilerBundle.message("disabled.in.power.save.mode")); - myEnableAutomakeLegendLabel.setFont(myEnableAutomakeLegendLabel.getFont().deriveFont(Font.BOLD)); - } - else { - myEnableAutomakeLegendLabel.setText(JavaCompilerBundle.message("only.works.while.not.running.debugging")); - myEnableAutomakeLegendLabel.setFont(myEnableAutomakeLegendLabel.getFont().deriveFont(Font.PLAIN)); - } - } - - private static String patternsToString(final String[] patterns) { + static String patternsToString(final String[] patterns) { final StringBuilder extensionsString = new StringBuilder(); for (int idx = 0; idx < patterns.length; idx++) { if (idx > 0) { @@ -199,60 +28,6 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura return extensionsString.toString(); } - @Override - public void apply() throws ConfigurationException { - - CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject); - final CompilerWorkspaceConfiguration workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(myProject); - if (!myDisabledSettings.contains(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR)) { - workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR = myCbAutoShowFirstError.isSelected(); - } - if (!myDisabledSettings.contains(Setting.DISPLAY_NOTIFICATION_POPUP)) { - workspaceConfiguration.DISPLAY_NOTIFICATION_POPUP = myCbDisplayNotificationPopup.isSelected(); - } - if (!myDisabledSettings.contains(Setting.CLEAR_OUTPUT_DIR_ON_REBUILD)) { - workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY = myCbClearOutputDirectory.isSelected(); - } - if (!myDisabledSettings.contains(Setting.EXTERNAL_BUILD)) { - if (!myDisabledSettings.contains(Setting.AUTO_MAKE)) { - workspaceConfiguration.MAKE_PROJECT_ON_SAVE = myCbEnableAutomake.isSelected(); - } - if (!myDisabledSettings.contains(Setting.PARALLEL_COMPILATION) && configuration.isParallelCompilationEnabled() != myCbParallelCompilation.isSelected()) { - configuration.setParallelCompilationEnabled(myCbParallelCompilation.isSelected()); - } - if (!myDisabledSettings.contains(Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE)) { - workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE = myCbRebuildOnDependencyChange.isSelected(); - } - if (!myDisabledSettings.contains(Setting.HEAP_SIZE)) { - try { - String heapSizeText = myHeapSizeField.getText().trim(); - workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE = heapSizeText.isEmpty() ? 0 : Integer.parseInt(heapSizeText); - configuration.setBuildProcessHeapSize(Integer.parseInt(mySharedHeapSizeField.getText().trim())); - } - catch (NumberFormatException ignored) { - LOG.info(ignored); - } - } - if (!myDisabledSettings.contains(Setting.COMPILER_VM_OPTIONS)) { - workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS = myVMOptionsField.getText().trim(); - configuration.setBuildProcessVMOptions(mySharedVMOptionsField.getText().trim()); - } - } - - if (!myDisabledSettings.contains(Setting.ADD_NOT_NULL_ASSERTIONS)) { - configuration.setAddNotNullAssertions(myCbAssertNotNull.isSelected()); - } - if (!myDisabledSettings.contains(Setting.RESOURCE_PATTERNS)) { - configuration.removeResourceFilePatterns(); - String extensionString = myResourcePatternsField.getText().trim(); - applyResourcePatterns(extensionString, configuration); - } - - if (!myProject.isDefault()) { - BuildManager.getInstance().clearState(myProject); - } - } - public static void applyResourcePatterns(String extensionString, final CompilerConfigurationImpl configuration) throws ConfigurationException { StringTokenizer tokenizer = new StringTokenizer(extensionString, ";", false); @@ -269,83 +44,19 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura } if (!errors.isEmpty()) { - final StringBuilder pattersnsWithErrors = new StringBuilder(); + final StringBuilder patternsWithError = new StringBuilder(); for (final Object error : errors) { String[] pair = (String[])error; - pattersnsWithErrors.append("\n"); - pattersnsWithErrors.append(pair[0]); - pattersnsWithErrors.append(": "); - pattersnsWithErrors.append(pair[1]); + patternsWithError.append("\n"); + patternsWithError.append(pair[0]); + patternsWithError.append(": "); + patternsWithError.append(pair[1]); } throw new ConfigurationException( - JavaCompilerBundle.message("error.compiler.configurable.malformed.patterns", pattersnsWithErrors.toString()), JavaCompilerBundle - .message("bad.resource.patterns.dialog.title") + JavaCompilerBundle.message("error.compiler.configurable.malformed.patterns", patternsWithError.toString()), + JavaCompilerBundle.message("bad.resource.patterns.dialog.title") ); } } - - @Override - public boolean isModified() { - final CompilerConfiguration configuration = CompilerConfiguration.getInstance(myProject); - final CompilerWorkspaceConfiguration workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(myProject); - boolean isModified = !myDisabledSettings.contains(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR) - && ComparingUtils.isModified(myCbAutoShowFirstError, workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR); - isModified |= !myDisabledSettings.contains(Setting.DISPLAY_NOTIFICATION_POPUP) - && ComparingUtils.isModified(myCbDisplayNotificationPopup, workspaceConfiguration.DISPLAY_NOTIFICATION_POPUP); - isModified |= !myDisabledSettings.contains(Setting.AUTO_MAKE) - && ComparingUtils.isModified(myCbEnableAutomake, workspaceConfiguration.MAKE_PROJECT_ON_SAVE); - isModified |= !myDisabledSettings.contains(Setting.PARALLEL_COMPILATION) - && ComparingUtils.isModified(myCbParallelCompilation, configuration.isParallelCompilationEnabled()); - isModified |= !myDisabledSettings.contains(Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE) - && ComparingUtils.isModified(myCbRebuildOnDependencyChange, workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE); - isModified |= !myDisabledSettings.contains(Setting.HEAP_SIZE) - && ComparingUtils.isModified(myHeapSizeField, 0, workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE); - isModified |= !myDisabledSettings.contains(Setting.COMPILER_VM_OPTIONS) - && ComparingUtils.isModified(myVMOptionsField, workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS); - - final CompilerConfigurationImpl compilerConfiguration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject); - isModified |= !myDisabledSettings.contains(Setting.HEAP_SIZE) - && ComparingUtils.isModified(mySharedHeapSizeField, compilerConfiguration.getBuildProcessHeapSize(0)); - isModified |= !myDisabledSettings.contains(Setting.COMPILER_VM_OPTIONS) - && ComparingUtils.isModified(mySharedVMOptionsField, compilerConfiguration.getBuildProcessVMOptions()); - isModified |= !myDisabledSettings.contains(Setting.ADD_NOT_NULL_ASSERTIONS) - && ComparingUtils.isModified(myCbAssertNotNull, compilerConfiguration.isAddNotNullAssertions()); - isModified |= !myDisabledSettings.contains(Setting.CLEAR_OUTPUT_DIR_ON_REBUILD) - && ComparingUtils.isModified(myCbClearOutputDirectory, workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY); - isModified |= !myDisabledSettings.contains(Setting.RESOURCE_PATTERNS) - && ComparingUtils.isModified(myResourcePatternsField, patternsToString(compilerConfiguration.getResourceFilePatterns())); - - return isModified; - } - - @Override - public String getDisplayName() { - return JavaCompilerBundle.message("configurable.CompilerUIConfigurable.display.name"); - } - - @Override - public String getHelpTopic() { - return null; - } - - @Override - @NotNull - public String getId() { - return "compiler.general"; - } - - @Override - public JComponent createComponent() { - return myPanel; - } - - JCheckBox getBuildOnSaveCheckBox() { - return myCbEnableAutomake; - } - - private void createUIComponents() { - myResourcePatternsField = new RawCommandLineEditor(ParametersListUtil.COLON_LINE_PARSER, ParametersListUtil.COLON_LINE_JOINER); - myResourcePatternsField.setDialogCaption("Resource patterns"); - } } diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurableKt.kt b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurableKt.kt new file mode 100644 index 000000000000..b1c1424a04f7 --- /dev/null +++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurableKt.kt @@ -0,0 +1,276 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.compiler.options + +import com.intellij.codeInsight.NullableNotNullDialog +import com.intellij.codeInsight.NullableNotNullManager +import com.intellij.compiler.CompilerConfiguration +import com.intellij.compiler.CompilerConfigurationImpl +import com.intellij.compiler.CompilerWorkspaceConfiguration +import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration +import com.intellij.compiler.options.CompilerOptionsFilter.Setting +import com.intellij.ide.PowerSaveMode +import com.intellij.openapi.compiler.JavaCompilerBundle +import com.intellij.openapi.options.DslConfigurableBase +import com.intellij.openapi.options.SearchableConfigurable +import com.intellij.openapi.project.Project +import com.intellij.openapi.util.NlsContexts +import com.intellij.openapi.util.text.StringUtil +import com.intellij.ui.DocumentAdapter +import com.intellij.ui.RawCommandLineEditor +import com.intellij.ui.components.fields.ExpandableTextField +import com.intellij.ui.dsl.builder.AlignX +import com.intellij.ui.dsl.builder.BottomGap +import com.intellij.ui.dsl.builder.Cell +import com.intellij.ui.dsl.builder.HyperlinkEventAction +import com.intellij.ui.dsl.builder.RightGap +import com.intellij.ui.dsl.builder.panel +import com.intellij.util.execution.ParametersListUtil +import com.intellij.util.ui.UIUtil +import org.jetbrains.annotations.NonNls +import java.util.EnumSet +import javax.swing.JButton +import javax.swing.JCheckBox +import javax.swing.JComponent +import javax.swing.JTextField + +class CompilerUIConfigurableKt(val project: Project) : DslConfigurableBase(), SearchableConfigurable { + val disabledSettings: MutableSet = EnumSet.noneOf(Setting::class.java) + + lateinit var resourcePatternsField: RawCommandLineEditor + + lateinit var cbClearOutputDirectory: JCheckBox + lateinit var cbAssertNotNull: JCheckBox + + lateinit var cbAutoShowFirstError: JCheckBox + lateinit var cbDisplayNotificationPopup: JCheckBox + lateinit var cbEnableAutomakeCell: Cell + lateinit var cbEnableAutomake: JCheckBox + lateinit var cbParallelCompilation: JCheckBox + + lateinit var sharedHeapSizeField: JTextField + lateinit var sharedVMOptionsField: ExpandableTextField + lateinit var heapSizeField: JTextField + lateinit var vmOptionsField: ExpandableTextField + + lateinit var cbRebuildOnDependencyChange: JCheckBox + + lateinit var configureAnnotations: JButton + + override fun createPanel() = panel { + row(JavaCompilerBundle.message("label.option.resource.patterns.text")) { + resourcePatternsField = cell(RawCommandLineEditor(ParametersListUtil.COLON_LINE_PARSER, ParametersListUtil.COLON_LINE_JOINER)) + .comment(JavaCompilerBundle.message("compiler.ui.pattern.legend.text")) + .resizableColumn() + .align(AlignX.FILL) + .component + contextHelp(JavaCompilerBundle.message("compiler.ui.pattern.context.help"), JavaCompilerBundle.message("compiler.ui.pattern.context.help.title")) + } + .bottomGap(BottomGap.SMALL) + + panel { + row { + cbClearOutputDirectory = checkBox(JavaCompilerBundle.message("label.option.clear.output.directory.on.rebuild")) + .comment(JavaCompilerBundle.message("settings.warning")) + .component + } + row { + cbAssertNotNull = checkBox(JavaCompilerBundle.message("add.notnull.assertions")) + .component + configureAnnotations = link(JavaCompilerBundle.message("settings.configure.annotations")) { + NullableNotNullDialog.showDialogWithInstrumentationOptions(project) + cbAssertNotNull.setSelected(!NullableNotNullManager.getInstance(project).getInstrumentedNotNulls().isEmpty()) + } + .component + } + row { + cbAutoShowFirstError = checkBox(JavaCompilerBundle.message("label.option.autoshow.first.error")) + .component + } + row { + cbDisplayNotificationPopup = checkBox(JavaCompilerBundle.message("label.option.display.notification.popup")) + .component + } + row { + cbEnableAutomakeCell = checkBox(JavaCompilerBundle.message("settings.build.project.automatically")) + .comment(JavaCompilerBundle.message("only.works.while.not.running.debugging")) + cbEnableAutomake = cbEnableAutomakeCell.component + } + row { + cbParallelCompilation = checkBox(JavaCompilerBundle.message("settings.compile.independent.modules.in.parallel")) + .comment(JavaCompilerBundle.message("settings.parallel.module.compile.may.require.larger.heap.size")) + .component + } + row { + cbRebuildOnDependencyChange = checkBox(JavaCompilerBundle.message("settings.rebuild.module.on.dependency.change")) + .component + } + } + + group(JavaCompilerBundle.message("settings.build.process.group")) { + row(JavaCompilerBundle.message("settings.build.process.heap.size")) { + sharedHeapSizeField = intTextField() + .gap(RightGap.SMALL) + .component + label(JavaCompilerBundle.message("settings.size.mbytes")) + } + row(JavaCompilerBundle.message("settings.shared.build.process.vm.options")) { + sharedVMOptionsField = expandableTextField() + .resizableColumn() + .align(AlignX.FILL) + .component + } + row(JavaCompilerBundle.message("settings.user.local.build.process.heap.size")) { + heapSizeField = intTextField() + .gap(RightGap.SMALL) + .comment(JavaCompilerBundle.message("settings.user.local.build.process.heap.size.comment")) + .component + label(JavaCompilerBundle.message("settings.size.mbytes")) + } + row(JavaCompilerBundle.message("settings.user.local.build.process.vm.options")) { + vmOptionsField = expandableTextField() + .comment(JavaCompilerBundle.message("settings.user.local.build.process.vm.options.comment")) + .resizableColumn() + .align(AlignX.FILL) + .component + } + .bottomGap(BottomGap.SMALL) + } + + tweakControls() + + val updateStateListener: DocumentAdapter = object : DocumentAdapter() { + override fun textChanged(e: javax.swing.event.DocumentEvent) { + sharedVMOptionsField.isEditable = vmOptionsField.document.length == 0 + sharedVMOptionsField.background = when (sharedVMOptionsField.isEditable) { + true -> UIUtil.getTextFieldBackground() + else -> UIUtil.getTextFieldDisabledBackground() + } + sharedHeapSizeField.isEnabled = heapSizeField.document.length == 0 && + ParametersListUtil.parse(vmOptionsField.text).none { StringUtil.startsWithIgnoreCase(it, "-Xmx") } + } + } + + vmOptionsField.getDocument().addDocumentListener(updateStateListener) + heapSizeField.getDocument().addDocumentListener(updateStateListener) + } + + fun tweakControls() { + val managers = CompilerOptionsFilter.EP_NAME.extensionList + var showExternalBuildSetting = true + for (manager in managers) { + showExternalBuildSetting = manager.isAvailable(Setting.EXTERNAL_BUILD, project) + if (!showExternalBuildSetting) { + disabledSettings.add(Setting.EXTERNAL_BUILD) + break + } + } + + for (setting in Setting.entries) { + if (!showExternalBuildSetting && CompilerUIConfigurable.EXTERNAL_BUILD_SETTINGS.contains(setting)) { + // Disable all nested external compiler settings if 'use external build' is unavailable. + disabledSettings.add(setting) + } + else { + for (manager in managers) { + if (!manager.isAvailable(setting, project)) { + disabledSettings.add(setting) + break + } + } + } + } + + val controls: Map> = mapOf( + Setting.RESOURCE_PATTERNS to listOf(resourcePatternsField), + Setting.CLEAR_OUTPUT_DIR_ON_REBUILD to listOf(cbClearOutputDirectory), + Setting.ADD_NOT_NULL_ASSERTIONS to listOf(cbAssertNotNull), + Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR to listOf(cbAutoShowFirstError), + Setting.DISPLAY_NOTIFICATION_POPUP to listOf(cbDisplayNotificationPopup), + Setting.AUTO_MAKE to listOf(cbEnableAutomake), + Setting.PARALLEL_COMPILATION to listOf(cbParallelCompilation), + Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE to listOf(cbRebuildOnDependencyChange), + Setting.HEAP_SIZE to listOf(heapSizeField, sharedHeapSizeField), + Setting.COMPILER_VM_OPTIONS to listOf(vmOptionsField, sharedVMOptionsField), + ) + + for (setting in disabledSettings) { + val components = controls[setting] + if (components != null) { + components.forEach { it.setVisible(false) } + } + } + } + + override fun reset() { + val configuration = CompilerConfiguration.getInstance(project) as CompilerConfigurationImpl + val workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(project) + + cbAutoShowFirstError.setSelected(workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR) + cbDisplayNotificationPopup.setSelected(workspaceConfiguration.DISPLAY_NOTIFICATION_POPUP) + cbClearOutputDirectory.setSelected(workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY) + cbAssertNotNull.setSelected(configuration.isAddNotNullAssertions()) + cbEnableAutomake.setSelected(workspaceConfiguration.MAKE_PROJECT_ON_SAVE) + cbParallelCompilation.setSelected(configuration.isParallelCompilationEnabled()) + cbRebuildOnDependencyChange.setSelected(workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE) + val heapSize = workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE + heapSizeField.setText(if (heapSize > 0) heapSize.toString() else "") + // for compatibility with older projects + val javacPreferred = JavacConfiguration.getOptions(project, JavacConfiguration::class.java).MAXIMUM_HEAP_SIZE + sharedHeapSizeField.setText(configuration.getBuildProcessHeapSize(javacPreferred).toString()) + val options = workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS + vmOptionsField.setText(options?.trim() ?: "") + sharedVMOptionsField.setText(configuration.getBuildProcessVMOptions()) + + configuration.convertPatterns() + + resourcePatternsField.setText(CompilerUIConfigurable.patternsToString(configuration.getResourceFilePatterns())) + + if (PowerSaveMode.isEnabled()) { + cbEnableAutomakeCell.comment(JavaCompilerBundle.message("disabled.in.power.save.mode"), 70, HyperlinkEventAction.HTML_HYPERLINK_INSTANCE) + } + else { + cbEnableAutomakeCell.comment(JavaCompilerBundle.message("only.works.while.not.running.debugging"), 70, HyperlinkEventAction.HTML_HYPERLINK_INSTANCE) + } + } + + override fun isModified(): Boolean { + val configuration = CompilerConfiguration.getInstance(project) + val workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(project) + + var isModified = !disabledSettings.contains(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR) + && ComparingUtils.isModified(cbAutoShowFirstError, workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR) + isModified = isModified || !disabledSettings.contains(Setting.DISPLAY_NOTIFICATION_POPUP) + && ComparingUtils.isModified(cbDisplayNotificationPopup, workspaceConfiguration.DISPLAY_NOTIFICATION_POPUP) + isModified = isModified || !disabledSettings.contains(Setting.AUTO_MAKE) + && ComparingUtils.isModified(cbEnableAutomake, workspaceConfiguration.MAKE_PROJECT_ON_SAVE) + isModified = isModified || !disabledSettings.contains(Setting.PARALLEL_COMPILATION) + && ComparingUtils.isModified(cbParallelCompilation, configuration.isParallelCompilationEnabled()) + isModified = isModified || !disabledSettings.contains(Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE) + && ComparingUtils.isModified(cbRebuildOnDependencyChange, workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE) + isModified = isModified || !disabledSettings.contains(Setting.HEAP_SIZE) + && ComparingUtils.isModified(heapSizeField, 0, workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE) + isModified = isModified || !disabledSettings.contains(Setting.COMPILER_VM_OPTIONS) + && ComparingUtils.isModified(vmOptionsField, workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS) + + val compilerConfiguration = CompilerConfiguration.getInstance(project) as CompilerConfigurationImpl + isModified = isModified || !disabledSettings.contains(Setting.HEAP_SIZE) + && ComparingUtils.isModified(sharedHeapSizeField, compilerConfiguration.getBuildProcessHeapSize(0)) + isModified = isModified || !disabledSettings.contains(Setting.COMPILER_VM_OPTIONS) + && ComparingUtils.isModified(sharedVMOptionsField, compilerConfiguration.getBuildProcessVMOptions()) + isModified = isModified || !disabledSettings.contains(Setting.ADD_NOT_NULL_ASSERTIONS) + && ComparingUtils.isModified(cbAssertNotNull, compilerConfiguration.isAddNotNullAssertions()) + isModified = isModified || !disabledSettings.contains(Setting.CLEAR_OUTPUT_DIR_ON_REBUILD) + && ComparingUtils.isModified(cbClearOutputDirectory, workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY) + isModified = isModified || !disabledSettings.contains(Setting.RESOURCE_PATTERNS) + && ComparingUtils.isModified(resourcePatternsField, CompilerUIConfigurable.patternsToString(compilerConfiguration.getResourceFilePatterns())) + + return isModified + } + + fun getBuildOnSaveCheckBox(): JCheckBox { + return cbEnableAutomake + } + + override fun getId(): @NonNls String = "compiler.general" + override fun getDisplayName(): @NlsContexts.ConfigurableName String = JavaCompilerBundle.message("configurable.CompilerUIConfigurable.display.name") +} diff --git a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties index 33d5697ee519..6e6f83bb729d 100644 --- a/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties +++ b/java/compiler/openapi/resources/messages/JavaCompilerBundle.properties @@ -131,13 +131,17 @@ settings.actions.on.save.page.build.project.on.save.checkbox.comment=Not trigger settings.actions.on.save.page.compiler.settings.link=Compiler settings... settings.compile.independent.modules.in.parallel=Compile independent modules in parallel settings.rebuild.module.on.dependency.change=Rebuild module on dependency change -settings.build.process.heap.size=Shared build process heap size (Mbytes): -settings.user.local.build.process.heap.size=User-local build process heap size (Mbytes) (overrides Shared size): -settings.shared.build.process.vm.options=Shared build process VM options: -settings.user.local.build.process.vm.options=User-local build process VM options (overrides Shared options): -settings.auto.build.only.works.while.not.running=(only works while not running / debugging) -settings.parallel.module.compile.may.require.larger.heap.size=(may require larger heap size) -settings.warning=WARNING!
If option 'Clear output directory on rebuild' is enabled, the entire contents of directories where generated sources are stored WILL BE CLEARED on rebuild. +settings.size.mbytes=Mbytes +settings.build.process.group=Build Process +settings.build.process.heap.size=Shared heap size: +settings.user.local.build.process.heap.size=User-local heap size: +settings.user.local.build.process.heap.size.comment=Overrides Shared size +settings.shared.build.process.vm.options=Shared VM options: +settings.user.local.build.process.vm.options=User-local VM options: +settings.user.local.build.process.vm.options.comment=Overrides Shared options +settings.auto.build.only.works.while.not.running=Only works while not running / debugging +settings.parallel.module.compile.may.require.larger.heap.size=May require a larger heap size +settings.warning=WARNING!
If enabled, the entire contents of directories where generated sources are stored
WILL BE CLEARED on rebuild.
settings.use.release.option.for.cross.compilation=Use '--release' option for cross-compilation (Java 9 and later) settings.project.bytecode.version=Project bytecode version: settings.per.module.bytecode.version=Per-module bytecode version: @@ -174,8 +178,8 @@ settings.validators=Validators: no.compilation.problems.found=No compilation problems found cannot.package.file=Cannot package file packaging.files=Packaging Files -only.works.while.not.running.debugging=(only works while not running / debugging) -disabled.in.power.save.mode=(disabled in Power Save mode) +only.works.while.not.running.debugging=Only works while not running / debugging +disabled.in.power.save.mode=Disabled in Power Save mode path.to.ecj.compiler.tool=Path to ecj compiler tool choose.members=Choose Members all.modules= @@ -236,10 +240,15 @@ progress.text.clearing.build.system.data=Clearing build system data\u2026 separator.choose.members.to.delete=Choose Members To Delete Since They Are Already Defined In {0} text.empty.profile=Profile name shouldn't be empty text.profile.exists=Profile {0} already exists -compiler.ui.pattern.legend.text=Use ; to separate patterns and ! to negate a pattern. \ - Accepted wildcards: ? \\— exactly one symbol; * \\— zero or more symbols; \ - / \\— path separator; /**/ \\— any number of directories; \ - \\<dir_name\\>:\\<pattern\\> \\— restrict to source roots with the specified name +compiler.ui.pattern.legend.text=Use ; to separate patterns and ! to negate a pattern. +compiler.ui.pattern.context.help.title=Accepted wildcards +compiler.ui.pattern.context.help=
    \ +
  • ? \\→ exactly one symbol;\ +
  • * \\→ zero or more symbols;\ +
  • / \\→ path separator;\ +
  • /**/ \\→ any number of directories;\ +
  • \\<dir_name\\>:\\<pattern\\> \\→ restrict to source roots with the specified name.\ +
notification.compiler.auto.build.failure=Auto build failure: {0} notification.compiler.auto.build.completed.with.errors=Auto build completed with errors dialog.title.manifest.select.main.class=Select Main Class