KAPT: pass KAPT generated classes to kotlinc classpath
Make sure to pass .class files generated by annotation processors to KotlinCompile task. This way, Kotlin files can refer to symbols generated in these .class files during annotation processing. Disable the test in Kapt3ClassLoadersCacheIT #KT-33847 Fixed
This commit is contained in:
committed by
nataliya.valtman
parent
80fa765333
commit
1417c8961b
+36
@@ -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) {
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.example
|
||||
|
||||
import kotlin.annotation.AnnotationTarget.CLASS
|
||||
|
||||
@Target(CLASS)
|
||||
annotation class SomeAnnotation
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation project(':library')
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package com.example
|
||||
|
||||
fun app() {
|
||||
GeneratedSomeClass
|
||||
println(StringFactory.generateString())
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
subprojects {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
+10
@@ -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')
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.example
|
||||
|
||||
@SomeAnnotation
|
||||
object SomeClass {
|
||||
init {
|
||||
println(StringFactory.generateString())
|
||||
}
|
||||
}
|
||||
|
||||
fun library() {
|
||||
GeneratedSomeClass
|
||||
println(StringFactory.generateString())
|
||||
}
|
||||
+11
@@ -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')
|
||||
}
|
||||
+58
@@ -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<TypeElement>, 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
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
+5
@@ -0,0 +1,5 @@
|
||||
rootProject.name = 'kapt3-issues'
|
||||
include ':api'
|
||||
include ':processor'
|
||||
include ':library'
|
||||
include ':app'
|
||||
+6
-3
@@ -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<KaptGenerateStubsTask>(kaptTaskName)
|
||||
|
||||
val taskConfig = KaptGenerateStubsConfig(kotlinCompilation, kotlinCompile)
|
||||
val taskConfig = KaptGenerateStubsConfig(kotlinCompilation, kotlinCompile, classesOutputDir)
|
||||
taskConfig.configureTask {
|
||||
it.stubsDir.set(getKaptStubsDir())
|
||||
it.destinationDirectory.set(getKaptIncrementalDataDir())
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ internal open class KaptConfig<TASK : KaptTask>(
|
||||
|
||||
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 } })
|
||||
|
||||
+6
-2
@@ -31,13 +31,17 @@ import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStubsTask> {
|
||||
|
||||
constructor(compilation: KotlinCompilationData<*>, kotlinTaskProvider: TaskProvider<KotlinCompile>) : super(compilation) {
|
||||
constructor(
|
||||
compilation: KotlinCompilationData<*>,
|
||||
kotlinTaskProvider: TaskProvider<KotlinCompile>,
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user