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 2f55ae4c88e..3fa5d78765b 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 @@ -90,6 +90,10 @@ class Kapt3ClassLoadersCacheIT : Kapt3IT() { override fun testChangesToKaptConfigurationDoNotTriggerStubGeneration(gradleVersion: GradleVersion) { } + @Disabled("classloaders cache is leaking file descriptors that prevents cleaning test project") + override fun testKt33847(gradleVersion: GradleVersion) { + } + override fun testAnnotationProcessorAsFqName(gradleVersion: GradleVersion) { project("annotationProcessorAsFqName".withPrefix, gradleVersion) { //classloaders caching is not compatible with includeCompileClasspath @@ -812,6 +816,38 @@ open class Kapt3IT : Kapt3BaseIT() { } } + @DisplayName("KT33847: Kapt does not included Filer-generated class files on compilation classpath") + @GradleTest + open fun testKt33847(gradleVersion: GradleVersion) { + project("kt33847".withPrefix, gradleVersion) { + + build("build") { + val processorSubproject = subProject("processor") + processorSubproject + .assertFileInProjectExists("build/tmp/kapt3/classes/main/META-INF/services/javax.annotation.processing.Processor") + + val processorJar = processorSubproject.projectPath.resolve("build/libs/processor.jar") + assertFileExists(processorJar) + + ZipFile(processorJar.toFile()).use { zip -> + assert(zip.getEntry("META-INF/services/javax.annotation.processing.Processor") != null) { + "Generated annotation processor jar file does not contain processor service entry!" + } + } + + assertTasksExecuted( + ":api:compileKotlin", + ":processor:compileKotlin", + ":library:kaptGenerateStubsKotlin", + ":library:kaptKotlin", + ":library:compileKotlin", + ":app:compileKotlin", + ) + assertKaptSuccessful() + } + } + } + @DisplayName("Dependency on kapt module should not resolve all configurations") @GradleTest fun testDependencyOnKaptModule(gradleVersion: GradleVersion) { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/api/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/api/build.gradle new file mode 100755 index 00000000000..439508cdc9a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/api/build.gradle @@ -0,0 +1,7 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/api/src/main/kotlin/Api.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/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/kt33847/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/kt33847/app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/app/build.gradle new file mode 100755 index 00000000000..bf92b34cb94 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/app/build.gradle @@ -0,0 +1,8 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation project(':library') +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/app/src/main/kotlin/App.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/app/src/main/kotlin/App.kt new file mode 100755 index 00000000000..a74820c7783 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/app/src/main/kotlin/App.kt @@ -0,0 +1,6 @@ +package com.example + +fun app() { + GeneratedSomeClass + println(StringFactory.generateString()) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/build.gradle new file mode 100755 index 00000000000..17bd6a55884 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/build.gradle @@ -0,0 +1,10 @@ +subprojects { + repositories { + mavenLocal() + mavenCentral() + } +} + +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/kt33847/library/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/library/build.gradle new file mode 100755 index 00000000000..56b62020636 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/library/build.gradle @@ -0,0 +1,10 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'org.jetbrains.kotlin.kapt' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 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/kt33847/library/src/main/kotlin/Library.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/library/src/main/kotlin/Library.kt new file mode 100755 index 00000000000..3e4cc12d048 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/library/src/main/kotlin/Library.kt @@ -0,0 +1,13 @@ +package com.example + +@SomeAnnotation +object SomeClass { + init { + println(StringFactory.generateString()) + } +} + +fun library() { + GeneratedSomeClass + println(StringFactory.generateString()) +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/build.gradle new file mode 100755 index 00000000000..89a6d4a7ef1 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/build.gradle @@ -0,0 +1,11 @@ +plugins { + id 'org.jetbrains.kotlin.jvm' + id 'org.jetbrains.kotlin.kapt' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + implementation 'com.google.auto.service:auto-service:1.0-rc3' + kapt 'com.google.auto.service:auto-service:1.0-rc3' + implementation project(':api') +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/src/main/kotlin/Processor.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/src/main/kotlin/Processor.kt new file mode 100755 index 00000000000..d9499ef6527 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/src/main/kotlin/Processor.kt @@ -0,0 +1,58 @@ +package com.example + +import com.google.auto.service.AutoService +import org.intellij.lang.annotations.Language +import javax.annotation.processing.AbstractProcessor +import javax.annotation.processing.ProcessingEnvironment +import javax.annotation.processing.Processor +import javax.annotation.processing.RoundEnvironment +import javax.lang.model.element.TypeElement +import javax.tools.Diagnostic +import javax.tools.Diagnostic.Kind.MANDATORY_WARNING +import javax.tools.StandardLocation + +@AutoService(Processor::class) +class Processor : AbstractProcessor() { + + override fun getSupportedAnnotationTypes() = setOf(SomeAnnotation::class.java.canonicalName) + + override fun process(annotations: Set, roundEnv: RoundEnvironment): Boolean { + if (annotations.isNotEmpty()) { + processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Writing StringFactory") + processingEnv.filer.createClassFile("com.example.StringFactory", *annotations.toTypedArray()) + .openOutputStream() + .use { output -> + javaClass.classLoader.getResourceAsStream("StringFactory.class")!! + .use { it.copyTo(output) } + } + } + + for (element in roundEnv.getElementsAnnotatedWith(SomeAnnotation::class.java)) { + val packageName = processingEnv.elementUtils.getPackageOf(element).qualifiedName + val name = "Generated${element.simpleName}" + val file = processingEnv.filer.createResource( + StandardLocation.SOURCE_OUTPUT, + packageName, + "$name.kt", + element + ) + processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Writing $name") + file.openWriter().use { writer -> + writer.write( + //language=kotlin + """ + package $packageName + + object $name { + init { + println(StringFactory.generateString()) + } + } + """.trimIndent() + ) + } + } + + return true + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/src/main/resources/StringFactory.class b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/src/main/resources/StringFactory.class new file mode 100644 index 00000000000..0111d04c731 Binary files /dev/null and b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/processor/src/main/resources/StringFactory.class differ diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/settings.gradle new file mode 100755 index 00000000000..cefd6c87f38 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/kapt2/kt33847/settings.gradle @@ -0,0 +1,5 @@ +rootProject.name = 'kapt3-issues' +include ':api' +include ':processor' +include ':library' +include ':app' diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt index 6cecf5555ad..0dd803c8d70 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/Kapt3KotlinGradleSubplugin.kt @@ -384,8 +384,11 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To kotlinCompilation.output.classesDirs.from(taskProvider.flatMap { it.classesDir }) - kotlinCompilation.compileKotlinTaskProvider.configure { - (it as AbstractKotlinCompileTool<*>).setSource(sourcesOutputDir, kotlinSourcesOutputDir) + kotlinCompilation.compileTaskProvider.configure { task -> + with(task as AbstractKotlinCompile<*>) { + setSource(sourcesOutputDir, kotlinSourcesOutputDir) + libraries.from(classesOutputDir) + } } } taskConfigAction.configureTask { task -> @@ -424,7 +427,7 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To val kaptTaskName = getKaptTaskName("kaptGenerateStubs") val kaptTaskProvider = project.registerTask(kaptTaskName) - val taskConfig = KaptGenerateStubsConfig(kotlinCompilation, kotlinCompile) + val taskConfig = KaptGenerateStubsConfig(kotlinCompilation, kotlinCompile, classesOutputDir) taskConfig.configureTask { it.stubsDir.set(getKaptStubsDir()) it.destinationDirectory.set(getKaptIncrementalDataDir()) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt index 9da702b6d1f..3f375d38e9d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptConfig.kt @@ -63,7 +63,7 @@ internal open class KaptConfig( internal constructor(kotlinCompileTask: KotlinCompile, ext: KaptExtension) : this(kotlinCompileTask.project, ext) { configureTask { task -> - task.classpath.from(kotlinCompileTask.libraries) + task.classpath.from(kotlinCompileTask.libraries - project.files(task.classesDir)) task.compiledSources.from( kotlinCompileTask.destinationDirectory, Callable { kotlinCompileTask.javaOutputDir.takeIf { it.isPresent } }) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptGenerateStubsConfig.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptGenerateStubsConfig.kt index a9b86b59a5e..40045dd9067 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptGenerateStubsConfig.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/tasks/configuration/KaptGenerateStubsConfig.kt @@ -31,13 +31,17 @@ import java.util.concurrent.ConcurrentHashMap internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig { - constructor(compilation: KotlinCompilationData<*>, kotlinTaskProvider: TaskProvider) : super(compilation) { + constructor( + compilation: KotlinCompilationData<*>, + kotlinTaskProvider: TaskProvider, + kaptClassesDir: File, + ) : super(compilation) { configureFromExtension(project.extensions.getByType(KaptExtension::class.java)) configureTask { task -> val kotlinCompileTask = kotlinTaskProvider.get() task.useModuleDetection.value(kotlinCompileTask.useModuleDetection).disallowChanges() task.moduleName.value(kotlinCompileTask.moduleName).disallowChanges() - task.libraries.from({ kotlinCompileTask.libraries }) + task.libraries.from({ kotlinCompileTask.libraries - project.files(kaptClassesDir) }) task.compileKotlinArgumentsContributor.set(providers.provider { kotlinCompileTask.compilerArgumentsContributor }) task.pluginOptions.addAll(kotlinCompileTask.pluginOptions) // KotlinCompile will also have as input output from KaptGenerateStubTask and KaptTask