diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginMultiVersionIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginMultiVersionIT.kt index dd1d2610061..f296e1a1421 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginMultiVersionIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/KotlinGradlePluginMultiVersionIT.kt @@ -1,8 +1,10 @@ package org.jetbrains.kotlin.gradle +import org.jetbrains.kotlin.gradle.util.getFileByName import org.jetbrains.kotlin.gradle.util.modify import org.junit.Test import java.io.File +import java.util.zip.ZipFile class KotlinGradlePluginMultiVersionIT : BaseMultiGradleVersionIT() { @Test @@ -18,6 +20,48 @@ class KotlinGradlePluginMultiVersionIT : BaseMultiGradleVersionIT() { } } + @Test + fun testKt19179() { + val project = Project("kt19179", gradleVersion, directoryPrefix = "kapt2") + + project.build("build") { + assertSuccessful() + assertFileExists("processor/build/tmp/kapt3/classes/main/META-INF/services/javax.annotation.processing.Processor") + + val processorJar = fileInWorkingDir("processor/build/libs/processor.jar") + assert(processorJar.exists()) + + ZipFile(processorJar).use { zip -> + assert(zip.getEntry("META-INF/services/javax.annotation.processing.Processor") != null) + } + + assertTasksExecuted(listOf( + ":processor:kaptGenerateStubsKotlin", ":processor:kaptKotlin", + ":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")) + } + + project.projectDir.getFileByName("Test.kt").modify { text -> + assert("SomeClass()" in text) + text.replace("SomeClass()", "SomeClass(); val a = 5") + } + + project.build("build") { + assertSuccessful() + assertTasksUpToDate(listOf(":processor:kaptGenerateStubsKotlin", ":processor:kaptKotlin", ":app:kaptKotlin")) + assertTasksExecuted(listOf(":app:kaptGenerateStubsKotlin")) + } + + project.projectDir.getFileByName("Test.kt").modify { text -> + text + "\n\nfun t() {}" + } + + project.build("build") { + assertSuccessful() + assertTasksUpToDate(listOf(":processor:kaptGenerateStubsKotlin", ":processor:kaptKotlin")) + assertTasksExecuted(listOf(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")) + } + } + @Test fun testJavaIcCompatibility() { val version = gradleVersion.split(".").map(String::toInt) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/api/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/api/build.gradle new file mode 100755 index 00000000000..c102d8feb62 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/api/build.gradle @@ -0,0 +1,5 @@ +apply plugin: 'kotlin' + +dependencies { + compile "org.jetbrains.kotlin:kotlin-runtime:$kotlin_version" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/api/src/main/kotlin/Api.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/api/src/main/kotlin/Api.kt new file mode 100755 index 00000000000..c3eeb44bee6 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/api/src/main/kotlin/Api.kt @@ -0,0 +1,6 @@ +package com.example + +import kotlin.annotation.AnnotationTarget.CLASS + +@Target(CLASS) +annotation class SomeAnnotation diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/app/build.gradle new file mode 100755 index 00000000000..9f2cc286714 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/app/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'kotlin' +apply plugin: 'kotlin-kapt' + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile project(':api') + kapt project(':processor') +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/app/src/main/kotlin/Test.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/app/src/main/kotlin/Test.kt new file mode 100755 index 00000000000..2df966cd1c9 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/app/src/main/kotlin/Test.kt @@ -0,0 +1,7 @@ +package com.example + +@SomeAnnotation class SomeClass + +fun main(vararg args: String) { + SomeClass() +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/build.gradle new file mode 100755 index 00000000000..1f6e897ab73 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/build.gradle @@ -0,0 +1,20 @@ +buildscript { + repositories { + mavenLocal() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +subprojects { + repositories { + mavenLocal() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/processor/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/processor/build.gradle new file mode 100755 index 00000000000..5e68fcbb023 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/processor/build.gradle @@ -0,0 +1,9 @@ +apply plugin: 'kotlin' +apply plugin: 'kotlin-kapt' + +dependencies { + compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + compile 'com.google.auto.service:auto-service:1.0-rc3' + kapt 'com.google.auto.service:auto-service:1.0-rc3' + compile project(':api') +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/processor/src/main/kotlin/Processor.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/processor/src/main/kotlin/Processor.kt new file mode 100755 index 00000000000..1ace4544a14 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/processor/src/main/kotlin/Processor.kt @@ -0,0 +1,19 @@ +package com.example + +import com.google.auto.service.AutoService +import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.Processor +import javax.annotation.processing.RoundEnvironment +import javax.lang.model.element.TypeElement +import javax.tools.Diagnostic.Kind.MANDATORY_WARNING + +@AutoService(Processor::class) +class Processor : AbstractProcessor() { + + override fun getSupportedAnnotationTypes() = setOf(SomeAnnotation::class.java.canonicalName) + + override fun process(annotations: Set, roundEnv: RoundEnvironment): Boolean { + processingEnv.messager.printMessage(MANDATORY_WARNING, "*** AP RUNNING ***' ") + return true + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/settings.gradle new file mode 100755 index 00000000000..d9b509ea4f5 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt19179/settings.gradle @@ -0,0 +1,4 @@ +rootProject.name = 'kapt3-issues' +include ':app' +include ':api' +include ':processor' 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 e8f61bd1d12..505e4f35a92 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 @@ -281,19 +281,8 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { kaptTask.stubsDir = getKaptStubsDir() kaptTask.destinationDir = sourcesOutputDir - kaptTask.mapClasspath { kotlinCompile.classpath } kaptTask.classesDir = classesOutputDir - kaptTask.mapSource { - val sourcesFromKotlinTask = kotlinCompile.source - .filter { it.extension == "java" && !kaptTask.isInsideDestinationDirs(it) } - .asFileTree - - val stubSources = project.fileTree(kaptTask.stubsDir) - - sourcesFromKotlinTask + stubSources - } - kotlinCompile.source(sourcesOutputDir, kotlinSourcesOutputDir) if (kaptVariantData != null) { 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 a6ef4a21000..6b2bd652cb2 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 @@ -1,8 +1,9 @@ package org.jetbrains.kotlin.gradle.internal import org.gradle.api.GradleException -import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.compile.AbstractCompile +import org.gradle.api.file.FileCollection +import org.gradle.api.internal.ConventionTask +import org.gradle.api.tasks.* import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil import org.jetbrains.kotlin.compilerRunner.GradleCompilerEnvironment @@ -11,20 +12,37 @@ import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl import org.jetbrains.kotlin.gradle.tasks.* import java.io.File -open class KaptTask : AbstractCompile() { +open class KaptTask : ConventionTask() { internal val pluginOptions = CompilerPluginOptions() - internal lateinit var kotlinCompileTask: KotlinCompile - fun isInsideDestinationDirs(file: File): Boolean { + internal lateinit var kotlinCompileTask: KotlinCompile + internal lateinit var stubsDir: File + + private fun isInsideDestinationDirs(file: File): Boolean { return FileUtil.isAncestor(destinationDir, file, /* strict = */ false) || FileUtil.isAncestor(classesDir, file, /* strict = */ false) } - lateinit var classesDir: File - lateinit var stubsDir: File + @OutputDirectory + internal lateinit var classesDir: File + + @OutputDirectory + lateinit var destinationDir: File + + val classpath: FileCollection + @InputFiles get() = kotlinCompileTask.classpath + + val source: FileCollection + @InputFiles get() { + val sourcesFromKotlinTask = kotlinCompileTask.source + .filter { it.extension == "java" && !isInsideDestinationDirs(it) } + + val stubSources = project.fileTree(stubsDir) + return sourcesFromKotlinTask + stubSources + } @TaskAction - override fun compile() { + fun compile() { /** Delete everything inside generated sources and classes output directory * (annotation processing is not incremental) */ destinationDir.clearDirectory() diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/gradleUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/gradleUtils.kt index 699b30987c9..b5fb3b0cda8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/gradleUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/gradleUtils.kt @@ -51,10 +51,6 @@ fun AbstractCompile.mapClasspath(fn: () -> FileCollection) { conventionMapping.map("classpath", fn) } -internal fun AbstractCompile.mapSource(fn: () -> FileTree) { - conventionMapping.map("source", fn) -} - internal inline fun Any.addConvention(name: String, plugin: T) { (this as HasConvention).convention.plugins[name] = plugin }