IDEA-110710 Compiler: Provide extension point for managing available settings

This commit is contained in:
Denis.Zhdanov
2013-07-18 13:32:11 +04:00
parent bee20bc0bf
commit 07675ac57b
4 changed files with 183 additions and 49 deletions
@@ -0,0 +1,41 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.compiler.options;
import com.intellij.openapi.extensions.ExtensionPointName;
import org.jetbrains.annotations.NotNull;
/**
* Compiler settings page (Project Settings | Compiler) offers number of controls. However, there is a possible case that
* some of them should be 'frozen' at particular environment (e.g. there is no point in disable external compiler
* in case of AndroidStudio).
* <p/>
* This interface defines api which allows extensions to control compiler options availability.
*
* @author Denis Zhdanov
* @since 7/18/13 12:40 PM
*/
public interface CompilerOptionsManager {
ExtensionPointName<CompilerOptionsManager> EP_NAME = ExtensionPointName.create("com.intellij.compiler.optionsManager");
enum Setting {
RESOURCE_PATTERNS, CLEAR_OUTPUT_DIR_ON_REBUILD, ADD_NOT_NULL_ASSERTIONS, AUTO_SHOW_FIRST_ERROR_IN_EDITOR,
EXTERNAL_BUILD, AUTO_MAKE, PARALLEL_COMPILATION, REBUILD_MODULE_ON_DEPENDENCY_CHANGE, HEAP_SIZE, COMPILER_VM_OPTIONS
}
boolean isAvailable(@NotNull Setting setting);
}
@@ -21,7 +21,7 @@
<properties/>
<border type="none"/>
<children>
<component id="b0748" class="javax.swing.JLabel">
<component id="b0748" class="javax.swing.JLabel" binding="myResourcePatternsLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
@@ -132,7 +132,7 @@
<text value="Compile independent modules in parallel"/>
</properties>
</component>
<component id="91979" class="javax.swing.JLabel">
<component id="91979" class="javax.swing.JLabel" binding="myParallelCompilationLegendLabel">
<constraints>
<grid row="6" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
@@ -140,7 +140,7 @@
<text value="(may require larger heap size)"/>
</properties>
</component>
<component id="732b1" class="javax.swing.JLabel">
<component id="732b1" class="javax.swing.JLabel" binding="myEnableAutomakeLegendLabel">
<constraints>
<grid row="5" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
@@ -38,14 +38,14 @@ import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.*;
import static com.intellij.compiler.options.CompilerOptionsManager.*;
public class CompilerUIConfigurable implements SearchableConfigurable, Configurable.NoScroll {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.options.CompilerUIConfigurable");
public static final Function<String, List<String>> LINE_PARSER = new Function<String, List<String>>() {
public static final Function<String, List<String>> LINE_PARSER = new Function<String, List<String>>() {
@Override
public List<String> fun(String text) {
final ArrayList<String> result = ContainerUtilRt.newArrayList();
@@ -56,29 +56,38 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
return result;
}
};
public static final Function<List<String>, String> LINE_JOINER = new Function<List<String>, String>() {
public static final Function<List<String>, String> LINE_JOINER = new Function<List<String>, String>() {
@Override
public String fun(List<String> strings) {
return StringUtil.join(strings, ";");
}
};
private static final Set<Setting> 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 JPanel myPanel;
private final Set<Setting> 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 myCbUseExternalBuild;
private JCheckBox myCbEnableAutomake;
private JCheckBox myCbParallelCompilation;
private JTextField myHeapSizeField;
private JTextField myVMOptionsField;
private JLabel myHeapSizeLabel;
private JLabel myVMOptionsLabel;
private JCheckBox myCbRebuildOnDependencyChange;
private JCheckBox myCbClearOutputDirectory;
private JCheckBox myCbAssertNotNull;
private JBLabel myPatternLegendLabel;
private JCheckBox myCbAutoShowFirstError;
private JCheckBox myCbUseExternalBuild;
private JCheckBox myCbEnableAutomake;
private JCheckBox myCbParallelCompilation;
private JTextField myHeapSizeField;
private JTextField myVMOptionsField;
private JLabel myHeapSizeLabel;
private JLabel myVMOptionsLabel;
private JCheckBox myCbRebuildOnDependencyChange;
private JLabel myResourcePatternsLabel;
private JLabel myEnableAutomakeLegendLabel;
private JLabel myParallelCompilationLegendLabel;
public CompilerUIConfigurable(final Project project) {
myProject = project;
@@ -96,6 +105,58 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
updateExternalMakeOptionControls(myCbUseExternalBuild.isSelected());
}
});
tweakControls();
}
private void tweakControls() {
CompilerOptionsManager[] managers = CompilerOptionsManager.EP_NAME.getExtensions();
boolean showExternalBuildSetting = true;
for (CompilerOptionsManager manager : managers) {
showExternalBuildSetting = manager.isAvailable(Setting.EXTERNAL_BUILD);
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 (CompilerOptionsManager manager : managers) {
if (!manager.isAvailable(setting)) {
myDisabledSettings.add(setting);
break;
}
}
}
}
Map<Setting, Collection<JComponent>> controls = ContainerUtilRt.newHashMap();
controls.put(Setting.RESOURCE_PATTERNS,
ContainerUtilRt.<JComponent>newArrayList(myResourcePatternsLabel, myResourcePatternsField, myPatternLegendLabel));
controls.put(Setting.CLEAR_OUTPUT_DIR_ON_REBUILD, Collections.<JComponent>singleton(myCbClearOutputDirectory));
controls.put(Setting.ADD_NOT_NULL_ASSERTIONS, Collections.<JComponent>singleton(myCbAutoShowFirstError));
controls.put(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR, Collections.<JComponent>singleton(myCbAutoShowFirstError));
controls.put(Setting.EXTERNAL_BUILD, ContainerUtilRt.<JComponent>newArrayList(myCbUseExternalBuild));
controls.put(Setting.AUTO_MAKE, ContainerUtilRt.<JComponent>newArrayList(myCbEnableAutomake, myEnableAutomakeLegendLabel));
controls.put(Setting.PARALLEL_COMPILATION,
ContainerUtilRt.<JComponent>newArrayList(myCbParallelCompilation, myParallelCompilationLegendLabel));
controls.put(Setting.REBUILD_MODULE_ON_DEPENDENCY_CHANGE, ContainerUtilRt.<JComponent>newArrayList(myCbRebuildOnDependencyChange));
controls.put(Setting.HEAP_SIZE, ContainerUtilRt.<JComponent>newArrayList(myHeapSizeLabel, myHeapSizeField));
controls.put(Setting.COMPILER_VM_OPTIONS, ContainerUtilRt.<JComponent>newArrayList(myVMOptionsLabel, myVMOptionsField));
for (Setting setting : myDisabledSettings) {
Collection<JComponent> components = controls.get(setting);
if (components != null) {
for (JComponent component : components) {
component.setVisible(false);
}
}
}
}
public void reset() {
@@ -111,7 +172,7 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
myCbRebuildOnDependencyChange.setSelected(workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE);
myHeapSizeField.setText(String.valueOf(workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE));
final String options = workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS;
myVMOptionsField.setText(options == null? "" : options.trim());
myVMOptionsField.setText(options == null ? "" : options.trim());
updateExternalMakeOptionControls(myCbUseExternalBuild.isSelected());
configuration.convertPatterns();
@@ -134,25 +195,45 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
CompilerConfigurationImpl configuration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject);
final CompilerWorkspaceConfiguration workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(myProject);
workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR = myCbAutoShowFirstError.isSelected();
workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY = myCbClearOutputDirectory.isSelected();
if (!myDisabledSettings.contains(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR)) {
workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR = myCbAutoShowFirstError.isSelected();
}
if (!myDisabledSettings.contains(Setting.CLEAR_OUTPUT_DIR_ON_REBUILD)) {
workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY = myCbClearOutputDirectory.isSelected();
}
boolean wasUsingExternalMake = workspaceConfiguration.USE_COMPILE_SERVER;
workspaceConfiguration.USE_COMPILE_SERVER = myCbUseExternalBuild.isSelected();
workspaceConfiguration.MAKE_PROJECT_ON_SAVE = myCbEnableAutomake.isSelected();
workspaceConfiguration.PARALLEL_COMPILATION = myCbParallelCompilation.isSelected();
workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE = myCbRebuildOnDependencyChange.isSelected();
try {
workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE = Integer.parseInt(myHeapSizeField.getText().trim());
if (!myDisabledSettings.contains(Setting.EXTERNAL_BUILD)) {
workspaceConfiguration.USE_COMPILE_SERVER = myCbUseExternalBuild.isSelected();
if (!myDisabledSettings.contains(Setting.AUTO_MAKE)) {
workspaceConfiguration.MAKE_PROJECT_ON_SAVE = myCbEnableAutomake.isSelected();
}
if (!myDisabledSettings.contains(Setting.PARALLEL_COMPILATION)) {
workspaceConfiguration.PARALLEL_COMPILATION = 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 {
workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE = Integer.parseInt(myHeapSizeField.getText().trim());
}
catch (NumberFormatException ignored) {
LOG.info(ignored);
}
}
if (!myDisabledSettings.contains(Setting.COMPILER_VM_OPTIONS)) {
workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS = myVMOptionsField.getText().trim();
}
}
catch (NumberFormatException ignored) {
LOG.info(ignored);
}
workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS = myVMOptionsField.getText().trim();
configuration.setAddNotNullAssertions(myCbAssertNotNull.isSelected());
configuration.removeResourceFilePatterns();
String extensionString = myResourcePatternsField.getText().trim();
applyResourcePatterns(extensionString, (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject));
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, (CompilerConfigurationImpl)CompilerConfiguration.getInstance(myProject));
}
if (wasUsingExternalMake != workspaceConfiguration.USE_COMPILE_SERVER) {
myProject.getMessageBus().syncPublisher(ExternalBuildOptionListener.TOPIC).externalBuildOptionChanged(workspaceConfiguration.USE_COMPILE_SERVER);
}
@@ -193,20 +274,29 @@ public class CompilerUIConfigurable implements SearchableConfigurable, Configura
}
public boolean isModified() {
boolean isModified = false;
final CompilerWorkspaceConfiguration workspaceConfiguration = CompilerWorkspaceConfiguration.getInstance(myProject);
isModified |= ComparingUtils.isModified(myCbAutoShowFirstError, workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR);
isModified |= ComparingUtils.isModified(myCbUseExternalBuild, workspaceConfiguration.USE_COMPILE_SERVER);
isModified |= ComparingUtils.isModified(myCbEnableAutomake, workspaceConfiguration.MAKE_PROJECT_ON_SAVE);
isModified |= ComparingUtils.isModified(myCbParallelCompilation, workspaceConfiguration.PARALLEL_COMPILATION);
isModified |= ComparingUtils.isModified(myCbRebuildOnDependencyChange, workspaceConfiguration.REBUILD_ON_DEPENDENCY_CHANGE);
isModified |= ComparingUtils.isModified(myHeapSizeField, workspaceConfiguration.COMPILER_PROCESS_HEAP_SIZE);
isModified |= ComparingUtils.isModified(myVMOptionsField, workspaceConfiguration.COMPILER_PROCESS_ADDITIONAL_VM_OPTIONS);
boolean isModified = !myDisabledSettings.contains(Setting.AUTO_SHOW_FIRST_ERROR_IN_EDITOR)
&& ComparingUtils.isModified(myCbAutoShowFirstError, workspaceConfiguration.AUTO_SHOW_ERRORS_IN_EDITOR);
isModified |= !myDisabledSettings.contains(Setting.EXTERNAL_BUILD)
&& ComparingUtils.isModified(myCbUseExternalBuild, workspaceConfiguration.USE_COMPILE_SERVER);
isModified |= !myDisabledSettings.contains(Setting.AUTO_MAKE)
&& ComparingUtils.isModified(myCbEnableAutomake, workspaceConfiguration.MAKE_PROJECT_ON_SAVE);
isModified |= !myDisabledSettings.contains(Setting.PARALLEL_COMPILATION)
&& ComparingUtils.isModified(myCbParallelCompilation, workspaceConfiguration.PARALLEL_COMPILATION);
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, 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 |= ComparingUtils.isModified(myCbAssertNotNull, compilerConfiguration.isAddNotNullAssertions());
isModified |= ComparingUtils.isModified(myCbClearOutputDirectory, workspaceConfiguration.CLEAR_OUTPUT_DIRECTORY);
isModified |= ComparingUtils.isModified(myResourcePatternsField, patternsToString(compilerConfiguration.getResourceFilePatterns()));
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;
}
@@ -50,6 +50,9 @@
<extensionPoint name="compiler.makeDependencyProcessor"
interface="com.intellij.compiler.DependencyProcessor"/>
<extensionPoint name="compiler.optionsManager"
interface="com.intellij.compiler.options.CompilerOptionsManager"/>
<extensionPoint name="compiler.resourceCompilerExtension"
interface="com.intellij.compiler.impl.resourceCompiler.ResourceCompilerExtension"/>