From 591910a216ef2960f492c5af27f354ef9463af3f Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 24 Jan 2017 16:27:25 +0300 Subject: [PATCH] Kotlin Facet: Import compiler arguments from Gradle project #KT-15819 Fixed #KT-15929 Fixed --- .idea/artifacts/KotlinPlugin.xml | 1 + .../cli/common/arguments/argumentUtils.kt | 12 ++++--- .../kotlin-gradle-tooling.iml | 1 + .../src/KotlinGradleModelBuilder.kt | 33 +++++++++++++++---- .../KotlinGradleProjectDataService.kt | 8 ++--- .../KotlinGradleProjectResolverExtension.kt | 7 ++++ .../jetbrains/kotlin/idea/facet/facetUtils.kt | 25 ++++++++++++++ 7 files changed, 72 insertions(+), 15 deletions(-) diff --git a/.idea/artifacts/KotlinPlugin.xml b/.idea/artifacts/KotlinPlugin.xml index 2e19cf5889a..31b46acd7b9 100644 --- a/.idea/artifacts/KotlinPlugin.xml +++ b/.idea/artifacts/KotlinPlugin.xml @@ -10,6 +10,7 @@ + diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/argumentUtils.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/argumentUtils.kt index 4e14e89e91b..1ec96cf8aa5 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/argumentUtils.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/argumentUtils.kt @@ -22,15 +22,17 @@ import java.lang.reflect.Field import java.lang.reflect.Modifier import java.util.* -fun parseArguments(args: Array, arguments: A) { +@JvmOverloads fun parseArguments(args: Array, arguments: A, ignoreInvalidArguments: Boolean = false) { val unparsedArgs = Args.parse(arguments, args, false) val (unknownExtraArgs, unknownArgs) = unparsedArgs.partition { it.startsWith("-X") } arguments.unknownExtraFlags = unknownExtraArgs - arguments.freeArgs = unknownArgs + arguments.freeArgs = if (ignoreInvalidArguments) unknownArgs.filterNot { it.startsWith("-") } else unknownArgs - for (argument in arguments.freeArgs) { - if (argument.startsWith("-")) { - throw IllegalArgumentException("Invalid argument: " + argument) + if (!ignoreInvalidArguments) { + for (argument in unknownArgs) { + if (argument.startsWith("-")) { + throw IllegalArgumentException("Invalid argument: " + argument) + } } } } diff --git a/idea/kotlin-gradle-tooling/kotlin-gradle-tooling.iml b/idea/kotlin-gradle-tooling/kotlin-gradle-tooling.iml index 8d6ac6d91f9..01cae37ce24 100644 --- a/idea/kotlin-gradle-tooling/kotlin-gradle-tooling.iml +++ b/idea/kotlin-gradle-tooling/kotlin-gradle-tooling.iml @@ -7,6 +7,7 @@ + diff --git a/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt b/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt index 641f4322ac4..ff1e15f588a 100644 --- a/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt +++ b/idea/kotlin-gradle-tooling/src/KotlinGradleModelBuilder.kt @@ -25,25 +25,46 @@ import java.lang.Exception interface KotlinGradleModel : Serializable { val implements: String? + val serializedCompilerArguments: List? } -class KotlinGradleModelImpl(override val implements: String?) : KotlinGradleModel +class KotlinGradleModelImpl( + override val implements: String?, + override val serializedCompilerArguments: List? +) : KotlinGradleModel class KotlinGradleModelBuilder : ModelBuilderService { + companion object { + val compileTasks = listOf("compileKotlin", "compileKotlin2Js") + } + override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder { return ErrorMessageBuilder.create(project, e, "Gradle import errors").withDescription("Unable to build Kotlin project configuration") } override fun canBuild(modelName: String?): Boolean = modelName == KotlinGradleModel::class.java.name - override fun buildAll(modelName: String?, project: Project): Any { + private fun getImplements(project: Project): String? { val implementsConfiguration = project.configurations.findByName("implement") if (implementsConfiguration != null) { val implementsProjectDependency = implementsConfiguration.dependencies.filterIsInstance().firstOrNull() - if (implementsProjectDependency != null) { - return KotlinGradleModelImpl(implementsProjectDependency.dependencyProject.path) - } + if (implementsProjectDependency != null) return implementsProjectDependency.dependencyProject.path } - return KotlinGradleModelImpl(null) + return null } + + @Suppress("UNCHECKED_CAST") + private fun getCompilerArguments(project: Project): List? { + val compileTask = compileTasks.mapNotNull { project.getTasksByName(it, false).firstOrNull() }.firstOrNull() ?: return null + val taskClass = compileTask.javaClass + return try { + taskClass.getDeclaredMethod("getSerializedCompilerArguments").invoke(compileTask) as List + } + catch (e : NoSuchMethodException) { + null + } + } + + override fun buildAll(modelName: String?, project: Project) = + KotlinGradleModelImpl(getImplements(project), getCompilerArguments(project)) } diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt index 6c62fa0527b..2a6c1af0db7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinGradleProjectDataService.kt @@ -24,14 +24,13 @@ import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsPr import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.project.Project +import com.intellij.util.text.VersionComparatorUtil +import org.jetbrains.kotlin.cli.common.arguments.* import org.jetbrains.kotlin.config.CoroutineSupport import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.TargetPlatformKind import org.jetbrains.kotlin.extensions.ProjectExtensionDescriptor -import org.jetbrains.kotlin.idea.facet.KotlinFacet -import org.jetbrains.kotlin.idea.facet.configureFacet -import org.jetbrains.kotlin.idea.facet.getOrCreateFacet -import org.jetbrains.kotlin.idea.facet.mavenLibraryId +import org.jetbrains.kotlin.idea.facet.* import org.jetbrains.kotlin.idea.inspections.gradle.findAll import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData @@ -88,6 +87,7 @@ class KotlinGradleProjectDataService : AbstractProjectDataService.serializedCompilerArguments by UserDataProperty(Key.create>("SERIALIZED_COMPILER_ARGUMENTS")) + class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() { override fun getToolingExtensionsClasses(): Set> { return setOf(KotlinGradleModelBuilder::class.java, Unit::class.java) @@ -44,6 +48,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() ideModule: DataNode, ideProject: DataNode) { val gradleModel = resolverCtx.getExtraProject(gradleModule, KotlinGradleModel::class.java) ?: return + gradleModel.implements?.let { implementsModuleId -> val targetModule = findModule(ideProject, implementsModuleId) ?: return if (resolverCtx.isResolveModulePerSourceSet) { @@ -54,6 +59,8 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() } } + ideModule.serializedCompilerArguments = gradleModel.serializedCompilerArguments + super.populateModuleDependencies(gradleModule, ideModule, ideProject) } diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt b/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt index fe2e7fb6ecf..a8322206be1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt @@ -25,7 +25,9 @@ import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootModel import com.intellij.openapi.roots.OrderRootType import com.intellij.util.text.VersionComparatorUtil +import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.arguments.copyBean +import org.jetbrains.kotlin.cli.common.arguments.parseArguments import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder @@ -181,4 +183,27 @@ fun KotlinFacet.configureFacet( } compilerInfo.coroutineSupport = coroutineSupport } +} + +fun parseCompilerArgumentsToFacet(arguments: List, kotlinFacet: KotlinFacet) { + val argumentArray = arguments.toTypedArray() + with(kotlinFacet.configuration.settings) { + // todo: merge common arguments with platform-specific ones in facet settings + parseArguments(argumentArray, compilerInfo.commonCompilerArguments!!, ignoreInvalidArguments = true) + + when (versionInfo.targetPlatformKind) { + is TargetPlatformKind.Jvm -> { + val jvmTarget = K2JVMCompilerArguments().apply { parseArguments(argumentArray, this) }.jvmTarget + if (jvmTarget != null) { + versionInfo.targetPlatformKind = TargetPlatformKind.Jvm.JVM_PLATFORMS.firstOrNull { + VersionComparatorUtil.compare(it.version.description, jvmTarget) >= 0 + } ?: TargetPlatformKind.Jvm.JVM_PLATFORMS.last() + } + } + is TargetPlatformKind.JavaScript -> parseArguments(argumentArray, compilerInfo.k2jsCompilerArguments!!) + else -> {} + } + + compilerInfo.compilerSettings!!.additionalArguments = compilerInfo.commonCompilerArguments!!.freeArgs.joinToString(separator = " ") + } } \ No newline at end of file