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 f724b1d9389..29ba2707a8f 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 @@ -270,4 +270,26 @@ class Kapt3IT : BaseGradleIT() { assertCompiledKotlinSources(project.relativize(allMainKotlinSrc)) } } + + @Test + fun testKaptClassesDirSync() { + val project = Project("autoService", GRADLE_VERSION, directoryPrefix = "kapt2") + + project.build("build") { + assertSuccessful() + assertKaptSuccessful() + assertFileExists("processor/build/classes/main/META-INF/services/javax.annotation.processing.Processor") + assertFileExists("processor/build/classes/main/processor/MyProcessor.class") + } + + project.projectDir.getFileByName("MyProcessor.kt").modify { + it.replace("@AutoService(Processor::class)", "") + } + + project.build(":processor:build") { + assertSuccessful() + assertNoSuchFile("processor/build/classes/main/META-INF/services/javax.annotation.processing.Processor") + assertFileExists("processor/build/classes/main/processor/MyProcessor.class") + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/build.gradle new file mode 100644 index 00000000000..da590eadb56 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/build.gradle @@ -0,0 +1,25 @@ +buildscript { + repositories { + mavenLocal() + mavenCentral() + } + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin' + +allprojects { + repositories { + mavenLocal() + mavenCentral() + } +} + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile project(":processor") + kapt project(":processor") +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/processor/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/processor/build.gradle new file mode 100644 index 00000000000..5edd5035436 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/processor/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin' + +dependencies { + ext.autoServiceVersion = '1.0-rc2' + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile "com.google.auto.service:auto-service:$autoServiceVersion" + kapt "com.google.auto.service:auto-service:$autoServiceVersion" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/processor/src/main/kotlin/processor/MyProcessor.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/processor/src/main/kotlin/processor/MyProcessor.kt new file mode 100644 index 00000000000..48d7f8bd669 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/processor/src/main/kotlin/processor/MyProcessor.kt @@ -0,0 +1,28 @@ +package processor + +import com.google.auto.service.AutoService +import javax.annotation.processing.* +import javax.lang.model.SourceVersion +import javax.lang.model.element.TypeElement +import javax.tools.Diagnostic + +@AutoService(Processor::class) +@SupportedAnnotationTypes("annotation.ProcessThis") +@SupportedSourceVersion(SourceVersion.RELEASE_8) +class MyProcessor() : AbstractProcessor() { + + private var fileCreated = false + + override fun process(annotations: Set, + roundEnv: RoundEnvironment): Boolean { + processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Working!") + if (fileCreated) return true + fileCreated = true + val file = processingEnv.filer.createSourceFile("Check") + file.openWriter().use { + it.appendln("// $annotations") + it.appendln("public class Check {}") + } + return true + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/settings.gradle new file mode 100644 index 00000000000..57d0d2be8eb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'kaptbug' include 'processor' \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/src/main/kotlin/annotation/ProcessThis.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/src/main/kotlin/annotation/ProcessThis.kt new file mode 100644 index 00000000000..6a067dbcd41 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/src/main/kotlin/annotation/ProcessThis.kt @@ -0,0 +1,3 @@ +package annotation + +annotation class ProcessThis diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/src/main/kotlin/model/Model.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/src/main/kotlin/model/Model.kt new file mode 100644 index 00000000000..2ebd8dd9129 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/autoService/src/main/kotlin/model/Model.kt @@ -0,0 +1,17 @@ +package model + +import annotation.ProcessThis + +@ProcessThis +interface Model { + + var a: Int + + var b: Int +} + +@ProcessThis +class Class { + + var a = 0 +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index cb22a0c9a55..ede383449df 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -60,12 +60,6 @@ internal class GradleCompilerRunner(private val project: Project) : KotlinCompil ): ExitCode { val outputDir = args.destinationAsFile - if (environment !is GradleIncrementalCompilerEnvironment) { - log.debug("Removing all kotlin classes in $outputDir") - // we're free to delete all classes since only we know about that directory - outputDir.deleteRecursively() - } - val moduleFile = makeModuleFile( args.moduleName, isTest = false, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt index a35e4face75..b9c4873577c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/Kapt3KotlinGradleSubplugin.kt @@ -29,6 +29,7 @@ import org.gradle.api.tasks.compile.JavaCompile import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.tasks.SyncOutputTask import java.io.File // apply plugin: 'kotlin-kapt' @@ -59,6 +60,9 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { } fun findMainKaptConfiguration(project: Project) = project.findKaptConfiguration(MAIN_KAPT_CONFIGURATION_NAME) + + fun getKaptClasssesDir(project: Project, sourceSetName: String): File = + File(project.project.buildDir, "tmp/kapt3/classes/$sourceSetName") } private val kotlinToKaptTasksMap = mutableMapOf() @@ -156,7 +160,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { javaCompile.source(generatedFilesDir) pluginOptions += SubpluginOption("sources", generatedFilesDir.canonicalPath) - pluginOptions += SubpluginOption("classes", kotlinCompile.destinationDir.canonicalPath) + pluginOptions += SubpluginOption("classes", getKaptClasssesDir(project, sourceSetName).canonicalPath) val androidPlugin = variantData?.let { project.extensions.findByName("android") as? BaseExtension @@ -193,6 +197,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { private fun Kapt3SubpluginContext.createKaptKotlinTask() { val sourcesOutputDir = getKaptGeneratedDir(project, sourceSetName) + val classesOutputDir = getKaptClasssesDir(project, sourceSetName) // Replace compile*Kotlin to kapt*Kotlin assert(kotlinCompile.name.startsWith("compile")) @@ -207,6 +212,7 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { kaptTask.mapClasspath { kotlinCompile.classpath } kaptTask.destinationDir = sourcesOutputDir + kaptTask.classesDir = classesOutputDir kaptTask.dependsOn(*(javaCompile.dependsOn.filter { it !== kotlinCompile }.toTypedArray())) kotlinCompile.dependsOn(kaptTask) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt index 5526bab9191..c0bdf5f365d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/KaptTask.kt @@ -39,12 +39,17 @@ open class KaptTask : AbstractCompile() { return FileUtil.isAncestor(destinationDir, this, /* strict = */ false) } + lateinit var classesDir: File + @TaskAction override fun compile() { /** Delete everything inside the [destinationDir] */ destinationDir.deleteRecursively() destinationDir.mkdirs() + classesDir.deleteRecursively() + classesDir.mkdirs() + val sourceRoots = SourceRoots.ForJvm.create(getSource(), rawSourceRoots) val compileClasspath = classpath.toList().filter(File::exists) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 6e8415b2b73..bde7f14954c 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -21,15 +21,15 @@ import org.gradle.api.tasks.bundling.Zip import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl -import org.jetbrains.kotlin.gradle.internal.AnnotationProcessingManager -import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin -import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin -import org.jetbrains.kotlin.gradle.internal.initKapt +import org.jetbrains.kotlin.gradle.internal.* +import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin.Companion.getKaptClasssesDir import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.plugin.android.KotlinJillTask import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProviderAndroidWrapper +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import java.io.File import java.net.URL import java.util.* @@ -540,6 +540,7 @@ private fun createSyncOutputTask( syncTask.kotlinTask = kotlinCompile kotlinTask.javaOutputDir = javaDir kotlinAfterJavaTask?.javaOutputDir = javaDir + syncTask.kaptClassesDir = getKaptClasssesDir(project, variantName) // copying should be executed after a latter task val previousTask = kotlinAfterJavaTask ?: javaTask diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt index f810f834c56..c1676a675d5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SyncOutputTask.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.gradle.tasks +import ch.qos.logback.core.util.FileUtil import org.gradle.api.DefaultTask import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.OutputDirectory @@ -23,6 +24,7 @@ import org.gradle.api.tasks.OutputFiles import org.gradle.api.tasks.TaskAction import org.gradle.api.tasks.incremental.IncrementalTaskInputs import org.gradle.api.tasks.incremental.InputFileDetails +import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil.* import org.jetbrains.kotlin.gradle.plugin.kotlinDebug import java.io.File import java.io.ObjectInputStream @@ -55,6 +57,13 @@ import kotlin.properties.Delegates internal open class SyncOutputTask : DefaultTask() { @get:InputFiles var kotlinOutputDir: File by Delegates.notNull() + + @get:InputFiles + var kaptClassesDir: File by Delegates.notNull() + + private val classesDirs: List + get() = listOf(kotlinOutputDir, kaptClassesDir).filter(File::exists) + var javaOutputDir: File by Delegates.notNull() var kotlinTask: KotlinCompile by Delegates.notNull() @@ -78,13 +87,14 @@ internal open class SyncOutputTask : DefaultTask() { @Suppress("unused") @TaskAction fun execute(inputs: IncrementalTaskInputs): Unit { + val sourceDirs = classesDirs.joinToString() if (inputs.isIncremental) { - logger.kotlinDebug { "Incremental copying files from $kotlinOutputDir to $javaOutputDir" } + logger.kotlinDebug { "Incremental copying files from $sourceDirs to $javaOutputDir" } inputs.outOfDate { processIncrementally(it) } inputs.removed { processIncrementally(it) } } else { - logger.kotlinDebug { "Non-incremental copying files from $kotlinOutputDir to $javaOutputDir" } + logger.kotlinDebug { "Non-incremental copying files from $sourceDirs to $javaOutputDir" } processNonIncrementally() } @@ -103,14 +113,16 @@ internal open class SyncOutputTask : DefaultTask() { timestampsFile.delete() timestamps.clear() - kotlinOutputDir.walkTopDown().forEach { - copy(it, it.siblingInJavaDir) + for (dir in classesDirs) { + dir.walkTopDown().forEach { + copy(it, it.siblingInJavaDir(baseDir = dir)) + } } } private fun processIncrementally(input: InputFileDetails) { val fileInKotlinDir = input.file - val fileInJavaDir = fileInKotlinDir.siblingInJavaDir + val fileInJavaDir = fileInKotlinDir.siblingInJavaDir() if (input.isRemoved) { // file was removed in kotlin dir, remove from java as well @@ -146,8 +158,10 @@ internal open class SyncOutputTask : DefaultTask() { } } - private val File.siblingInJavaDir: File - get() = File(javaOutputDir, this.relativeTo(kotlinOutputDir).path) + private fun File.siblingInJavaDir(baseDir: File? = null): File { + val base = baseDir ?: classesDirs.find { isAncestor(it, this, true) }!! + return File(javaOutputDir, this.relativeTo(base).path) + } } private val TIMESTAMP_FILE_NAME = "kotlin-files-in-java-timestamps.bin" 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 4f635a8ba8a..bb7b8ddabdb 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 @@ -231,6 +231,12 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl } } + if (!incremental) { + logger.kotlinDebug { "Removing all kotlin classes in $destinationDir" } + destinationDir.deleteRecursively() + destinationDir.mkdirs() + } + try { val exitCode = compilerRunner.runJvmCompiler(sourceRoots.kotlinSourceFiles, sourceRoots.javaSourceRoots, args, environment) processCompilerExitCode(exitCode)