Kotlin Facet: Support multiple configuration editor

#KT-15914 Fixed
This commit is contained in:
Alexey Sedunov
2017-02-01 12:37:31 +03:00
parent 8849d0e2a3
commit 0c331a3846
5 changed files with 229 additions and 63 deletions

View File

@@ -21,12 +21,13 @@
<properties/>
<border type="none"/>
<children>
<component id="3b8d3" class="javax.swing.JCheckBox" binding="generateNoWarningsCheckBox" default-binding="true">
<component id="fc71f" class="com.intellij.util.ui.ThreeStateCheckBox" binding="generateNoWarningsCheckBox" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="false"/>
<state value="NOT_SELECTED"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="kotlin.compiler.option.generate.no.warnings"/>
</properties>
</component>
@@ -48,11 +49,12 @@
<dialogCaption resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="kotlin.compiler.option.additional.command.line.parameters.dialog.title"/>
</properties>
</component>
<component id="c45a6" class="javax.swing.JCheckBox" binding="keepAliveCheckBox">
<component id="dae3f" class="com.intellij.util.ui.ThreeStateCheckBox" binding="keepAliveCheckBox">
<constraints>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<state value="NOT_SELECTED"/>
<text value="Keep compiler process alive between invocations"/>
</properties>
</component>
@@ -222,12 +224,13 @@
</clientProperties>
<border type="etched" title-resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" title-key="kotlin.compiler.js.option.panel.title"/>
<children>
<component id="1fbe0" class="javax.swing.JCheckBox" binding="generateSourceMapsCheckBox" default-binding="true">
<component id="e1cc8" class="com.intellij.util.ui.ThreeStateCheckBox" binding="generateSourceMapsCheckBox" default-binding="true">
<constraints>
<grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="kotlin.compiler.js.option.generate.sourcemaps"/>
<state value="NOT_SELECTED"/>
</properties>
</component>
<component id="3ac8f" class="javax.swing.JLabel" binding="labelForOutputPrefixFile">
@@ -280,12 +283,13 @@
<text value="lib"/>
</properties>
</component>
<component id="bb4ef" class="javax.swing.JCheckBox" binding="copyRuntimeFilesCheckBox">
<component id="97317" class="com.intellij.util.ui.ThreeStateCheckBox" binding="copyRuntimeFilesCheckBox">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="kotlin.compiler.js.option.output.copy.files"/>
<state value="NOT_SELECTED"/>
</properties>
</component>
<component id="915d" class="javax.swing.JLabel">

View File

@@ -32,6 +32,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.RawCommandLineEditor;
import com.intellij.util.text.VersionComparatorUtil;
import com.intellij.util.ui.ThreeStateCheckBox;
import kotlin.collections.ArraysKt;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
@@ -76,18 +77,18 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
private final Project project;
private final boolean isProjectSettings;
private JPanel contentPane;
private JCheckBox generateNoWarningsCheckBox;
private ThreeStateCheckBox generateNoWarningsCheckBox;
private RawCommandLineEditor additionalArgsOptionsField;
private JLabel additionalArgsLabel;
private JCheckBox generateSourceMapsCheckBox;
private ThreeStateCheckBox generateSourceMapsCheckBox;
private TextFieldWithBrowseButton outputPrefixFile;
private TextFieldWithBrowseButton outputPostfixFile;
private JLabel labelForOutputPrefixFile;
private JLabel labelForOutputPostfixFile;
private JLabel labelForOutputDirectory;
private JTextField outputDirectory;
private JCheckBox copyRuntimeFilesCheckBox;
private JCheckBox keepAliveCheckBox;
private ThreeStateCheckBox copyRuntimeFilesCheckBox;
private ThreeStateCheckBox keepAliveCheckBox;
private JCheckBox enablePreciseIncrementalCheckBox;
private JComboBox moduleKindComboBox;
private JTextField scriptTemplatesField;
@@ -110,7 +111,8 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
CompilerSettings compilerSettings,
@Nullable KotlinCompilerWorkspaceSettings compilerWorkspaceSettings,
@Nullable K2JVMCompilerArguments k2jvmCompilerArguments,
boolean isProjectSettings
boolean isProjectSettings,
boolean isMultiEditor
) {
this.project = project;
this.commonCompilerArguments = commonCompilerArguments;
@@ -154,6 +156,11 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
keepAliveCheckBox.setVisible(false);
k2jvmPanel.setVisible(false);
}
generateNoWarningsCheckBox.setThirdStateEnabled(isMultiEditor);
generateSourceMapsCheckBox.setThirdStateEnabled(isMultiEditor);
copyRuntimeFilesCheckBox.setThirdStateEnabled(isMultiEditor);
keepAliveCheckBox.setThirdStateEnabled(isMultiEditor);
}
@SuppressWarnings("unused")
@@ -164,7 +171,8 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
KotlinCompilerSettings.getInstance(project).getSettings(),
ServiceManager.getService(project, KotlinCompilerWorkspaceSettings.class),
Kotlin2JvmCompilerArgumentsHolder.getInstance(project).getSettings(),
true);
true,
false);
}
@NotNull
@@ -437,6 +445,50 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
return contentPane;
}
public ThreeStateCheckBox getGenerateNoWarningsCheckBox() {
return generateNoWarningsCheckBox;
}
public RawCommandLineEditor getAdditionalArgsOptionsField() {
return additionalArgsOptionsField;
}
public ThreeStateCheckBox getGenerateSourceMapsCheckBox() {
return generateSourceMapsCheckBox;
}
public TextFieldWithBrowseButton getOutputPrefixFile() {
return outputPrefixFile;
}
public TextFieldWithBrowseButton getOutputPostfixFile() {
return outputPostfixFile;
}
public JTextField getOutputDirectory() {
return outputDirectory;
}
public ThreeStateCheckBox getCopyRuntimeFilesCheckBox() {
return copyRuntimeFilesCheckBox;
}
public ThreeStateCheckBox getKeepAliveCheckBox() {
return keepAliveCheckBox;
}
public JComboBox getModuleKindComboBox() {
return moduleKindComboBox;
}
public JTextField getScriptTemplatesField() {
return scriptTemplatesField;
}
public JTextField getScriptTemplatesClasspathField() {
return scriptTemplatesClasspathField;
}
public JComboBox getLanguageVersionComboBox() {
return languageVersionComboBox;
}
@@ -444,4 +496,8 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
public JComboBox getApiVersionComboBox() {
return apiVersionComboBox;
}
public JComboBox getCoroutineSupportComboBox() {
return coroutineSupportComboBox;
}
}

View File

@@ -19,8 +19,14 @@ package org.jetbrains.kotlin.idea.facet
import com.intellij.facet.impl.ui.libraries.DelegatingLibrariesValidatorContext
import com.intellij.facet.ui.*
import com.intellij.facet.ui.libraries.FrameworkLibraryValidator
import com.intellij.openapi.project.Project
import com.intellij.util.ui.FormBuilder
import com.intellij.util.ui.ThreeStateCheckBox
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.KotlinCompilerInfo
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerConfigurableTab
@@ -32,13 +38,73 @@ class KotlinFacetEditorGeneralTab(
private val editorContext: FacetEditorContext,
validatorsManager: FacetValidatorsManager
) : FacetEditorTab() {
class EditorComponent(
project: Project,
configuration: KotlinFacetConfiguration?
) : JPanel(BorderLayout()) {
private val isMultiEditor = configuration == null
private val compilerInfo = configuration?.settings?.compilerInfo
?: KotlinCompilerInfo()
.apply {
commonCompilerArguments = object : CommonCompilerArguments() {}
k2jsCompilerArguments = K2JSCompilerArguments()
compilerSettings = CompilerSettings()
}
val compilerConfigurable = with(compilerInfo) {
KotlinCompilerConfigurableTab(
project,
commonCompilerArguments,
k2jsCompilerArguments,
compilerSettings,
null,
null,
false,
isMultiEditor
)
}
val useProjectSettingsCheckBox = ThreeStateCheckBox("Use project settings").apply { isThirdStateEnabled = isMultiEditor }
val targetPlatformComboBox =
JComboBox<TargetPlatformKind<*>>(TargetPlatformKind.ALL_PLATFORMS.toTypedArray()).apply {
setRenderer(DescriptionListCellRenderer())
}
init {
val contentPanel = FormBuilder
.createFormBuilder()
.addComponent(useProjectSettingsCheckBox)
.addLabeledComponent("&Target platform: ", targetPlatformComboBox)
.addComponent(compilerConfigurable.createComponent()!!)
.panel
add(contentPanel, BorderLayout.NORTH)
useProjectSettingsCheckBox.addActionListener {
updateCompilerConfigurable()
}
targetPlatformComboBox.addActionListener {
updateCompilerConfigurable()
}
}
internal fun updateCompilerConfigurable() {
compilerConfigurable.setTargetPlatform(chosenPlatform)
UIUtil.setEnabled(compilerConfigurable.contentPane, !useProjectSettingsCheckBox.isSelected, true)
}
val chosenPlatform: TargetPlatformKind<*>?
get() = targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
}
inner class VersionValidator : FacetEditorValidator() {
override fun check(): ValidationResult {
val apiLevel = compilerConfigurable.apiVersionComboBox.selectedItem as? LanguageVersion?
val apiLevel = editor.compilerConfigurable.apiVersionComboBox.selectedItem as? LanguageVersion?
?: return ValidationResult.OK
val languageLevel = compilerConfigurable.languageVersionComboBox.selectedItem as? LanguageVersion?
val languageLevel = editor.compilerConfigurable.languageVersionComboBox.selectedItem as? LanguageVersion?
?: return ValidationResult.OK
val targetPlatform = targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
val targetPlatform = editor.targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
val libraryLevel = getLibraryLanguageLevel(editorContext.module, editorContext.rootModel, targetPlatform)
if (languageLevel < apiLevel || libraryLevel < apiLevel) {
return ValidationResult("Language version/Runtime version may not be less than API version", null)
@@ -47,24 +113,7 @@ class KotlinFacetEditorGeneralTab(
}
}
private val compilerConfigurable = with(configuration.settings.compilerInfo) {
KotlinCompilerConfigurableTab(
editorContext.project,
commonCompilerArguments,
k2jsCompilerArguments,
compilerSettings,
null,
null,
false
)
}
private val useProjectSettingsCheckBox = JCheckBox("Use project settings")
private val targetPlatformComboBox =
JComboBox<TargetPlatformKind<*>>(TargetPlatformKind.ALL_PLATFORMS.toTypedArray()).apply {
setRenderer(DescriptionListCellRenderer())
}
val editor = EditorComponent(editorContext.project, configuration)
private val libraryValidator: FrameworkLibraryValidator
private val versionValidator = VersionValidator()
@@ -74,56 +123,46 @@ class KotlinFacetEditorGeneralTab(
DelegatingLibrariesValidatorContext(editorContext),
validatorsManager,
"kotlin"
) { targetPlatformComboBox.selectedItem as TargetPlatformKind<*> }
) { editor.targetPlatformComboBox.selectedItem as TargetPlatformKind<*> }
validatorsManager.registerValidator(libraryValidator)
validatorsManager.registerValidator(versionValidator)
useProjectSettingsCheckBox.addActionListener {
updateCompilerConfigurable()
}
compilerConfigurable.languageVersionComboBox.addActionListener {
editor.compilerConfigurable.languageVersionComboBox.addActionListener {
validatorsManager.validate()
}
compilerConfigurable.apiVersionComboBox.addActionListener {
editor.compilerConfigurable.apiVersionComboBox.addActionListener {
validatorsManager.validate()
}
targetPlatformComboBox.addActionListener {
editor.targetPlatformComboBox.addActionListener {
validatorsManager.validate()
updateCompilerConfigurable()
}
updateCompilerConfigurable()
editor.updateCompilerConfigurable()
reset()
}
private fun updateCompilerConfigurable() {
compilerConfigurable.setTargetPlatform(chosenPlatform)
UIUtil.setEnabled(compilerConfigurable.contentPane, !useProjectSettingsCheckBox.isSelected, true)
}
override fun isModified(): Boolean {
if (useProjectSettingsCheckBox.isSelected != configuration.settings.useProjectSettings) return true
if (targetPlatformComboBox.selectedItem != configuration.settings.versionInfo.targetPlatformKind) return true
return !useProjectSettingsCheckBox.isSelected && compilerConfigurable.isModified
if (editor.useProjectSettingsCheckBox.isSelected != configuration.settings.useProjectSettings) return true
if (editor.targetPlatformComboBox.selectedItem != configuration.settings.versionInfo.targetPlatformKind) return true
return !editor.useProjectSettingsCheckBox.isSelected && editor.compilerConfigurable.isModified
}
override fun reset() {
useProjectSettingsCheckBox.isSelected = configuration.settings.useProjectSettings
targetPlatformComboBox.selectedItem = configuration.settings.versionInfo.targetPlatformKind
compilerConfigurable.reset()
updateCompilerConfigurable()
editor.useProjectSettingsCheckBox.isSelected = configuration.settings.useProjectSettings
editor.targetPlatformComboBox.selectedItem = configuration.settings.versionInfo.targetPlatformKind
editor.compilerConfigurable.reset()
editor.updateCompilerConfigurable()
}
override fun apply() {
compilerConfigurable.apply()
editor.compilerConfigurable.apply()
with(configuration.settings) {
useProjectSettings = useProjectSettingsCheckBox.isSelected
versionInfo.targetPlatformKind = targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
useProjectSettings = editor.useProjectSettingsCheckBox.isSelected
versionInfo.targetPlatformKind = editor.targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
versionInfo.languageLevel = LanguageVersion.fromVersionString(compilerInfo.commonCompilerArguments?.languageVersion)
versionInfo.apiLevel = LanguageVersion.fromVersionString(compilerInfo.commonCompilerArguments?.apiVersion)
}
@@ -135,18 +174,15 @@ class KotlinFacetEditorGeneralTab(
val mainPanel = JPanel(BorderLayout())
val contentPanel = FormBuilder
.createFormBuilder()
.addComponent(useProjectSettingsCheckBox)
.addLabeledComponent("&Target platform: ", targetPlatformComboBox)
.addComponent(compilerConfigurable.createComponent()!!)
.addComponent(editor.useProjectSettingsCheckBox)
.addLabeledComponent("&Target platform: ", editor.targetPlatformComboBox)
.addComponent(editor.compilerConfigurable.createComponent()!!)
.panel
mainPanel.add(contentPanel, BorderLayout.NORTH)
return mainPanel
}
override fun disposeUIResources() {
compilerConfigurable.disposeUIResources()
editor.compilerConfigurable.disposeUIResources()
}
val chosenPlatform: TargetPlatformKind<*>?
get() = targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
}

View File

@@ -20,9 +20,11 @@ import com.intellij.facet.Facet
import com.intellij.facet.FacetType
import com.intellij.facet.FacetTypeId
import com.intellij.facet.FacetTypeRegistry
import com.intellij.facet.ui.FacetEditor
import com.intellij.openapi.module.JavaModuleType
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleType
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.KotlinIcons
import javax.swing.Icon
@@ -48,4 +50,7 @@ class KotlinFacetType : FacetType<KotlinFacet, KotlinFacetConfiguration>(TYPE_ID
configuration: KotlinFacetConfiguration,
underlyingFacet: Facet<*>?
) = KotlinFacet(module, name, configuration)
override fun createMultipleConfigurationsEditor(project: Project, editors: Array<out FacetEditor>) =
MultipleKotlinFacetEditor(project, editors)
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2010-2017 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 org.jetbrains.kotlin.idea.facet
import com.intellij.facet.ui.FacetEditor
import com.intellij.facet.ui.FacetEditorsFactory
import com.intellij.facet.ui.MultipleFacetSettingsEditor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerConfigurableTab
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
import javax.swing.JComponent
class MultipleKotlinFacetEditor(
private val project: Project,
private val editors: Array<out FacetEditor>
) : MultipleFacetSettingsEditor() {
private val helper = FacetEditorsFactory.getInstance().createMultipleFacetEditorHelper()
private val FacetEditor.tabEditor: KotlinFacetEditorGeneralTab.EditorComponent
get() = editorTabs.firstIsInstance<KotlinFacetEditorGeneralTab>().editor
private val FacetEditor.compilerConfigurable: KotlinCompilerConfigurableTab
get() = tabEditor.compilerConfigurable
override fun createComponent(): JComponent? {
return KotlinFacetEditorGeneralTab.EditorComponent(project, null).apply {
helper.bind(useProjectSettingsCheckBox, editors) { it.tabEditor.useProjectSettingsCheckBox }
helper.bind(targetPlatformComboBox, editors) { it.tabEditor.targetPlatformComboBox }
with(compilerConfigurable) {
helper.bind(generateNoWarningsCheckBox, editors) { it.compilerConfigurable.generateNoWarningsCheckBox }
helper.bind(additionalArgsOptionsField.textField, editors) { it.compilerConfigurable.additionalArgsOptionsField.textField }
helper.bind(generateSourceMapsCheckBox, editors) { it.compilerConfigurable.generateSourceMapsCheckBox}
helper.bind(outputPrefixFile.textField, editors) { it.compilerConfigurable.outputPrefixFile.textField}
helper.bind(outputPostfixFile.textField, editors) { it.compilerConfigurable.outputPostfixFile.textField}
helper.bind(outputDirectory, editors) { it.compilerConfigurable.outputDirectory}
helper.bind(copyRuntimeFilesCheckBox, editors) { it.compilerConfigurable.copyRuntimeFilesCheckBox}
helper.bind(keepAliveCheckBox, editors) { it.compilerConfigurable.keepAliveCheckBox}
helper.bind(moduleKindComboBox, editors) { it.compilerConfigurable.moduleKindComboBox}
helper.bind(scriptTemplatesField, editors) { it.compilerConfigurable.scriptTemplatesField}
helper.bind(scriptTemplatesClasspathField, editors) { it.compilerConfigurable.scriptTemplatesClasspathField}
helper.bind(languageVersionComboBox, editors) { it.compilerConfigurable.languageVersionComboBox}
helper.bind(apiVersionComboBox, editors) { it.compilerConfigurable.apiVersionComboBox}
helper.bind(coroutineSupportComboBox, editors) { it.compilerConfigurable.coroutineSupportComboBox}
}
}
}
override fun disposeUIResources() {
helper.unbind()
}
}