diff --git a/libraries/examples/annotation-processor-example/src/main/kotlin/example/KotlinFilerGeneratingProcessor.kt b/libraries/examples/annotation-processor-example/src/main/kotlin/example/KotlinFilerGeneratingProcessor.kt new file mode 100644 index 00000000000..523f7fb2f33 --- /dev/null +++ b/libraries/examples/annotation-processor-example/src/main/kotlin/example/KotlinFilerGeneratingProcessor.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package example + +import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.RoundEnvironment +import javax.lang.model.SourceVersion +import javax.lang.model.element.TypeElement +import javax.tools.StandardLocation + +/** Annotation processor that users [javax.annotation.processing.Filer] APIs to generate Kotlin sources. */ +class KotlinFilerGeneratingProcessor : AbstractProcessor() { + + override fun process(annotations: MutableSet?, roundEnv: RoundEnvironment): Boolean { + val annotatedWith = roundEnv.getElementsAnnotatedWith(KotlinFilerGenerated::class.java) + + for (element in annotatedWith) { + val packageName = processingEnv.elementUtils.getPackageOf(element).qualifiedName.toString() + val simpleName = element.simpleName.toString() + + processingEnv.filer.createResource(StandardLocation.SOURCE_OUTPUT, packageName, "${simpleName}Generated.kt", element) + .openWriter().use { + it.write( + """ + package $packageName + + class ${simpleName}Generated + """.trimIndent() + ) + } + } + return true + } + + override fun getSupportedSourceVersion() = SourceVersion.RELEASE_6 + + override fun getSupportedAnnotationTypes(): Set { + return setOf(KotlinFilerGenerated::class.java.canonicalName) + } +} \ No newline at end of file diff --git a/libraries/examples/annotation-processor-example/src/main/kotlin/example/annotations.kt b/libraries/examples/annotation-processor-example/src/main/kotlin/example/annotations.kt index 25222c6fc04..b7ccbc84bfa 100644 --- a/libraries/examples/annotation-processor-example/src/main/kotlin/example/annotations.kt +++ b/libraries/examples/annotation-processor-example/src/main/kotlin/example/annotations.kt @@ -17,4 +17,6 @@ annotation class ExampleBinaryAnnotation @Retention(AnnotationRetention.RUNTIME) annotation class ExampleRuntimeAnnotation -annotation class GenError \ No newline at end of file +annotation class GenError + +annotation class KotlinFilerGenerated \ No newline at end of file diff --git a/libraries/examples/annotation-processor-example/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/libraries/examples/annotation-processor-example/src/main/resources/META-INF/services/javax.annotation.processing.Processor index af5b149f6fb..4392f5eafb8 100644 --- a/libraries/examples/annotation-processor-example/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/libraries/examples/annotation-processor-example/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1 +1,2 @@ -example.ExampleAnnotationProcessor \ No newline at end of file +example.ExampleAnnotationProcessor +example.KotlinFilerGeneratingProcessor \ No newline at end of file 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 4d04b578ae9..ee03b3a1dd1 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 @@ -517,6 +517,12 @@ abstract class BaseGradleIT { assertTasksNotRealized(*tasks) } + fun CompiledProject.assertTasksSkipped(vararg tasks: String) { + for (task in tasks) { + assertContains("Skipping task '$task'") + } + } + fun CompiledProject.getOutputForTask(taskName: String): String { val taskOutputRegex = ("(?:\\[LIFECYCLE] \\[class org\\.gradle(?:\\.internal\\.buildevents)?\\.TaskExecutionLogger] :$taskName|" + "\\[org\\.gradle\\.execution\\.plan\\.DefaultPlanExecutor\\] :$taskName.*?started)" + 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 4930dab7553..917dea64d45 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 @@ -612,4 +612,33 @@ open class Kapt3IT : Kapt3BaseIT() { assertTasksExecuted(":dac:jdk:kaptGenerateStubsKotlin", ":dac:jdk:compileKotlin") } } + + /** Regression test for KT-31127. */ + @Test + fun testKotlinProcessorUsingFiler() { + val project = Project("kotlinProject").apply { + setupWorkingDir() + gradleBuildScript().appendText(""" + apply plugin: 'kotlin-kapt' + + dependencies { + kapt "org.jetbrains.kotlin:annotation-processor-example:${"$"}kotlin_version" + implementation "org.jetbrains.kotlin:annotation-processor-example:${"$"}kotlin_version" + } + """.trimIndent()) + + // The test must not contain any java sources in order to detect the issue. + Assert.assertEquals(emptyList(), projectDir.allJavaFiles().toList()) + projectDir.getFileByName("Dummy.kt").modify { + it.replace("class Dummy", "@example.KotlinFilerGenerated class Dummy") + } + } + + project.build("build") { + assertSuccessful() + assertFileExists("build/generated/source/kapt/main/demo/DummyGenerated.kt") + assertTasksExecuted(":compileKotlin") + assertTasksSkipped(":compileJava") + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index 12d25a9d9f9..a2e220f4e2d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -266,8 +266,6 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin { pluginOptions += SubpluginOption("aptMode", aptMode) disableAnnotationProcessingInJavaTask() - javaCompile?.source(generatedFilesDir) - pluginOptions += FilesSubpluginOption("sources", listOf(generatedFilesDir)) pluginOptions += FilesSubpluginOption("classes", listOf(getKaptGeneratedClassesDir(project, sourceSetName))) @@ -527,7 +525,9 @@ private val artifactType = Attribute.of("artifactType", String::class.java) internal fun registerGeneratedJavaSource(kaptTask: KaptTask, javaTask: AbstractCompile) { - javaTask.source(kaptTask.destinationDir) + val generatedJavaSources = javaTask.project.fileTree(kaptTask.destinationDir) + generatedJavaSources.include("**/*.java") + javaTask.source(generatedJavaSources) } internal fun Configuration.getNamedDependencies(): List = allDependencies.filter { it.group != null && it.name != null }