From 5f593ac3f85c1c2b3756406e390d87a2a8f742c0 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Thu, 7 Sep 2017 14:31:47 +0300 Subject: [PATCH] Add @Input to compiler args and compiler JAR. Add up-to-date-ness tests. Issue #KT-20036 Fixed Issue #KT-3463 Fixed Issue #KT-16299 Fixed Issue #KT-16915 Fixed (cherry picked from commit e6d867f) --- .../jetbrains/kotlin/gradle/UpToDatenessIT.kt | 144 ++++++++++++++++++ .../jetbrains/kotlin/gradle/tasks/Tasks.kt | 4 + 2 files changed, 148 insertions(+) create mode 100644 libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDatenessIT.kt diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDatenessIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDatenessIT.kt new file mode 100644 index 00000000000..1afeca3faab --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/UpToDatenessIT.kt @@ -0,0 +1,144 @@ +package org.jetbrains.kotlin.gradle + +import org.jetbrains.kotlin.gradle.util.modify +import org.junit.Assert +import org.junit.Assume +import org.junit.Test +import java.io.File + +class UpToDateIT : BaseGradleIT() { + @Test + fun testNoMutation() = testWithMutation(object : ProjectMutation { + override fun initProject(project: Project) = Unit + override fun mutateProject(project: Project) = Unit + + override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { + assertTasksUpToDate(listOf(":compileKotlin")) + } + }) + + @Test + fun testJvmTargetMutation() = testWithMutation(optionMutation( + "compileKotlin.kotlinOptions.jvmTarget", "'1.6'", "'1.8'", + shouldOutdateCompileKotlin = true)) + + @Test + fun testFreeCompilerArgsMutation() = testWithMutation(optionMutation( + "compileKotlin.kotlinOptions.freeCompilerArgs", "[]", "['-Xallow-kotlin-package']", + shouldOutdateCompileKotlin = true)) + + @Test + fun testCoroutinesMutation() = testWithMutation(optionMutation( + "kotlin.experimental.coroutines", "'error'", "'enable'", + shouldOutdateCompileKotlin = true)) + + @Test + fun testArchivesBaseNameMutation() = testWithMutation(optionMutation( + "archivesBaseName", "'someName'", "'otherName'", + shouldOutdateCompileKotlin = true)) + + @Test + fun testSubpluginOptionsMutation() = testWithMutation(object : ProjectMutation { + override fun initProject(project: Project) = with(project) { + buildGradle.appendText("""${'\n'} + buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-allopen:${'$'}kotlin_version" } } + apply plugin: "kotlin-allopen" + allOpen { annotation("com.my.Annotation") } + """.trimIndent()) + } + + override fun mutateProject(project: Project) = with(project) { + buildGradle.modify { it.replace("com.my.Annotation", "com.my.AnotherAnnotation") } + } + + override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { + assertTasksExecuted(listOf(":compileKotlin")) + } + }) + + @Test + fun testCompilerJarMutation() = testWithMutation(object : ProjectMutation { + lateinit var originalCompilerJar: File + val originalPath get() = originalCompilerJar.absolutePath.replace("\\", "/") + + override fun initProject(project: Project) = with(project) { + buildGradle.appendText("\nprintln 'compiler_jar=' + compileKotlin.getCompilerJar\$kotlin_gradle_plugin()") + build("clean") { originalCompilerJar = File("compiler_jar=(.*)".toRegex().find(output)!!.groupValues[1]) } + buildGradle.appendText("\ncompileKotlin.compilerJarFile = file('$originalPath')") + } + + override fun mutateProject(project: Project) = with(project) { + val localCompilerJar = originalCompilerJar.copyTo(File(projectDir, "compiler.jar")) + buildGradle.modify { + it.replace("file('${originalPath}')", "file('${localCompilerJar.absolutePath.replace('\\', '/')}')") + } + } + + override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { + assertTasksExecuted(listOf(":compileKotlin")) + } + }) + + @Test + fun testExternalOutputMutation() = testWithMutation(object : ProjectMutation { + override fun initProject(project: Project) = Unit + + lateinit var helloWorldKtClass: File + + override fun mutateProject(project: Project) = with(project) { + helloWorldKtClass = File(projectDir, "build/classes/kotlin/main/demo/KotlinGreetingJoiner.class") + Assume.assumeTrue(helloWorldKtClass.exists()) + helloWorldKtClass.delete(); Unit + } + + override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { + assertTasksExecuted(listOf(":compileKotlin")) + Assert.assertTrue(helloWorldKtClass.exists()) + } + }) + + private fun testWithMutation(projectMutation: ProjectMutation) { + val project = Project("simpleProject", "4.1") + project.projectDir.run { if (exists()) deleteRecursively() } + project.setupWorkingDir() + projectMutation.initProject(project) + project.build("build") { assertSuccessful() } + projectMutation.mutateProject(project) + project.build("build") { + assertSuccessful() + projectMutation.checkAfterRebuild(this) + } + } + + private val BaseGradleIT.Project.buildGradle get() = File(projectDir, "build.gradle") + + private interface ProjectMutation { + fun initProject(project: Project) + fun mutateProject(project: Project) + fun checkAfterRebuild(compiledProject: CompiledProject) + } + + private fun optionMutation( + path: String, + oldValue: String, + newValue: String, + shouldOutdateCompileKotlin: Boolean + ) = object : ProjectMutation { + override fun initProject(project: Project) = with(project) { + buildGradle.appendText("\n$path = $oldValue") + } + + override fun mutateProject(project: Project) = with(project) { + buildGradle.modify { it.replace("$path = $oldValue", "$path = $newValue") } + } + + override fun checkAfterRebuild(compiledProject: CompiledProject) = with(compiledProject) { + if (shouldOutdateCompileKotlin) { + assertTasksExecuted(listOf(":compileKotlin")) + } + else { + assertTasksUpToDate(listOf(":compileKotlin")) + } + } + } +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 8d148fd34b3..58ccae39078 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -22,6 +22,7 @@ import org.gradle.api.file.SourceDirectorySet import org.gradle.api.logging.Logger import org.gradle.api.plugins.BasePluginConvention import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.SourceTask import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.compile.AbstractCompile @@ -59,6 +60,7 @@ abstract class AbstractKotlinCompileTool() : AbstractCo var compilerJarFile: File? = null var compilerClasspath: List? = null + @get:InputFiles internal val computedCompilerClasspath: List get() = compilerClasspath?.takeIf { it.isNotEmpty() } ?: compilerJarFile?.let { @@ -67,6 +69,7 @@ abstract class AbstractKotlinCompileTool() : AbstractCo } ?: findKotlinCompilerClasspath(project).takeIf { it.isNotEmpty() } ?: throw IllegalStateException("Could not find Kotlin Compiler classpath. Please specify $name.compilerClasspath") + protected abstract fun findKotlinCompilerClasspath(project: Project): List } @@ -105,6 +108,7 @@ abstract class AbstractKotlinCompile() : AbstractKo get() = (classpath + additionalClasspath) .filterTo(LinkedHashSet(), File::exists) + @get:Input override val serializedCompilerArguments: List get() { val arguments = createCompilerArgs()