Kotlin Facet: Import compiler arguments from Gradle project

#KT-15819 Fixed
 #KT-15929 Fixed
This commit is contained in:
Alexey Sedunov
2017-01-24 16:27:25 +03:00
parent dafb6f8b3c
commit 591910a216
7 changed files with 72 additions and 15 deletions
+1
View File
@@ -10,6 +10,7 @@
<root id="root">
<element id="directory" name="lib">
<element id="archive" name="kotlin-plugin.jar">
<element id="extracted-dir" path="$PROJECT_DIR$/dependencies/cli-parser-1.1.2.jar" path-in-jar="/" />
<element id="module-output" name="backend" />
<element id="module-output" name="frontend" />
<element id="module-output" name="descriptors" />
@@ -22,15 +22,17 @@ import java.lang.reflect.Field
import java.lang.reflect.Modifier
import java.util.*
fun <A : CommonCompilerArguments> parseArguments(args: Array<String>, arguments: A) {
@JvmOverloads fun <A : CommonCompilerArguments> parseArguments(args: Array<String>, 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)
}
}
}
}
@@ -7,6 +7,7 @@
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="cli-common" />
<orderEntry type="library" name="gradle-and-groovy-plugin" level="project" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component>
@@ -25,25 +25,46 @@ import java.lang.Exception
interface KotlinGradleModel : Serializable {
val implements: String?
val serializedCompilerArguments: List<String>?
}
class KotlinGradleModelImpl(override val implements: String?) : KotlinGradleModel
class KotlinGradleModelImpl(
override val implements: String?,
override val serializedCompilerArguments: List<String>?
) : 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<ProjectDependency>().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<String>? {
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<String>
}
catch (e : NoSuchMethodException) {
null
}
}
override fun buildAll(modelName: String?, project: Project) =
KotlinGradleModelImpl(getImplements(project), getCompilerArguments(project))
}
@@ -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<GradleSourceSe
val kotlinFacet = ideModule.getOrCreateFacet(modelsProvider, false)
kotlinFacet.configureFacet(compilerVersion, coroutinesProperty, platformKind, modelsProvider)
moduleNode.serializedCompilerArguments?.let { parseCompilerArgumentsToFacet(it, kotlinFacet) }
GradleProjectImportHandler.getInstances(project).forEach { it(kotlinFacet, sourceSetNode) }
}
}
@@ -23,14 +23,18 @@ import com.intellij.openapi.externalSystem.model.project.ModuleDependencyData
import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.util.Key
import org.gradle.tooling.model.idea.IdeaModule
import org.jetbrains.kotlin.gradle.KotlinGradleModel
import org.jetbrains.kotlin.gradle.KotlinGradleModelBuilder
import org.jetbrains.kotlin.psi.UserDataProperty
import org.jetbrains.plugins.gradle.model.ExternalProject
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverUtil.getModuleId
var DataNode<ModuleData>.serializedCompilerArguments by UserDataProperty(Key.create<List<String>>("SERIALIZED_COMPILER_ARGUMENTS"))
class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() {
override fun getToolingExtensionsClasses(): Set<Class<out Any>> {
return setOf(KotlinGradleModelBuilder::class.java, Unit::class.java)
@@ -44,6 +48,7 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
ideModule: DataNode<ModuleData>,
ideProject: DataNode<ProjectData>) {
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)
}
@@ -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<String>, 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 = " ")
}
}