From c8d7c339cfe4a8006c8cb18231950e3471e845db Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 13 Apr 2017 19:39:16 +0300 Subject: [PATCH] Kapt3: Modify kapt incremental tests in order to support kapt3 --- .../jetbrains/kotlin/gradle/BaseGradleIT.kt | 38 ++++++++-- .../org/jetbrains/kotlin/gradle/Kapt3IT.kt | 4 ++ .../kotlin/gradle/KaptIncrementalIT.kt | 69 +++++++++++++++++-- .../build.gradle | 1 + .../GradleCompilerEnvironment.kt | 4 +- .../gradle/internal/KaptGenerateStubsTask.kt | 3 + 6 files changed, 107 insertions(+), 12 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt index d2a1da84161..7a6463856c5 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BaseGradleIT.kt @@ -153,7 +153,13 @@ abstract class BaseGradleIT { val javaSourcesListRegex = Regex("\\[DEBUG\\] \\[[^\\]]*JavaCompiler\\] Compiler arguments: ([^\\r\\n]*)") } - val compiledKotlinSources: Iterable by lazy { kotlinSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(", ").map { File(project.projectDir, it).canonicalFile } } } + private fun getCompiledFiles(regex: Regex, output: String) = regex.findAll(output) + .asIterable() + .flatMap { it.groups[1]!!.value.split(", ") + .map { File(project.projectDir, it).canonicalFile } } + + fun getCompiledKotlinSources(output: String) = getCompiledFiles(kotlinSourcesListRegex, output) + val compiledJavaSources: Iterable by lazy { javaSourcesListRegex.findAll(output).asIterable().flatMap { it.groups[1]!!.value.split(" ").filter { it.endsWith(".java", ignoreCase = true) }.map { File(it).canonicalFile } } } } @@ -304,11 +310,35 @@ abstract class BaseGradleIT { return this } - fun CompiledProject.assertCompiledKotlinSources(sources: Iterable, weakTesting: Boolean = false): CompiledProject = + fun CompiledProject.getOutputForTask(taskName: String): String { + fun String.substringAfter(delimiter: String, missingDelimiterValue: () -> String): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue() else substring(index + delimiter.length, length) + } + + fun String.substringBefore(delimiter: String, missingDelimiterValue: () -> String): String { + val index = indexOf(delimiter) + return if (index == -1) missingDelimiterValue() else substring(0, index) + } + + return output.substringAfter("[LIFECYCLE] [class org.gradle.TaskExecutionLogger] :$taskName") { error("Can't find start for task $taskName") } + .substringBefore("Finished executing task ':$taskName'") { error("Can't find completion for task $taskName") } + } + + fun CompiledProject.assertCompiledKotlinSources( + sources: Iterable, + weakTesting: Boolean = false, + tasks: List) { + for (task in tasks) { + assertCompiledKotlinSources(sources, weakTesting, getOutputForTask(task)) + } + } + + fun CompiledProject.assertCompiledKotlinSources(sources: Iterable, weakTesting: Boolean = false, output: String = this.output): CompiledProject = if (weakTesting) - assertContainFiles(sources, compiledKotlinSources.projectRelativePaths(this.project), "Compiled Kotlin files differ:\n ") + assertContainFiles(sources, getCompiledKotlinSources(output).projectRelativePaths(this.project), "Compiled Kotlin files differ:\n ") else - assertSameFiles(sources, compiledKotlinSources.projectRelativePaths(this.project), "Compiled Kotlin files differ:\n ") + assertSameFiles(sources, getCompiledKotlinSources(output).projectRelativePaths(this.project), "Compiled Kotlin files differ:\n ") fun CompiledProject.assertCompiledJavaSources(sources: Iterable, weakTesting: Boolean = false): CompiledProject = if (weakTesting) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt index 8051d39dafc..cdd9162a2ca 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/Kapt3IT.kt @@ -113,6 +113,8 @@ class Kapt3IT : BaseGradleIT() { project.build("build", options = options) { assertSuccessful() assertContains(":compileKotlin UP-TO-DATE") + assertContains(":kaptGenerateStubsKotlin UP-TO-DATE") + assertContains(":kaptKotlin UP-TO-DATE") assertFileExists("build/classes/main/example/TestClass.class") assertClassFilesNotContain(classesDir, "ExampleSourceAnnotation") } @@ -277,6 +279,7 @@ class Kapt3IT : BaseGradleIT() { project.build("classes", options = options) { assertSuccessful() + assertFileExists("build/generated/source/kapt/main/foo/InternalDummyGenerated.java") } // remove annotation @@ -286,6 +289,7 @@ class Kapt3IT : BaseGradleIT() { assertSuccessful() val allMainKotlinSrc = File(project.projectDir, "src/main").allKotlinFiles() assertCompiledKotlinSources(project.relativize(allMainKotlinSrc)) + assertNoSuchFile("build/generated/source/kapt/main/foo/InternalDummyGenerated.java") } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt index 3844de20f69..4c5e1bea2c9 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KaptIncrementalIT.kt @@ -9,19 +9,35 @@ import org.junit.Test class KaptIncrementalNoStubsIT : KaptIncrementalBaseIT(shouldUseStubs = false) class KaptIncrementalWithStubsIT : KaptIncrementalBaseIT(shouldUseStubs = true) -abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT() { +class Kapt3Incremental : KaptIncrementalBaseIT(shouldUseStubs = false, useKapt3 = true) + +abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean, val useKapt3: Boolean = false): BaseGradleIT() { + init { + if (useKapt3) { + assert(!shouldUseStubs) + } + } companion object { private const val GRADLE_VERSION = "2.10" private val EXAMPLE_ANNOTATION_REGEX = "@(field:)?example.ExampleAnnotation".toRegex() private const val GENERATE_STUBS_PLACEHOLDER = "GENERATE_STUBS_PLACEHOLDER" + + private const val APPLY_KAPT3_PLUGIN_PLACEHOLDER = "// APPLY_KAPT_PLUGIN" + private const val APPLY_KAPT3_PLUGIN = "apply plugin: \"kotlin-kapt\"" } + protected open val projectName = "kaptIncrementalCompilationProject" + private fun getProject() = - Project("kaptIncrementalCompilationProject", GRADLE_VERSION).apply { + Project(projectName, GRADLE_VERSION).apply { setupWorkingDir() val buildGradle = projectDir.parentFile.getFileByName("build.gradle") buildGradle.modify { it.replace(GENERATE_STUBS_PLACEHOLDER, shouldUseStubs.toString()) } + + if (useKapt3) { + buildGradle.modify { it.replace(APPLY_KAPT3_PLUGIN_PLACEHOLDER, APPLY_KAPT3_PLUGIN) } + } } private val annotatedElements = @@ -47,6 +63,11 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT( assertContains(":compileKotlin UP-TO-DATE", ":compileJava UP-TO-DATE") + if (useKapt3) { + assertContains(":kaptKotlin UP-TO-DATE", + ":kaptGenerateStubsKotlin UP-TO-DATE") + } + if (shouldUseStubs) { assertContains(":compileKotlinAfterJava UP-TO-DATE") } @@ -70,8 +91,10 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT( project.build("build") { assertSuccessful() + assertKapt3FullyExecuted() + // todo: for kapt with stubs check compileKotlin and compileKotlinAfterJava separately - assertCompiledKotlinSources(project.relativize(utilKt)) + assertCompiledKotlinSourcesHandleKapt3(project.relativize(utilKt)) checkGenerated(*(annotatedElements + arrayOf("newUtilFun"))) } } @@ -88,6 +111,7 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT( project.build("build") { assertSuccessful() + assertKapt3FullyExecuted() assertCompiledKotlinSources(project.relativize(utilKt)) checkGenerated(*(annotatedElements + arrayOf("notAnnotatedFun"))) } @@ -113,7 +137,8 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT( project.build("build") { assertSuccessful() - assertCompiledKotlinSources(project.relativize(project.projectDir.allKotlinFiles())) + assertKapt3FullyExecuted() + assertCompiledKotlinSourcesHandleKapt3(project.relativize(project.projectDir.allKotlinFiles())) val affectedElements = arrayOf("B", "funB", "valB", "useB") checkGenerated(*(annotatedElements.toSet() - affectedElements).toTypedArray()) checkNotGenerated(*affectedElements) @@ -133,7 +158,19 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT( project.build("build") { assertSuccessful() - if (shouldUseStubs) { + + if (useKapt3) { + assertKapt3FullyExecuted() + + val useBKt = project.projectDir.getFileByName("useB.kt") + assertCompiledKotlinSources(project.relativize(bKt, useBKt), + output = getOutputForTask("kaptGenerateStubsKotlin")) + + // java removal is detected + assertCompiledKotlinSources(project.relativize(project.projectDir.allKotlinFiles()), + output = getOutputForTask("compileKotlin")) + } + else if (shouldUseStubs) { // java removal is detected assertCompiledKotlinSources(project.relativize(project.projectDir.allKotlinFiles())) } @@ -159,11 +196,31 @@ abstract class KaptIncrementalBaseIT(val shouldUseStubs: Boolean): BaseGradleIT( project.build("build") { assertSuccessful() - assertCompiledKotlinSources(project.relativize(bKt, useBKt)) + assertKapt3FullyExecuted() + assertCompiledKotlinSourcesHandleKapt3(project.relativize(bKt, useBKt)) checkGenerated(*annotatedElements) } } + private fun CompiledProject.assertCompiledKotlinSourcesHandleKapt3( + sources: Iterable, + weakTesting: Boolean = false + ) { + if (useKapt3) { + assertCompiledKotlinSources(sources, weakTesting, + tasks = listOf("compileKotlin", "kaptGenerateStubsKotlin")) + } else { + assertCompiledKotlinSources(sources, weakTesting) + } + } + + private fun CompiledProject.assertKapt3FullyExecuted() { + if (useKapt3) { + assertNotContains(":kaptKotlin UP-TO-DATE", + ":kaptGenerateStubsKotlin UP-TO-DATE") + } + } + private fun CompiledProject.checkGenerated(vararg annotatedElementNames: String) { getGeneratedFileNames(*annotatedElementNames).forEach { val file = project.projectDir.getFileByName(it) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kaptIncrementalCompilationProject/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kaptIncrementalCompilationProject/build.gradle index 99369092cbc..4575bf15572 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kaptIncrementalCompilationProject/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kaptIncrementalCompilationProject/build.gradle @@ -9,6 +9,7 @@ buildscript { apply plugin: "java" apply plugin: "kotlin" +// APPLY_KAPT_PLUGIN repositories { mavenLocal() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt index f943bc52dc3..9e6d4766b97 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleCompilerEnvironment.kt @@ -7,7 +7,7 @@ import org.jetbrains.kotlin.config.Services import org.jetbrains.kotlin.gradle.tasks.GradleMessageCollector import org.jetbrains.kotlin.gradle.tasks.findToolsJar import org.jetbrains.kotlin.incremental.ChangedFiles -import org.jetbrains.kotlin.incremental.GradleICReporter +import org.jetbrains.kotlin.incremental.ICReporter import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider import java.io.File import java.net.URL @@ -30,7 +30,7 @@ internal open class GradleCompilerEnvironment( internal class GradleIncrementalCompilerEnvironment( compilerJar: File, val changedFiles: ChangedFiles, - val reporter: GradleICReporter, + val reporter: ICReporter, val workingDir: File, messageCollector: GradleMessageCollector, outputItemsCollector: OutputItemsCollector, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt index 3fbb1d5790c..27d904ac49c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptGenerateStubsTask.kt @@ -18,11 +18,14 @@ package org.jetbrains.kotlin.gradle.internal import org.gradle.api.tasks.SourceTask import org.gradle.api.tasks.incremental.IncrementalTaskInputs +import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.incremental.ChangedFiles +import org.jetbrains.kotlin.incremental.GradleICReporter +import org.jetbrains.kotlin.incremental.ICReporter import org.jetbrains.kotlin.incremental.pathsAsStringRelativeTo import java.io.File