Kotlin Facet: Add compiler settings to facet configuration

This commit is contained in:
Alexey Sedunov
2016-10-19 12:34:52 +03:00
parent 03f4d9f574
commit ea13456bba
10 changed files with 234 additions and 35 deletions
@@ -20,6 +20,7 @@ import com.intellij.util.SmartList;
import com.sampullara.cli.Argument;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
public abstract class CommonCompilerArguments {
@@ -72,11 +73,44 @@ public abstract class CommonCompilerArguments {
public List<String> unknownExtraFlags = new SmartList<String>();
public CommonCompilerArguments() {
}
protected CommonCompilerArguments(CommonCompilerArguments arguments) {
this.languageVersion = arguments.languageVersion;
this.apiVersion = arguments.apiVersion;
this.suppressWarnings = arguments.suppressWarnings;
this.verbose = arguments.verbose;
this.version = arguments.version;
this.help = arguments.help;
this.extraHelp = arguments.extraHelp;
this.noInline = arguments.noInline;
this.repeat = arguments.repeat;
this.pluginClasspaths = arguments.pluginClasspaths != null ? Arrays.copyOf(arguments.pluginClasspaths, arguments.pluginClasspaths.length) : null;
this.pluginOptions = arguments.pluginOptions != null ? Arrays.copyOf(arguments.pluginOptions, arguments.pluginOptions.length) : null;
this.freeArgs.addAll(arguments.freeArgs);
this.unknownExtraFlags.addAll(arguments.unknownExtraFlags);
}
public abstract CommonCompilerArguments copy();
@NotNull
public String executableScriptFileName() {
return "kotlinc";
}
// Used only for serialize and deserialize settings. Don't use in other places!
public static final class DummyImpl extends CommonCompilerArguments {}
public static final class DummyImpl extends CommonCompilerArguments {
public DummyImpl() {
}
public DummyImpl(DummyImpl arguments) {
super(arguments);
}
@Override
public CommonCompilerArguments copy() {
return new DummyImpl(this);
}
}
}
@@ -20,6 +20,8 @@ import com.sampullara.cli.Argument;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import static org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.CALL;
import static org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants.NO_CALL;
@@ -73,6 +75,29 @@ public class K2JSCompilerArguments extends CommonCompilerArguments {
@ValueDescription("<path>")
public String outputPostfix;
public K2JSCompilerArguments() {
}
private K2JSCompilerArguments(K2JSCompilerArguments arguments) {
super(arguments);
this.outputFile = arguments.outputFile;
this.noStdlib = arguments.noStdlib;
this.libraryFiles = arguments.libraryFiles != null ? Arrays.copyOf(arguments.libraryFiles, arguments.libraryFiles.length) : null;
this.sourceMap = arguments.sourceMap;
this.metaInfo = arguments.metaInfo;
this.kjsm = arguments.kjsm;
this.target = arguments.target;
this.moduleKind = arguments.moduleKind;
this.main = arguments.main;
this.outputPrefix = arguments.outputPrefix;
this.outputPostfix = arguments.outputPostfix;
}
@Override
public K2JSCompilerArguments copy() {
return new K2JSCompilerArguments(this);
}
@Override
@NotNull
public String executableScriptFileName() {
@@ -107,6 +107,12 @@ public class K2JVMCompilerArguments extends CommonCompilerArguments {
// Paths to output directories for friend modules.
public String[] friendPaths;
@Override
public CommonCompilerArguments copy() {
// No need to copy these arguments yet
throw new UnsupportedOperationException();
}
@Override
@NotNull
public String executableScriptFileName() {
@@ -23,6 +23,16 @@ class CompilerSettings {
var copyJsLibraryFiles: Boolean = true
var outputDirectoryForJsLibraryFiles: String = DEFAULT_OUTPUT_DIRECTORY
constructor()
constructor(settings: CompilerSettings) {
additionalArguments = settings.additionalArguments
scriptTemplates = settings.scriptTemplates
scriptTemplatesClasspath = settings.scriptTemplatesClasspath
copyJsLibraryFiles = settings.copyJsLibraryFiles
outputDirectoryForJsLibraryFiles = settings.outputDirectoryForJsLibraryFiles
}
companion object {
private val DEFAULT_ADDITIONAL_ARGUMENTS = "-version"
private val DEFAULT_OUTPUT_DIRECTORY = "lib"
@@ -92,7 +92,7 @@
</component>
</children>
</grid>
<grid id="2f977" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="2f977" binding="k2jvmPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
@@ -115,7 +115,7 @@
</component>
</children>
</grid>
<grid id="98e8a" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="98e8a" binding="k2jsPanel" layout-manager="GridLayoutManager" row-count="6" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JsArgumentConstants;
import org.jetbrains.kotlin.config.CompilerSettings;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.PluginStartupComponent;
import org.jetbrains.kotlin.idea.facet.KotlinFacetConfiguration;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
@@ -50,6 +51,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
private final CommonCompilerArguments commonCompilerArguments;
private final K2JSCompilerArguments k2jsCompilerArguments;
private final CompilerSettings compilerSettings;
@Nullable
private final KotlinCompilerWorkspaceSettings compilerWorkspaceSettings;
private final Project project;
private JPanel contentPane;
@@ -71,6 +73,8 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
private JTextField scriptTemplatesClasspathField;
private JLabel scriptTemplatesLabel;
private JLabel scriptTemplatesClasspathLabel;
private JPanel k2jvmPanel;
private JPanel k2jsPanel;
static {
moduleKindDescriptions.put(K2JsArgumentConstants.MODULE_PLAIN, "Plain (put to global scope)");
@@ -79,12 +83,18 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
moduleKindDescriptions.put(K2JsArgumentConstants.MODULE_UMD, "UMD (detect AMD or CommonJS if available, fallback to plain)");
}
public KotlinCompilerConfigurableTab(Project project) {
this.commonCompilerArguments = KotlinCommonCompilerArgumentsHolder.getInstance(project).getSettings();
this.k2jsCompilerArguments = Kotlin2JsCompilerArgumentsHolder.getInstance(project).getSettings();
this.compilerSettings = KotlinCompilerSettings.getInstance(project).getSettings();
this.compilerWorkspaceSettings = ServiceManager.getService(project, KotlinCompilerWorkspaceSettings.class);
public KotlinCompilerConfigurableTab(
Project project,
CommonCompilerArguments commonCompilerArguments,
K2JSCompilerArguments k2jsCompilerArguments,
CompilerSettings compilerSettings,
@Nullable KotlinCompilerWorkspaceSettings compilerWorkspaceSettings
) {
this.project = project;
this.commonCompilerArguments = commonCompilerArguments;
this.k2jsCompilerArguments = k2jsCompilerArguments;
this.compilerSettings = compilerSettings;
this.compilerWorkspaceSettings = compilerWorkspaceSettings;
additionalArgsOptionsField.attachLabel(additionalArgsLabel);
@@ -103,6 +113,24 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
});
fillModuleKindList();
if (compilerWorkspaceSettings == null) {
keepAliveCheckBox.setVisible(false);
k2jvmPanel.setVisible(false);
}
}
public void setTargetPlatform(@Nullable KotlinFacetConfiguration.TargetPlatform targetPlatform) {
k2jsPanel.setVisible(targetPlatform == KotlinFacetConfiguration.TargetPlatform.JS);
}
@SuppressWarnings("unused")
public KotlinCompilerConfigurableTab(Project project) {
this(project,
KotlinCommonCompilerArgumentsHolder.getInstance(project).getSettings(),
Kotlin2JsCompilerArgumentsHolder.getInstance(project).getSettings(),
KotlinCompilerSettings.getInstance(project).getSettings(),
ServiceManager.getService(project, KotlinCompilerWorkspaceSettings.class));
}
@SuppressWarnings("unchecked")
@@ -152,8 +180,9 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
ComparingUtils.isModified(copyRuntimeFilesCheckBox, compilerSettings.getCopyJsLibraryFiles()) ||
ComparingUtils.isModified(outputDirectory, compilerSettings.getOutputDirectoryForJsLibraryFiles()) ||
ComparingUtils.isModified(enablePreciseIncrementalCheckBox, compilerWorkspaceSettings.getPreciseIncrementalEnabled()) ||
ComparingUtils.isModified(keepAliveCheckBox, compilerWorkspaceSettings.getEnableDaemon()) ||
(compilerWorkspaceSettings != null &&
(ComparingUtils.isModified(enablePreciseIncrementalCheckBox, compilerWorkspaceSettings.getPreciseIncrementalEnabled()) ||
ComparingUtils.isModified(keepAliveCheckBox, compilerWorkspaceSettings.getEnableDaemon()))) ||
ComparingUtils.isModified(generateSourceMapsCheckBox, k2jsCompilerArguments.sourceMap) ||
isModified(outputPrefixFile, k2jsCompilerArguments.outputPrefix) ||
@@ -175,12 +204,14 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
compilerSettings.setCopyJsLibraryFiles(copyRuntimeFilesCheckBox.isSelected());
compilerSettings.setOutputDirectoryForJsLibraryFiles(outputDirectory.getText());
compilerWorkspaceSettings.setPreciseIncrementalEnabled(enablePreciseIncrementalCheckBox.isSelected());
if (compilerWorkspaceSettings != null) {
compilerWorkspaceSettings.setPreciseIncrementalEnabled(enablePreciseIncrementalCheckBox.isSelected());
boolean oldEnableDaemon = compilerWorkspaceSettings.getEnableDaemon();
compilerWorkspaceSettings.setEnableDaemon(keepAliveCheckBox.isSelected());
if (keepAliveCheckBox.isSelected() != oldEnableDaemon) {
PluginStartupComponent.getInstance().resetAliveFlag();
boolean oldEnableDaemon = compilerWorkspaceSettings.getEnableDaemon();
compilerWorkspaceSettings.setEnableDaemon(keepAliveCheckBox.isSelected());
if (keepAliveCheckBox.isSelected() != oldEnableDaemon) {
PluginStartupComponent.getInstance().resetAliveFlag();
}
}
k2jsCompilerArguments.sourceMap = generateSourceMapsCheckBox.isSelected();
@@ -208,8 +239,10 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
copyRuntimeFilesCheckBox.setSelected(compilerSettings.getCopyJsLibraryFiles());
outputDirectory.setText(compilerSettings.getOutputDirectoryForJsLibraryFiles());
enablePreciseIncrementalCheckBox.setSelected(compilerWorkspaceSettings.getPreciseIncrementalEnabled());
keepAliveCheckBox.setSelected(compilerWorkspaceSettings.getEnableDaemon());
if (compilerWorkspaceSettings != null) {
enablePreciseIncrementalCheckBox.setSelected(compilerWorkspaceSettings.getPreciseIncrementalEnabled());
keepAliveCheckBox.setSelected(compilerWorkspaceSettings.getEnableDaemon());
}
generateSourceMapsCheckBox.setSelected(k2jsCompilerArguments.sourceMap);
outputPrefixFile.setText(k2jsCompilerArguments.outputPrefix);
@@ -22,6 +22,9 @@ import com.intellij.facet.ui.FacetEditorTab
import com.intellij.facet.ui.FacetValidatorsManager
import com.intellij.openapi.components.PersistentStateComponent
import org.jdom.Element
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.idea.util.DescriptionAware
class KotlinFacetConfiguration : FacetConfiguration, PersistentStateComponent<KotlinFacetConfiguration.Settings> {
@@ -42,8 +45,15 @@ class KotlinFacetConfiguration : FacetConfiguration, PersistentStateComponent<Ko
var targetPlatformKind: TargetPlatform? = null
)
class CompilerInfo {
var commonCompilerArguments: CommonCompilerArguments? = null
var k2jsCompilerArguments: K2JSCompilerArguments? = null
var compilerSettings: CompilerSettings? = null
}
class Settings {
val versionInfo = VersionInfo()
val compilerInfo = CompilerInfo()
}
private var settings = Settings()
@@ -68,7 +78,11 @@ class KotlinFacetConfiguration : FacetConfiguration, PersistentStateComponent<Ko
editorContext: FacetEditorContext,
validatorsManager: FacetValidatorsManager
): Array<FacetEditorTab> {
val tabs = arrayListOf<FacetEditorTab>(KotlinFacetEditorTab(this, editorContext, validatorsManager))
state.initializeIfNeeded(editorContext.module, editorContext.rootModel)
val compilerTab = KotlinFacetEditorCompilerTab(state.compilerInfo, editorContext)
val generalTab = KotlinFacetEditorGeneralTab(this, editorContext, validatorsManager, compilerTab)
val tabs = arrayListOf(generalTab, compilerTab)
KotlinFacetConfigurationExtension.EP_NAME.extensions.flatMapTo(tabs) { it.createEditorTabs(editorContext, validatorsManager) }
return tabs.toTypedArray()
}
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2016 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.FacetEditorContext
import com.intellij.facet.ui.FacetEditorTab
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerConfigurableTab
class KotlinFacetEditorCompilerTab(
compilerInfo: KotlinFacetConfiguration.CompilerInfo,
editorContext: FacetEditorContext
) : FacetEditorTab() {
val compilerConfigurable = KotlinCompilerConfigurableTab(
editorContext.project,
compilerInfo.commonCompilerArguments,
compilerInfo.k2jsCompilerArguments,
compilerInfo.compilerSettings,
null
)
override fun apply() = compilerConfigurable.apply()
override fun getDisplayName() = "Compiler"
override fun createComponent() = compilerConfigurable.createComponent()!!
override fun disposeUIResources() = compilerConfigurable.disposeUIResources()
override fun isModified() = compilerConfigurable.isModified
override fun reset() = compilerConfigurable.reset()
}
@@ -25,10 +25,11 @@ import java.awt.BorderLayout
import java.awt.Component
import javax.swing.*
class KotlinFacetEditorTab(
class KotlinFacetEditorGeneralTab(
private val configuration: KotlinFacetConfiguration,
private val editorContext: FacetEditorContext,
validatorsManager: FacetValidatorsManager
validatorsManager: FacetValidatorsManager,
private val compilerTab: KotlinFacetEditorCompilerTab
) : FacetEditorTab() {
class DescriptionListCellRenderer : DefaultListCellRenderer() {
override fun getListCellRendererComponent(list: JList<*>?, value: Any?, index: Int, isSelected: Boolean, cellHasFocus: Boolean): Component {
@@ -51,8 +52,6 @@ class KotlinFacetEditorTab(
}
}
private val languageVersionComboBox =
JComboBox<KotlinFacetConfiguration.LanguageLevel>(KotlinFacetConfiguration.LanguageLevel.values()).apply {
setRenderer(DescriptionListCellRenderer())
@@ -83,13 +82,18 @@ class KotlinFacetEditorTab(
targetPlatformComboBox.addActionListener {
validatorsManager.validate()
updateCompilerTab()
}
configuration.state.versionInfo.initializeIfNeeded(editorContext.module, editorContext.rootModel)
updateCompilerTab()
reset()
}
private fun updateCompilerTab() {
compilerTab.compilerConfigurable.setTargetPlatform(chosenPlatform)
}
override fun isModified(): Boolean {
return with(configuration.state.versionInfo) {
languageVersionComboBox.selectedItem != languageLevel
@@ -131,4 +135,7 @@ class KotlinFacetEditorTab(
override fun disposeUIResources() {
}
val chosenPlatform: KotlinFacetConfiguration.TargetPlatform?
get() = targetPlatformComboBox.selectedItem as KotlinFacetConfiguration.TargetPlatform?
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.idea.facet
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.projectRoots.JavaSdk
import com.intellij.openapi.projectRoots.JavaSdkVersion
@@ -23,6 +24,11 @@ import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModel
import com.intellij.util.text.VersionComparatorUtil
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerWorkspaceSettings
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider
import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider
import org.jetbrains.kotlin.idea.framework.getLibraryProperties
@@ -95,24 +101,42 @@ internal fun getLibraryLanguageLevel(
return getDefaultLanguageLevel(module, minVersion)
}
internal fun KotlinFacetConfiguration.VersionInfo.initializeIfNeeded(module: Module, rootModel: ModuleRootModel?) {
if (targetPlatformKind == null) {
targetPlatformKind = getDefaultTargetPlatform(module, rootModel)
internal fun KotlinFacetConfiguration.Settings.initializeIfNeeded(module: Module, rootModel: ModuleRootModel?) {
val project = module.project
with(versionInfo) {
if (targetPlatformKind == null) {
targetPlatformKind = getDefaultTargetPlatform(module, rootModel)
}
if (languageLevel == null) {
languageLevel = getDefaultLanguageLevel(module)
}
if (apiLevel == null) {
apiLevel = languageLevel!!.coerceAtMost(getLibraryLanguageLevel(module, rootModel, targetPlatformKind!!))
}
}
if (languageLevel == null) {
languageLevel = getDefaultLanguageLevel(module)
}
with(compilerInfo) {
if (commonCompilerArguments == null) {
commonCompilerArguments = KotlinCommonCompilerArgumentsHolder.getInstance(project).settings.copy()
}
if (apiLevel == null) {
apiLevel = languageLevel!!.coerceAtMost(getLibraryLanguageLevel(module, rootModel, targetPlatformKind!!))
if (compilerSettings == null) {
compilerSettings = CompilerSettings(KotlinCompilerSettings.getInstance(project).settings)
}
if (k2jsCompilerArguments == null) {
k2jsCompilerArguments = Kotlin2JsCompilerArgumentsHolder.getInstance (project).settings.copy()
}
}
}
internal fun Module.getKotlinVersionInfo(rootModel: ModuleRootModel? = null): KotlinFacetConfiguration.VersionInfo {
val versionInfo = KotlinFacet.get(this)?.configuration?.state?.versionInfo ?: KotlinFacetConfiguration.VersionInfo()
versionInfo.initializeIfNeeded(this, rootModel)
return versionInfo
internal fun Module.getKotlinSettings(rootModel: ModuleRootModel? = null): KotlinFacetConfiguration.Settings {
val settings = KotlinFacet.get(this)?.configuration?.state ?: KotlinFacetConfiguration.Settings()
settings.initializeIfNeeded(this, rootModel)
return settings
}
val KotlinFacetConfiguration.TargetPlatform.mavenLibraryId: String