as31: Kotlin Facet: Configure facet based on Android build variant (in AS)
#KT-19958 Fixed
This commit is contained in:
committed by
Nikolay Krasko
parent
a9cdccc6de
commit
6636c4376b
+40
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* 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.android.configure
|
||||||
|
|
||||||
|
import com.android.tools.idea.gradle.project.model.AndroidModuleModel
|
||||||
|
import com.android.tools.idea.gradle.project.sync.setup.post.ModuleSetupStep
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.progress.ProgressIndicator
|
||||||
|
import org.jetbrains.android.facet.AndroidFacet
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.compilerArgumentsBySourceSet
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.configureFacetByCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.sourceSetName
|
||||||
|
import org.jetbrains.kotlin.idea.facet.KotlinFacet
|
||||||
|
|
||||||
|
class KotlinAndroidModuleSetupStep : ModuleSetupStep() {
|
||||||
|
override fun setUpModule(module: Module, progressIndicator: ProgressIndicator?) {
|
||||||
|
val facet = AndroidFacet.getInstance(module) ?: return
|
||||||
|
val androidModel = AndroidModuleModel.get(facet) ?: return
|
||||||
|
val sourceSetName = androidModel.selectedVariant.name
|
||||||
|
if (module.sourceSetName == sourceSetName) return
|
||||||
|
val argsInfo = module.compilerArgumentsBySourceSet?.get(sourceSetName) ?: return
|
||||||
|
val kotlinFacet = KotlinFacet.get(module) ?: return
|
||||||
|
module.sourceSetName = sourceSetName
|
||||||
|
configureFacetByCompilerArguments(kotlinFacet, argsInfo, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -46,7 +46,8 @@ class KotlinGradleAndroidModuleModelProjectDataService : AbstractProjectDataServ
|
|||||||
val moduleNode = ExternalSystemApiUtil.findParent(moduleModelNode, ProjectKeys.MODULE) ?: continue
|
val moduleNode = ExternalSystemApiUtil.findParent(moduleModelNode, ProjectKeys.MODULE) ?: continue
|
||||||
val moduleData = moduleNode.data
|
val moduleData = moduleNode.data
|
||||||
val ideModule = modelsProvider.findIdeModule(moduleData) ?: continue
|
val ideModule = modelsProvider.findIdeModule(moduleData) ?: continue
|
||||||
val kotlinFacet = configureFacetByGradleModule(moduleNode, null, ideModule, modelsProvider) ?: continue
|
val sourceSetName = moduleModelNode.data.selectedVariant.name
|
||||||
|
val kotlinFacet = configureFacetByGradleModule(moduleNode, sourceSetName, ideModule, modelsProvider) ?: continue
|
||||||
GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, moduleNode) }
|
GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, moduleNode) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-13
@@ -26,11 +26,13 @@ import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsPr
|
|||||||
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
||||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
import com.intellij.openapi.module.Module
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.module.isQualifiedModuleNamesEnabled
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.roots.OrderRootType
|
import com.intellij.openapi.roots.OrderRootType
|
||||||
import com.intellij.openapi.roots.impl.libraries.LibraryEx
|
import com.intellij.openapi.roots.impl.libraries.LibraryEx
|
||||||
import com.intellij.openapi.roots.impl.libraries.LibraryImpl
|
import com.intellij.openapi.roots.impl.libraries.LibraryImpl
|
||||||
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
|
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.util.PathUtil
|
import com.intellij.util.PathUtil
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
@@ -40,6 +42,8 @@ import org.jetbrains.kotlin.config.JvmTarget
|
|||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.TargetPlatformKind
|
import org.jetbrains.kotlin.config.TargetPlatformKind
|
||||||
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor
|
||||||
|
import org.jetbrains.kotlin.gradle.ArgsInfo
|
||||||
|
import org.jetbrains.kotlin.gradle.CompilerArgumentsBySourceSet
|
||||||
import org.jetbrains.kotlin.idea.facet.*
|
import org.jetbrains.kotlin.idea.facet.*
|
||||||
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
|
import org.jetbrains.kotlin.idea.framework.CommonLibraryKind
|
||||||
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
|
import org.jetbrains.kotlin.idea.framework.JSLibraryKind
|
||||||
@@ -47,11 +51,18 @@ import org.jetbrains.kotlin.idea.framework.detectLibraryKind
|
|||||||
import org.jetbrains.kotlin.idea.inspections.gradle.findAll
|
import org.jetbrains.kotlin.idea.inspections.gradle.findAll
|
||||||
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
|
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
|
||||||
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData
|
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData
|
||||||
|
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||||
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
|
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
|
||||||
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
|
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
var Module.compilerArgumentsBySourceSet
|
||||||
|
by UserDataProperty(Key.create<CompilerArgumentsBySourceSet>("CURRENT_COMPILER_ARGUMENTS"))
|
||||||
|
|
||||||
|
var Module.sourceSetName
|
||||||
|
by UserDataProperty(Key.create<String>("SOURCE_SET_NAME"))
|
||||||
|
|
||||||
interface GradleProjectImportHandler {
|
interface GradleProjectImportHandler {
|
||||||
companion object : ProjectExtensionDescriptor<GradleProjectImportHandler>(
|
companion object : ProjectExtensionDescriptor<GradleProjectImportHandler>(
|
||||||
"org.jetbrains.kotlin.gradleProjectImportHandler",
|
"org.jetbrains.kotlin.gradleProjectImportHandler",
|
||||||
@@ -76,7 +87,8 @@ class KotlinGradleSourceSetDataService : AbstractProjectDataService<GradleSource
|
|||||||
val ideModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
|
val ideModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
|
||||||
|
|
||||||
val moduleNode = ExternalSystemApiUtil.findParent(sourceSetNode, ProjectKeys.MODULE) ?: continue
|
val moduleNode = ExternalSystemApiUtil.findParent(sourceSetNode, ProjectKeys.MODULE) ?: continue
|
||||||
val kotlinFacet = configureFacetByGradleModule(moduleNode, sourceSetNode, ideModule, modelsProvider) ?: continue
|
val sourceSetName = sourceSetNode.data.id.let { it.substring(it.lastIndexOf(':') + 1) }
|
||||||
|
val kotlinFacet = configureFacetByGradleModule(moduleNode, sourceSetName, ideModule, modelsProvider) ?: continue
|
||||||
GradleProjectImportHandler.getInstances(project).forEach { it.importBySourceSet(kotlinFacet, sourceSetNode) }
|
GradleProjectImportHandler.getInstances(project).forEach { it.importBySourceSet(kotlinFacet, sourceSetNode) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +186,7 @@ private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPla
|
|||||||
|
|
||||||
fun configureFacetByGradleModule(
|
fun configureFacetByGradleModule(
|
||||||
moduleNode: DataNode<ModuleData>,
|
moduleNode: DataNode<ModuleData>,
|
||||||
sourceSetNode: DataNode<GradleSourceSetData>?,
|
sourceSetName: String?,
|
||||||
ideModule: Module,
|
ideModule: Module,
|
||||||
modelsProvider: IdeModifiableModelsProvider
|
modelsProvider: IdeModifiableModelsProvider
|
||||||
): KotlinFacet? {
|
): KotlinFacet? {
|
||||||
@@ -200,23 +212,17 @@ fun configureFacetByGradleModule(
|
|||||||
val kotlinFacet = ideModule.getOrCreateFacet(modelsProvider, false)
|
val kotlinFacet = ideModule.getOrCreateFacet(modelsProvider, false)
|
||||||
kotlinFacet.configureFacet(compilerVersion, coroutinesProperty, platformKind, modelsProvider)
|
kotlinFacet.configureFacet(compilerVersion, coroutinesProperty, platformKind, modelsProvider)
|
||||||
|
|
||||||
val sourceSetName = sourceSetNode?.data?.id?.let { it.substring(it.lastIndexOf(':') + 1) }
|
ideModule.compilerArgumentsBySourceSet = moduleNode.compilerArgumentsBySourceSet
|
||||||
|
ideModule.sourceSetName = sourceSetName
|
||||||
|
|
||||||
val argsInfo = moduleNode.compilerArgumentsBySourceSet?.get(sourceSetName ?: "main")
|
val argsInfo = moduleNode.compilerArgumentsBySourceSet?.get(sourceSetName ?: "main")
|
||||||
if (argsInfo != null) {
|
if (argsInfo != null) {
|
||||||
val currentCompilerArguments = argsInfo.currentArguments
|
configureFacetByCompilerArguments(kotlinFacet, argsInfo, modelsProvider)
|
||||||
val defaultCompilerArguments = argsInfo.defaultArguments
|
|
||||||
val dependencyClasspath = argsInfo.dependencyClasspath.map { PathUtil.toSystemIndependentName(it) }
|
|
||||||
if (currentCompilerArguments.isNotEmpty()) {
|
|
||||||
parseCompilerArgumentsToFacet(currentCompilerArguments, defaultCompilerArguments, kotlinFacet, modelsProvider)
|
|
||||||
}
|
|
||||||
adjustClasspath(kotlinFacet, dependencyClasspath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
with(kotlinFacet.configuration.settings) {
|
with(kotlinFacet.configuration.settings) {
|
||||||
implementedModuleNames = (sourceSetNode ?: moduleNode).implementedModuleNames
|
implementedModuleNames = getImplementedModuleNames(moduleNode, sourceSetName, ideModule.project)
|
||||||
productionOutputPath = getExplicitOutputPath(moduleNode, platformKind, "main")
|
testOutputPath = getExplicitTestOutputPath(moduleNode, platformKind)
|
||||||
testOutputPath = getExplicitOutputPath(moduleNode, platformKind, "test")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinFacet.noVersionAutoAdvance()
|
kotlinFacet.noVersionAutoAdvance()
|
||||||
@@ -224,6 +230,23 @@ fun configureFacetByGradleModule(
|
|||||||
return kotlinFacet
|
return kotlinFacet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun configureFacetByCompilerArguments(kotlinFacet: KotlinFacet, argsInfo: ArgsInfo, modelsProvider: IdeModifiableModelsProvider?) {
|
||||||
|
val currentCompilerArguments = argsInfo.currentArguments
|
||||||
|
val defaultCompilerArguments = argsInfo.defaultArguments
|
||||||
|
val dependencyClasspath = argsInfo.dependencyClasspath.map { PathUtil.toSystemIndependentName(it) }
|
||||||
|
if (currentCompilerArguments.isNotEmpty()) {
|
||||||
|
parseCompilerArgumentsToFacet(currentCompilerArguments, defaultCompilerArguments, kotlinFacet, modelsProvider)
|
||||||
|
}
|
||||||
|
adjustClasspath(kotlinFacet, dependencyClasspath)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getImplementedModuleNames(moduleNode: DataNode<ModuleData>, sourceSetName: String?, project: Project): List<String> {
|
||||||
|
val baseModuleNames = moduleNode.implementedModuleNames
|
||||||
|
if (baseModuleNames.isEmpty() || sourceSetName == null) return baseModuleNames
|
||||||
|
val delimiter = if(isQualifiedModuleNamesEnabled(project)) "." else "_"
|
||||||
|
return baseModuleNames.map { "$it$delimiter$sourceSetName" }
|
||||||
|
}
|
||||||
|
|
||||||
private fun getExplicitOutputPath(moduleNode: DataNode<ModuleData>, platformKind: TargetPlatformKind<*>?, sourceSet: String): String? {
|
private fun getExplicitOutputPath(moduleNode: DataNode<ModuleData>, platformKind: TargetPlatformKind<*>?, sourceSet: String): String? {
|
||||||
if (platformKind !== TargetPlatformKind.JavaScript) return null
|
if (platformKind !== TargetPlatformKind.JavaScript) return null
|
||||||
val k2jsArgumentList = moduleNode.compilerArgumentsBySourceSet?.get(sourceSet)?.currentArguments ?: return null
|
val k2jsArgumentList = moduleNode.compilerArgumentsBySourceSet?.get(sourceSet)?.currentArguments ?: return null
|
||||||
|
|||||||
@@ -110,6 +110,10 @@
|
|||||||
<androidLintQuickFixProvider implementation="org.jetbrains.kotlin.android.quickfix.KotlinAndroidQuickFixProvider" />
|
<androidLintQuickFixProvider implementation="org.jetbrains.kotlin.android.quickfix.KotlinAndroidQuickFixProvider" />
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|
||||||
|
<extensions defaultExtensionNs="com.android.gradle.sync">
|
||||||
|
<postSyncModuleSetupStep implementation="org.jetbrains.kotlin.android.configure.KotlinAndroidModuleSetupStep"/>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
<extensions defaultExtensionNs="org.jetbrains.kotlin.android.model">
|
<extensions defaultExtensionNs="org.jetbrains.kotlin.android.model">
|
||||||
<androidModuleInfoProvider implementation="org.jetbrains.kotlin.android.model.impl.AndroidModuleInfoProviderImpl"/>
|
<androidModuleInfoProvider implementation="org.jetbrains.kotlin.android.model.impl.AndroidModuleInfoProviderImpl"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
|||||||
@@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* 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.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||||
|
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProviderImpl
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.projectRoots.JavaSdk
|
||||||
|
import com.intellij.openapi.projectRoots.JavaSdkVersion
|
||||||
|
import com.intellij.openapi.projectRoots.ProjectJdkTable
|
||||||
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
|
import com.intellij.openapi.roots.ModuleRootModel
|
||||||
|
import com.intellij.openapi.roots.ProjectRootModificationTracker
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
import com.intellij.psi.util.CachedValueProvider
|
||||||
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
|
import org.jetbrains.kotlin.caches.resolve.KotlinCacheService
|
||||||
|
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
|
||||||
|
import org.jetbrains.kotlin.config.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.project.*
|
||||||
|
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder
|
||||||
|
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder
|
||||||
|
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder
|
||||||
|
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
||||||
|
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.idea.versions.*
|
||||||
|
import kotlin.reflect.KProperty1
|
||||||
|
|
||||||
|
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): TargetPlatformKind<*> {
|
||||||
|
for (platform in TargetPlatformKind.ALL_PLATFORMS) {
|
||||||
|
if (getRuntimeLibraryVersions(module, rootModel, platform).isNotEmpty()) {
|
||||||
|
return platform
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk
|
||||||
|
val sdkVersion = (sdk?.sdkType as? JavaSdk)?.getVersion(sdk!!)
|
||||||
|
return when {
|
||||||
|
sdkVersion == null || sdkVersion >= JavaSdkVersion.JDK_1_8 -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_8]
|
||||||
|
else -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinFacetSettings.initializeIfNeeded(
|
||||||
|
module: Module,
|
||||||
|
rootModel: ModuleRootModel?,
|
||||||
|
platformKind: TargetPlatformKind<*>? = null, // if null, detect by module dependencies
|
||||||
|
languageVersion: String? = null
|
||||||
|
) {
|
||||||
|
val project = module.project
|
||||||
|
|
||||||
|
val shouldInferLanguageLevel = languageLevel == null
|
||||||
|
val shouldInferAPILevel = apiLevel == null
|
||||||
|
|
||||||
|
if (compilerSettings == null) {
|
||||||
|
compilerSettings = KotlinCompilerSettings.getInstance(project).settings
|
||||||
|
}
|
||||||
|
|
||||||
|
val commonArguments = KotlinCommonCompilerArgumentsHolder.getInstance(module.project).settings
|
||||||
|
|
||||||
|
if (compilerArguments == null) {
|
||||||
|
val targetPlatformKind = platformKind ?: getDefaultTargetPlatform(module, rootModel)
|
||||||
|
compilerArguments = targetPlatformKind.createCompilerArguments {
|
||||||
|
targetPlatformKind.getPlatformCompilerArgumentsByProject(module.project)?.let { mergeBeans(it, this) }
|
||||||
|
mergeBeans(commonArguments, this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldInferLanguageLevel) {
|
||||||
|
languageLevel = (if (useProjectSettings) LanguageVersion.fromVersionString(commonArguments.languageVersion) else null)
|
||||||
|
?: getDefaultLanguageLevel(module, languageVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldInferAPILevel) {
|
||||||
|
apiLevel = if (useProjectSettings) {
|
||||||
|
LanguageVersion.fromVersionString(commonArguments.apiVersion) ?: languageLevel
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
languageLevel!!.coerceAtMost(getLibraryLanguageLevel(module, rootModel, targetPlatformKind))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TargetPlatformKind<*>.getPlatformCompilerArgumentsByProject(project: Project): CommonCompilerArguments? {
|
||||||
|
return when (this) {
|
||||||
|
is TargetPlatformKind.Jvm -> Kotlin2JvmCompilerArgumentsHolder.getInstance(project).settings
|
||||||
|
is TargetPlatformKind.JavaScript -> Kotlin2JsCompilerArgumentsHolder.getInstance(project).settings
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val TargetPlatformKind<*>.mavenLibraryIds: List<String>
|
||||||
|
get() = when (this) {
|
||||||
|
is TargetPlatformKind.Jvm -> listOf(MAVEN_STDLIB_ID, MAVEN_STDLIB_ID_JRE7, MAVEN_STDLIB_ID_JDK7, MAVEN_STDLIB_ID_JRE8, MAVEN_STDLIB_ID_JDK8)
|
||||||
|
is TargetPlatformKind.JavaScript -> listOf(MAVEN_JS_STDLIB_ID, MAVEN_OLD_JS_STDLIB_ID)
|
||||||
|
is TargetPlatformKind.Common -> listOf(MAVEN_COMMON_STDLIB_ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
val mavenLibraryIdToPlatform: Map<String, TargetPlatformKind<*>> by lazy {
|
||||||
|
TargetPlatformKind.ALL_PLATFORMS
|
||||||
|
.flatMap { platform -> platform.mavenLibraryIds.map { it to platform } }
|
||||||
|
.sortedByDescending { it.first.length }
|
||||||
|
.toMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Module.getOrCreateFacet(modelsProvider: IdeModifiableModelsProvider,
|
||||||
|
useProjectSettings: Boolean,
|
||||||
|
commitModel: Boolean = false): KotlinFacet {
|
||||||
|
val facetModel = modelsProvider.getModifiableFacetModel(this)
|
||||||
|
|
||||||
|
val facet = facetModel.findFacet(KotlinFacetType.TYPE_ID, KotlinFacetType.INSTANCE.defaultFacetName)
|
||||||
|
?: with(KotlinFacetType.INSTANCE) { createFacet(this@getOrCreateFacet, defaultFacetName, createDefaultConfiguration(), null) }
|
||||||
|
.apply { facetModel.addFacet(this) }
|
||||||
|
facet.configuration.settings.useProjectSettings = useProjectSettings
|
||||||
|
if (commitModel) {
|
||||||
|
runWriteAction {
|
||||||
|
facetModel.commit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return facet
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinFacet.configureFacet(
|
||||||
|
compilerVersion: String,
|
||||||
|
coroutineSupport: LanguageFeature.State,
|
||||||
|
platformKind: TargetPlatformKind<*>?, // if null, detect by module dependencies
|
||||||
|
modelsProvider: IdeModifiableModelsProvider
|
||||||
|
) {
|
||||||
|
val module = module
|
||||||
|
with(configuration.settings) {
|
||||||
|
compilerArguments = null
|
||||||
|
compilerSettings = null
|
||||||
|
initializeIfNeeded(
|
||||||
|
module,
|
||||||
|
modelsProvider.getModifiableRootModel(module),
|
||||||
|
platformKind,
|
||||||
|
compilerVersion
|
||||||
|
)
|
||||||
|
val apiLevel = apiLevel
|
||||||
|
val languageLevel = languageLevel
|
||||||
|
if (languageLevel != null && apiLevel != null && apiLevel > languageLevel) {
|
||||||
|
this.apiLevel = languageLevel
|
||||||
|
}
|
||||||
|
this.coroutineSupport = coroutineSupport
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KotlinFacet.noVersionAutoAdvance() {
|
||||||
|
configuration.settings.compilerArguments?.let {
|
||||||
|
it.autoAdvanceLanguageVersion = false
|
||||||
|
it.autoAdvanceApiVersion = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Primary" fields are written to argument beans directly and thus not presented in the "additional arguments" string
|
||||||
|
// Update these lists when facet/project settings UI changes
|
||||||
|
val commonUIExposedFields = listOf(CommonCompilerArguments::languageVersion.name,
|
||||||
|
CommonCompilerArguments::apiVersion.name,
|
||||||
|
CommonCompilerArguments::suppressWarnings.name,
|
||||||
|
CommonCompilerArguments::coroutinesState.name)
|
||||||
|
private val commonUIHiddenFields = listOf(CommonCompilerArguments::pluginClasspaths.name,
|
||||||
|
CommonCompilerArguments::pluginOptions.name)
|
||||||
|
private val commonPrimaryFields = commonUIExposedFields + commonUIHiddenFields
|
||||||
|
|
||||||
|
private val jvmSpecificUIExposedFields = listOf(K2JVMCompilerArguments::jvmTarget.name,
|
||||||
|
K2JVMCompilerArguments::destination.name,
|
||||||
|
K2JVMCompilerArguments::classpath.name)
|
||||||
|
val jvmUIExposedFields = commonUIExposedFields + jvmSpecificUIExposedFields
|
||||||
|
private val jvmPrimaryFields = commonPrimaryFields + jvmSpecificUIExposedFields
|
||||||
|
|
||||||
|
private val jsSpecificUIExposedFields = listOf(K2JSCompilerArguments::sourceMap.name,
|
||||||
|
K2JSCompilerArguments::sourceMapPrefix.name,
|
||||||
|
K2JSCompilerArguments::sourceMapEmbedSources.name,
|
||||||
|
K2JSCompilerArguments::outputPrefix.name,
|
||||||
|
K2JSCompilerArguments::outputPostfix.name,
|
||||||
|
K2JSCompilerArguments::moduleKind.name)
|
||||||
|
val jsUIExposedFields = commonUIExposedFields + jsSpecificUIExposedFields
|
||||||
|
private val jsPrimaryFields = commonPrimaryFields + jsSpecificUIExposedFields
|
||||||
|
|
||||||
|
private val metadataSpecificUIExposedFields = listOf(K2MetadataCompilerArguments::destination.name,
|
||||||
|
K2MetadataCompilerArguments::classpath.name)
|
||||||
|
val metadataUIExposedFields = commonUIExposedFields + metadataSpecificUIExposedFields
|
||||||
|
private val metadataPrimaryFields = commonPrimaryFields + metadataSpecificUIExposedFields
|
||||||
|
|
||||||
|
private val CommonCompilerArguments.primaryFields: List<String>
|
||||||
|
get() = when (this) {
|
||||||
|
is K2JVMCompilerArguments -> jvmPrimaryFields
|
||||||
|
is K2JSCompilerArguments -> jsPrimaryFields
|
||||||
|
is K2MetadataCompilerArguments -> metadataPrimaryFields
|
||||||
|
else -> commonPrimaryFields
|
||||||
|
}
|
||||||
|
|
||||||
|
private val CommonCompilerArguments.ignoredFields: List<String>
|
||||||
|
get() = when (this) {
|
||||||
|
is K2JVMCompilerArguments -> listOf(K2JVMCompilerArguments::noJdk.name, K2JVMCompilerArguments::jdkHome.name)
|
||||||
|
else -> emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Module.configureSdkIfPossible(compilerArguments: CommonCompilerArguments, modelsProvider: IdeModifiableModelsProvider) {
|
||||||
|
val allSdks = ProjectJdkTable.getInstance().allJdks
|
||||||
|
val sdk = if (compilerArguments is K2JVMCompilerArguments) {
|
||||||
|
val jdkHome = compilerArguments.jdkHome ?: return
|
||||||
|
allSdks.firstOrNull { it.sdkType is JavaSdk && FileUtil.comparePaths(it.homePath, jdkHome) == 0 } ?: return
|
||||||
|
} else {
|
||||||
|
allSdks.firstOrNull { it.sdkType is KotlinSdkType } ?: KotlinSdkType.INSTANCE.createSdkWithUniqueName(allSdks.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
modelsProvider.getModifiableRootModel(this).sdk = sdk
|
||||||
|
}
|
||||||
|
|
||||||
|
fun parseCompilerArgumentsToFacet(
|
||||||
|
arguments: List<String>,
|
||||||
|
defaultArguments: List<String>,
|
||||||
|
kotlinFacet: KotlinFacet,
|
||||||
|
modelsProvider: IdeModifiableModelsProvider?
|
||||||
|
) {
|
||||||
|
with(kotlinFacet.configuration.settings) {
|
||||||
|
val compilerArguments = this.compilerArguments ?: return
|
||||||
|
|
||||||
|
val defaultCompilerArguments = compilerArguments::class.java.newInstance()
|
||||||
|
parseCommandLineArguments(defaultArguments, defaultCompilerArguments)
|
||||||
|
defaultCompilerArguments.convertPathsToSystemIndependent()
|
||||||
|
|
||||||
|
parseCommandLineArguments(arguments, compilerArguments)
|
||||||
|
|
||||||
|
compilerArguments.convertPathsToSystemIndependent()
|
||||||
|
|
||||||
|
// Retain only fields exposed (and not explicitly ignored) in facet configuration editor.
|
||||||
|
// The rest is combined into string and stored in CompilerSettings.additionalArguments
|
||||||
|
|
||||||
|
kotlinFacet.module.configureSdkIfPossible(compilerArguments, modelsProvider)
|
||||||
|
|
||||||
|
val primaryFields = compilerArguments.primaryFields
|
||||||
|
val ignoredFields = compilerArguments.ignoredFields
|
||||||
|
|
||||||
|
fun exposeAsAdditionalArgument(property: KProperty1<CommonCompilerArguments, Any?>) =
|
||||||
|
property.name !in primaryFields && property.get(compilerArguments) != property.get(defaultCompilerArguments)
|
||||||
|
|
||||||
|
val additionalArgumentsString = with(compilerArguments::class.java.newInstance()) {
|
||||||
|
copyFieldsSatisfying(compilerArguments, this) { exposeAsAdditionalArgument(it) && it.name !in ignoredFields }
|
||||||
|
ArgumentUtils.convertArgumentsToStringList(this).joinToString(separator = " ") {
|
||||||
|
if (StringUtil.containsWhitespaces(it) || it.startsWith('"')) {
|
||||||
|
StringUtil.wrapWithDoubleQuote(StringUtil.escapeQuotes(it))
|
||||||
|
} else it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compilerSettings?.additionalArguments =
|
||||||
|
if (additionalArgumentsString.isNotEmpty()) additionalArgumentsString else CompilerSettings.DEFAULT_ADDITIONAL_ARGUMENTS
|
||||||
|
|
||||||
|
with(compilerArguments::class.java.newInstance()) {
|
||||||
|
copyFieldsSatisfying(this, compilerArguments) { exposeAsAdditionalArgument(it) || it.name in ignoredFields }
|
||||||
|
}
|
||||||
|
|
||||||
|
val languageLevel = languageLevel
|
||||||
|
val apiLevel = apiLevel
|
||||||
|
if (languageLevel != null && apiLevel != null && apiLevel > languageLevel) {
|
||||||
|
this.apiLevel = languageLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
updateMergedArguments()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user