Kotlin Facet: Distinguish compiler arguments specified for different source sets
#KT-16698 Fixed
This commit is contained in:
@@ -17,29 +17,35 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
|
||||
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
|
||||
import java.io.Serializable
|
||||
import java.lang.Exception
|
||||
import java.lang.reflect.InvocationTargetException
|
||||
import java.lang.reflect.Method
|
||||
|
||||
typealias CompilerArgumentsBySourceSet = Map<String, List<String>>
|
||||
|
||||
interface KotlinGradleModel : Serializable {
|
||||
val implements: String?
|
||||
val currentCompilerArguments: List<String>?
|
||||
val defaultCompilerArguments: List<String>?
|
||||
val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet
|
||||
val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet
|
||||
val coroutines: String?
|
||||
}
|
||||
|
||||
class KotlinGradleModelImpl(
|
||||
override val implements: String?,
|
||||
override val currentCompilerArguments: List<String>?,
|
||||
override val defaultCompilerArguments: List<String>?,
|
||||
override val currentCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet,
|
||||
override val defaultCompilerArgumentsBySourceSet: CompilerArgumentsBySourceSet,
|
||||
override val coroutines: String?
|
||||
) : KotlinGradleModel
|
||||
|
||||
class KotlinGradleModelBuilder : ModelBuilderService {
|
||||
companion object {
|
||||
val compileTasks = listOf("compileKotlin", "compileKotlin2Js")
|
||||
val kotlinCompileTaskClasses = listOf("org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated",
|
||||
"org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile_Decorated")
|
||||
}
|
||||
|
||||
override fun getErrorMessageBuilder(project: Project, e: Exception): ErrorMessageBuilder {
|
||||
@@ -57,15 +63,35 @@ class KotlinGradleModelBuilder : ModelBuilderService {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun Class<*>.findGetterMethod(name: String): Method? {
|
||||
generateSequence(this) { it.superclass }.forEach {
|
||||
try {
|
||||
return it.getDeclaredMethod(name)
|
||||
}
|
||||
catch(e: Exception) {
|
||||
// Check next super class
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun getCompilerArguments(project: Project, methodName: String): List<String>? {
|
||||
val compileTask = compileTasks.mapNotNull { project.getTasksByName(it, false).firstOrNull() }.firstOrNull() ?: return null
|
||||
private fun collectCompilerArguments(
|
||||
compileTask: Task,
|
||||
methodName: String,
|
||||
argumentsBySourceSet: MutableMap<String, List<String>>
|
||||
) {
|
||||
val taskClass = compileTask.javaClass
|
||||
return try {
|
||||
taskClass.getDeclaredMethod(methodName).invoke(compileTask) as List<String>
|
||||
val sourceSetName = try {
|
||||
taskClass.findGetterMethod("getSourceSetName\$kotlin_gradle_plugin")?.invoke(compileTask) as? String
|
||||
} catch (e : InvocationTargetException) {
|
||||
null // can be thrown if property is not initialized yet
|
||||
} ?: "main"
|
||||
try {
|
||||
argumentsBySourceSet[sourceSetName] = taskClass.getDeclaredMethod(methodName).invoke(compileTask) as List<String>
|
||||
}
|
||||
catch (e : NoSuchMethodException) {
|
||||
null
|
||||
// No argument accessor method is available
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +112,22 @@ class KotlinGradleModelBuilder : ModelBuilderService {
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildAll(modelName: String?, project: Project) =
|
||||
KotlinGradleModelImpl(
|
||||
getImplements(project),
|
||||
getCompilerArguments(project, "getSerializedCompilerArguments"),
|
||||
getCompilerArguments(project, "getDefaultSerializedCompilerArguments"),
|
||||
getCoroutines(project)
|
||||
)
|
||||
override fun buildAll(modelName: String?, project: Project): KotlinGradleModelImpl {
|
||||
val currentCompilerArgumentsBySourceSet = LinkedHashMap<String, List<String>>()
|
||||
val defaultCompilerArgumentsBySourceSet = LinkedHashMap<String, List<String>>()
|
||||
|
||||
project.getAllTasks(false)[project]?.forEach { compileTask ->
|
||||
if (compileTask.javaClass.name !in kotlinCompileTaskClasses) return@forEach
|
||||
|
||||
collectCompilerArguments(compileTask, "getSerializedCompilerArguments", currentCompilerArgumentsBySourceSet)
|
||||
collectCompilerArguments(compileTask, "getDefaultSerializedCompilerArguments", defaultCompilerArgumentsBySourceSet)
|
||||
}
|
||||
|
||||
return KotlinGradleModelImpl(
|
||||
getImplements(project),
|
||||
currentCompilerArgumentsBySourceSet,
|
||||
defaultCompilerArgumentsBySourceSet,
|
||||
getCoroutines(project)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-5
@@ -25,6 +25,7 @@ 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.CompilerArgumentsBySourceSet
|
||||
import org.jetbrains.kotlin.gradle.KotlinGradleModel
|
||||
import org.jetbrains.kotlin.gradle.KotlinGradleModelBuilder
|
||||
import org.jetbrains.kotlin.psi.UserDataProperty
|
||||
@@ -33,9 +34,12 @@ 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>.currentCompilerArguments by UserDataProperty(Key.create<List<String>>("CURRENT_COMPILER_ARGUMENTS"))
|
||||
var DataNode<ModuleData>.defaultCompilerArguments by UserDataProperty(Key.create<List<String>>("DEFAULT_COMPILER_ARGUMENTS"))
|
||||
var DataNode<ModuleData>.coroutines by UserDataProperty(Key.create<String>("KOTLIN_COROUTINES"))
|
||||
var DataNode<ModuleData>.currentCompilerArgumentsBySourceSet
|
||||
by UserDataProperty(Key.create<CompilerArgumentsBySourceSet>("CURRENT_COMPILER_ARGUMENTS"))
|
||||
var DataNode<ModuleData>.defaultCompilerArgumentsBySourceSet
|
||||
by UserDataProperty(Key.create<CompilerArgumentsBySourceSet>("DEFAULT_COMPILER_ARGUMENTS"))
|
||||
var DataNode<ModuleData>.coroutines
|
||||
by UserDataProperty(Key.create<String>("KOTLIN_COROUTINES"))
|
||||
|
||||
class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension() {
|
||||
override fun getToolingExtensionsClasses(): Set<Class<out Any>> {
|
||||
@@ -61,8 +65,8 @@ class KotlinGradleProjectResolverExtension : AbstractProjectResolverExtension()
|
||||
}
|
||||
}
|
||||
|
||||
ideModule.currentCompilerArguments = gradleModel.currentCompilerArguments
|
||||
ideModule.defaultCompilerArguments = gradleModel.defaultCompilerArguments
|
||||
ideModule.currentCompilerArgumentsBySourceSet = gradleModel.currentCompilerArgumentsBySourceSet
|
||||
ideModule.defaultCompilerArgumentsBySourceSet = gradleModel.defaultCompilerArgumentsBySourceSet
|
||||
ideModule.coroutines = gradleModel.coroutines
|
||||
|
||||
super.populateModuleDependencies(gradleModule, ideModule, ideProject)
|
||||
|
||||
+7
-4
@@ -62,7 +62,7 @@ class KotlinGradleSourceSetDataService : AbstractProjectDataService<GradleSource
|
||||
val ideModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
|
||||
|
||||
val moduleNode = ExternalSystemApiUtil.findParent(sourceSetNode, ProjectKeys.MODULE) ?: continue
|
||||
val kotlinFacet = configureFacetByGradleModule(moduleNode, ideModule, modelsProvider) ?: continue
|
||||
val kotlinFacet = configureFacetByGradleModule(moduleNode, sourceSetNode, ideModule, modelsProvider) ?: continue
|
||||
GradleProjectImportHandler.getInstances(project).forEach { it.importBySourceSet(kotlinFacet, sourceSetNode) }
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,7 @@ class KotlinGradleProjectDataService : AbstractProjectDataService<ModuleData, Vo
|
||||
|
||||
val moduleData = moduleNode.data
|
||||
val ideModule = modelsProvider.findIdeModule(moduleData) ?: continue
|
||||
val kotlinFacet = configureFacetByGradleModule(moduleNode, ideModule, modelsProvider) ?: continue
|
||||
val kotlinFacet = configureFacetByGradleModule(moduleNode, null, ideModule, modelsProvider) ?: continue
|
||||
GradleProjectImportHandler.getInstances(project).forEach { it.importByModule(kotlinFacet, moduleNode) }
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,7 @@ private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPla
|
||||
|
||||
private fun configureFacetByGradleModule(
|
||||
moduleNode: DataNode<ModuleData>,
|
||||
sourceSetNode: DataNode<GradleSourceSetData>?,
|
||||
ideModule: Module,
|
||||
modelsProvider: IdeModifiableModelsProvider
|
||||
): KotlinFacet? {
|
||||
@@ -121,8 +122,10 @@ private fun configureFacetByGradleModule(
|
||||
val kotlinFacet = ideModule.getOrCreateFacet(modelsProvider, false)
|
||||
kotlinFacet.configureFacet(compilerVersion, coroutinesProperty, platformKind, modelsProvider)
|
||||
|
||||
val currentCompilerArguments = moduleNode.currentCompilerArguments
|
||||
val defaultCompilerArguments = moduleNode.defaultCompilerArguments ?: emptyList()
|
||||
val sourceSetName = sourceSetNode?.data?.id?.let { it.substring(it.lastIndexOf(':') + 1) } ?: "main"
|
||||
|
||||
val currentCompilerArguments = moduleNode.currentCompilerArgumentsBySourceSet?.get(sourceSetName)
|
||||
val defaultCompilerArguments = moduleNode.defaultCompilerArgumentsBySourceSet?.get(sourceSetName) ?: emptyList()
|
||||
if (currentCompilerArguments != null) {
|
||||
parseCompilerArgumentsToFacet(currentCompilerArguments, defaultCompilerArguments, kotlinFacet)
|
||||
}
|
||||
|
||||
@@ -27,8 +27,13 @@ import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
class GradleFacetImportTest : GradleImportingTestCase() {
|
||||
private fun facetSettings(moduleName: String) = KotlinFacet.get(getModule(moduleName))!!.configuration.settings
|
||||
|
||||
private val facetSettings: KotlinFacetSettings
|
||||
get() = KotlinFacet.get(getModule("project_main"))!!.configuration.settings
|
||||
get() = facetSettings("project_main")
|
||||
|
||||
private val testFacetSettings: KotlinFacetSettings
|
||||
get() = facetSettings("project_test")
|
||||
|
||||
@Test
|
||||
fun testJvmImport() {
|
||||
@@ -59,6 +64,12 @@ class GradleFacetImportTest : GradleImportingTestCase() {
|
||||
kotlinOptions.jvmTarget = "1.7"
|
||||
kotlinOptions.freeCompilerArgs = ["-Xsingle-module", "-Xdump-declarations-to", "tmp"]
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions.jvmTarget = "1.6"
|
||||
kotlinOptions.apiVersion = "1.0"
|
||||
kotlinOptions.freeCompilerArgs = ["-Xdump-declarations-to", "tmpTest"]
|
||||
}
|
||||
""")
|
||||
importProject()
|
||||
|
||||
@@ -70,6 +81,83 @@ class GradleFacetImportTest : GradleImportingTestCase() {
|
||||
Assert.assertEquals("-Xdump-declarations-to tmp -Xsingle-module",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
with (testFacetSettings) {
|
||||
Assert.assertEquals("1.1", languageLevel!!.versionString)
|
||||
Assert.assertEquals("1.0", apiLevel!!.versionString)
|
||||
Assert.assertEquals(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6], targetPlatformKind)
|
||||
Assert.assertEquals("1.6", (compilerArguments as K2JVMCompilerArguments).jvmTarget)
|
||||
Assert.assertEquals("-Xdump-declarations-to tmpTest",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJvmImportWithCustomSourceSets() {
|
||||
createProjectSubFile("build.gradle", """
|
||||
group 'Again'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
sourceSets {
|
||||
myMain {
|
||||
kotlin {
|
||||
srcDir 'src'
|
||||
}
|
||||
}
|
||||
myTest {
|
||||
kotlin {
|
||||
srcDir 'test'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:1.1.0"
|
||||
}
|
||||
|
||||
compileMyMainKotlin {
|
||||
kotlinOptions.jvmTarget = "1.7"
|
||||
kotlinOptions.freeCompilerArgs = ["-Xsingle-module", "-Xdump-declarations-to", "tmp"]
|
||||
}
|
||||
|
||||
compileMyTestKotlin {
|
||||
kotlinOptions.jvmTarget = "1.6"
|
||||
kotlinOptions.apiVersion = "1.0"
|
||||
kotlinOptions.freeCompilerArgs = ["-Xdump-declarations-to", "tmpTest"]
|
||||
}
|
||||
""")
|
||||
importProject()
|
||||
|
||||
with (facetSettings("project_myMain")) {
|
||||
Assert.assertEquals("1.1", languageLevel!!.versionString)
|
||||
Assert.assertEquals("1.1", apiLevel!!.versionString)
|
||||
Assert.assertEquals(TargetPlatformKind.Jvm[JvmTarget.JVM_1_8], targetPlatformKind)
|
||||
Assert.assertEquals("1.7", (compilerArguments as K2JVMCompilerArguments).jvmTarget)
|
||||
Assert.assertEquals("-Xdump-declarations-to tmp -Xsingle-module",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
with (facetSettings("project_myTest")) {
|
||||
Assert.assertEquals("1.1", languageLevel!!.versionString)
|
||||
Assert.assertEquals("1.0", apiLevel!!.versionString)
|
||||
Assert.assertEquals(TargetPlatformKind.Jvm[JvmTarget.JVM_1_6], targetPlatformKind)
|
||||
Assert.assertEquals("1.6", (compilerArguments as K2JVMCompilerArguments).jvmTarget)
|
||||
Assert.assertEquals("-Xdump-declarations-to tmpTest",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -218,7 +306,12 @@ class GradleFacetImportTest : GradleImportingTestCase() {
|
||||
|
||||
compileKotlin2Js {
|
||||
kotlinOptions.sourceMap = true
|
||||
kotlinOptions.freeCompilerArgs = ["-module-kind", "plain"]
|
||||
kotlinOptions.freeCompilerArgs = ["-module-kind", "plain", "-main", "callMain"]
|
||||
}
|
||||
|
||||
compileTestKotlin2Js {
|
||||
kotlinOptions.apiVersion = "1.0"
|
||||
kotlinOptions.freeCompilerArgs = ["-module-kind", "umd", "-main", "callTest"]
|
||||
}
|
||||
""")
|
||||
importProject()
|
||||
@@ -231,7 +324,94 @@ class GradleFacetImportTest : GradleImportingTestCase() {
|
||||
Assert.assertEquals(true, sourceMap)
|
||||
Assert.assertEquals("plain", moduleKind)
|
||||
}
|
||||
Assert.assertEquals("-version",
|
||||
Assert.assertEquals("-main callMain",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
|
||||
with (testFacetSettings) {
|
||||
Assert.assertEquals("1.1", languageLevel!!.versionString)
|
||||
Assert.assertEquals("1.0", apiLevel!!.versionString)
|
||||
Assert.assertEquals(TargetPlatformKind.JavaScript, targetPlatformKind)
|
||||
with(compilerArguments as K2JSCompilerArguments) {
|
||||
Assert.assertEquals(false, sourceMap)
|
||||
Assert.assertEquals("umd", moduleKind)
|
||||
}
|
||||
Assert.assertEquals("-main callTest",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJsImportWithCustomSourceSets() {
|
||||
createProjectSubFile("build.gradle", """
|
||||
group 'Again'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven {
|
||||
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin2js'
|
||||
|
||||
sourceSets {
|
||||
myMain {
|
||||
kotlin {
|
||||
srcDir 'src'
|
||||
}
|
||||
}
|
||||
myTest {
|
||||
kotlin {
|
||||
srcDir 'test'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.0"
|
||||
}
|
||||
|
||||
compileMyMainKotlin2Js {
|
||||
kotlinOptions.sourceMap = true
|
||||
kotlinOptions.freeCompilerArgs = ["-module-kind", "plain", "-main", "callMain"]
|
||||
}
|
||||
|
||||
compileMyTestKotlin2Js {
|
||||
kotlinOptions.apiVersion = "1.0"
|
||||
kotlinOptions.freeCompilerArgs = ["-module-kind", "umd", "-main", "callTest"]
|
||||
}
|
||||
""")
|
||||
importProject()
|
||||
|
||||
with (facetSettings("project_myMain")) {
|
||||
Assert.assertEquals("1.1", languageLevel!!.versionString)
|
||||
Assert.assertEquals("1.1", apiLevel!!.versionString)
|
||||
Assert.assertEquals(TargetPlatformKind.JavaScript, targetPlatformKind)
|
||||
with(compilerArguments as K2JSCompilerArguments) {
|
||||
Assert.assertEquals(true, sourceMap)
|
||||
Assert.assertEquals("plain", moduleKind)
|
||||
}
|
||||
Assert.assertEquals("-main callMain",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
|
||||
with (facetSettings("project_myTest")) {
|
||||
Assert.assertEquals("1.1", languageLevel!!.versionString)
|
||||
Assert.assertEquals("1.0", apiLevel!!.versionString)
|
||||
Assert.assertEquals(TargetPlatformKind.JavaScript, targetPlatformKind)
|
||||
with(compilerArguments as K2JSCompilerArguments) {
|
||||
Assert.assertEquals(false, sourceMap)
|
||||
Assert.assertEquals("umd", moduleKind)
|
||||
}
|
||||
Assert.assertEquals("-main callTest",
|
||||
compilerSettings!!.additionalArguments)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user