Propagate the subplugin options from the tasks to the source sets

If a source set is used in only one compilation, take the options from
its compile task.

If a source set is used by multiple compilations of a single target,
either choose the 'main' compilation or choose any (this will happen
for Android, and it looks OK for the first time). If there are multiple
compilations of different targets, use the metadata compilation.

Issue #KT-27499 In Progress
This commit is contained in:
Sergey Igushkin
2018-10-15 21:47:18 +03:00
parent e573911e16
commit 9f2e5cdc4d
5 changed files with 204 additions and 8 deletions
@@ -8,6 +8,8 @@ import org.jetbrains.kotlin.gradle.util.modify
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class KotlinAndroidGradleIT : AbstractKotlinAndroidGradleTests(androidGradlePluginVersion = "2.3.0") {
@@ -22,7 +24,7 @@ class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT(androidGradlePluginVersio
@Test
fun testAndroidWithNewMppApp() = with(Project("new-mpp-android")) {
build("assemble", "compileDebugUnitTestJavaWithJavac") {
build("assemble", "compileDebugUnitTestJavaWithJavac", "printCompilerPluginOptions") {
assertSuccessful()
assertTasksExecuted(
@@ -48,6 +50,25 @@ class KotlinAndroid32GradleIT : KotlinAndroid3GradleIT(androidGradlePluginVersio
assertFileExists("app/build/tmp/kotlin-classes/$variant/com/example/app/AKt.class")
assertFileExists("app/build/tmp/kotlin-classes/$variant/com/example/app/KtUsageKt.class")
}
// Check that Android extensions arguments are available only in the Android source sets:
val compilerPluginArgsRegex = "(\\w+)${Regex.escape("=args=>")}(.*)".toRegex()
val compilerPluginOptionsBySourceSet =
compilerPluginArgsRegex.findAll(output).associate { it.groupValues[1] to it.groupValues[2] }
compilerPluginOptionsBySourceSet.entries.forEach { (sourceSetName, argsString) ->
val shouldHaveAndroidExtensionArgs = sourceSetName.startsWith("androidApp")
if (shouldHaveAndroidExtensionArgs)
assertTrue("$sourceSetName is an Android source set and should have Android Extensions in the args") {
"plugin:org.jetbrains.kotlin.android" in argsString
}
else
assertEquals(
"[]",
argsString,
"$sourceSetName is not an Android source set and should not have Android Extensions in the args"
)
}
}
}
@@ -928,6 +928,94 @@ class NewMultiplatformIT : BaseGradleIT() {
}
}
@Test
fun testMppBuildWithCompilerPlugins() = with(Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")) {
setupWorkingDir()
val printOptionsTaskName = "printCompilerPluginOptions"
val argsMarker = "=args=>"
val classpathMarker = "=cp=>"
val compilerPluginArgsRegex = "(\\w+)${Regex.escape(argsMarker)}(.*)".toRegex()
val compilerPluginClasspathRegex = "(\\w+)${Regex.escape(classpathMarker)}(.*)".toRegex()
gradleBuildScript().appendText(
"\n" + """
buildscript {
dependencies {
classpath "org.jetbrains.kotlin:kotlin-allopen:${'$'}kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-noarg:${'$'}kotlin_version"
}
}
apply plugin: 'kotlin-allopen'
apply plugin: 'kotlin-noarg'
allOpen { annotation 'com.example.Annotation' }
noArg { annotation 'com.example.Annotation' }
task $printOptionsTaskName {
doFirst {
kotlin.sourceSets.each { sourceSet ->
def args = sourceSet.languageSettings.compilerPluginArguments
def cp = sourceSet.languageSettings.compilerPluginClasspath.files
println sourceSet.name + '$argsMarker' + args
println sourceSet.name + '$classpathMarker' + cp
}
}
}
""".trimIndent()
)
projectDir.resolve("src/commonMain/kotlin/Annotation.kt").writeText(
"""
package com.example
annotation class Annotation
""".trimIndent()
)
projectDir.resolve("src/commonMain/kotlin/Annotated.kt").writeText(
"""
package com.example
@Annotation
open class Annotated(var y: Int) { var x = 2 }
""".trimIndent()
)
// TODO once Kotlin/Native properly supports compiler plugins, move this class to the common sources
listOf("jvm6", "nodeJs").forEach {
projectDir.resolve("src/${it}Main/kotlin/Override.kt").writeText(
"""
package com.example
@Annotation
class Override : Annotated(0) {
override var x = 3
}
""".trimIndent()
)
}
build("assemble", printOptionsTaskName) {
assertSuccessful()
assertTasksExecuted(*listOf("Jvm6", "NodeJs", nativeHostTargetName.capitalize()).map { ":compileKotlin$it" }.toTypedArray())
assertFileExists("build/classes/kotlin/jvm6/main/com/example/Annotated.class")
assertFileExists("build/classes/kotlin/jvm6/main/com/example/Override.class")
assertFileContains("build/classes/kotlin/nodeJs/main/sample-lib.js", "Override")
val (compilerPluginArgsBySourceSet, compilerPluginClasspathBySourceSet) =
listOf(compilerPluginArgsRegex, compilerPluginClasspathRegex)
.map { marker ->
marker.findAll(output).associate { it.groupValues[1] to it.groupValues[2] }
}
// TODO once Kotlin/Native properly supports compiler plugins, expand this to all source sets:
listOf("commonMain", "commonTest", "jvm6Main", "jvm6Test", "nodeJsMain", "nodeJsTest").forEach {
val expectedArgs = "[plugin:org.jetbrains.kotlin.allopen:annotation=com.example.Annotation, " +
"plugin:org.jetbrains.kotlin.noarg:annotation=com.example.Annotation]"
assertEquals(expectedArgs, compilerPluginArgsBySourceSet[it], "Expected $expectedArgs as plugin args for $it")
assertTrue { compilerPluginClasspathBySourceSet[it]!!.contains("kotlin-allopen") }
assertTrue { compilerPluginClasspathBySourceSet[it]!!.contains("kotlin-noarg") }
}
}
}
@Test
fun testJsDceInMpp() = with(Project("new-mpp-js-dce", gradleVersion)) {
build("runRhino") {
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-multiplatform'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 27
@@ -55,4 +56,16 @@ kotlin {
fromPreset(presets.jvm, 'jvmApp')
fromPreset(presets.js, 'jsApp')
}
}
// test diagnostic task, not needed by the build
task printCompilerPluginOptions {
doFirst {
kotlin.sourceSets.each { sourceSet ->
def args = sourceSet.languageSettings.compilerPluginArguments
def cp = sourceSet.languageSettings.compilerPluginClasspath.files
println sourceSet.name + '=args=>' + args
println sourceSet.name + '=cp=>' + cp
}
}
}