[KAPT4] KT-51982 Implement Kapt4AnalysisHandlerExtension, add KAPT CLI and Gradle IT

Co-authored-by: Alexander Udalov <Alexander.Udalov@jetbrains.com>
This commit is contained in:
Alexander Udalov
2023-08-31 22:19:13 +00:00
committed by Space Team
parent d50d36f16c
commit 5c19cb3fcb
61 changed files with 1577 additions and 68 deletions
@@ -0,0 +1,3 @@
-language-version 2.0
-d output/ap
ap/Processor.kt
@@ -0,0 +1,36 @@
# copy
../simple/ap
ap
# copy
../simple/Test.kt
Test.kt
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
@apKotlincArgs.txt
# kapt
@kaptArgs.txt
# javac
@javacArgs.txt
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/classes:output/javaClasses
Test.kt
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test
@@ -0,0 +1,6 @@
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Function.java
output/sources/generated/Property.java
output/sources/generated/Test.java
@@ -0,0 +1,11 @@
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-processors=apt.SampleApt
-d output/classes
-cp output/ap
Test.kt
@@ -0,0 +1,11 @@
# kapt
-language-version 2.0
-Xsuppress-version-warnings
-Xuse-kapt4
-Kapt-mode=compile
../simple/Test.kt
# after
Return code: 1
error: [kapt] KAPT "compile" mode is not supported in Kotlin 2.x. Run kapt with -Kapt-mode=stubsAndApt and use kotlinc for the final compilation step.
@@ -0,0 +1,14 @@
package test
import apt.Anno
import generated.Property
object Test {
@field:Anno
lateinit var property: Property
@JvmStatic
fun main(args: Array<String>) {
print(javaClass.getDeclaredField("property").type.toGenericString())
}
}
@@ -0,0 +1,31 @@
package apt
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.*
import javax.lang.model.type.DeclaredType
import javax.tools.Diagnostic.Kind.*
annotation class Anno
class SampleApt : AbstractProcessor() {
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
for (element in roundEnv.getElementsAnnotatedWith(Anno::class.java).filterIsInstance<VariableElement>()) {
val type = element.asType() as? DeclaredType ?: continue
if (type.toString() == "error.NonExistentClass") {
processingEnv.messager.printMessage(ERROR, "NonExistentClass type occurred")
}
val generatedSimpleName = element.simpleName.toString().capitalize()
processingEnv.filer.createSourceFile("generated.$generatedSimpleName").openWriter().use {
it.write("package generated;\npublic class $generatedSimpleName {}")
}
}
return true
}
override fun getSupportedOptions() = emptySet<String>()
override fun getSupportedSourceVersion() = SourceVersion.RELEASE_8
override fun getSupportedAnnotationTypes() = setOf("apt.Anno")
}
@@ -0,0 +1,44 @@
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-processors=apt.SampleApt
-Kapt-correct-error-types=true
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# javac
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Property.java
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/classes:%KOTLIN_STDLIB%
Test.kt
output/sources
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.Test
# after
public class generated.Property
@@ -0,0 +1 @@
class RootClass
@@ -0,0 +1,7 @@
package test
import RootClass
interface Usage {
fun test(): RootClass
}
@@ -0,0 +1,47 @@
# copy
../simple/ap
ap
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-processors=apt.SampleApt
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
RootClass.kt
Usage.kt
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/classes:output/sources:%KOTLIN_STDLIB%
RootClass.kt
Usage.kt
# after
Return code: 1
warning: [kapt] test.Usage: Can't reference type 'RootClass' from default package in Java stub.
error: output/stubs/test/Usage.java:9: error: cannot find symbol
public abstract RootClass test();
^
symbol: class RootClass
location: interface Usage
@@ -0,0 +1,19 @@
package test
import apt.Anno
import generated.Test as TestGenerated
@Anno
class Test {
@field:Anno
val property: String = ""
@Anno
fun function() {
}
}
fun main() {
println("Generated class: " + TestGenerated::class.java.name)
}
@@ -0,0 +1,37 @@
package apt
import java.io.File
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement
import javax.tools.Diagnostic.Kind.*
annotation class Anno
class SampleApt : AbstractProcessor() {
private companion object {
const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"
}
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
val kaptKotlinGeneratedDir = processingEnv.options[KAPT_KOTLIN_GENERATED_OPTION_NAME] ?: run {
processingEnv.messager.printMessage(ERROR, "Can't find the target directory for generated Kotlin files.")
return false
}
val baseDir = File(kaptKotlinGeneratedDir, "generated")
baseDir.mkdirs()
for (element in roundEnv.getElementsAnnotatedWith(Anno::class.java)) {
val generatedSimpleName = element.simpleName.toString().capitalize()
val file = File(baseDir, "$generatedSimpleName.kt")
file.writeText("package generated\n@apt.Anno\nclass $generatedSimpleName")
}
return true
}
override fun getSupportedOptions() = emptySet<String>()
override fun getSupportedSourceVersion() = SourceVersion.RELEASE_8
override fun getSupportedAnnotationTypes() = setOf("apt.Anno")
}
@@ -0,0 +1,43 @@
# mkdir
output/ap
output/stubs
output/classes
output/sources
output/kotlin-sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# copy
ap/META-INF/services/javax.annotation.processing.Processor
output/ap/META-INF/services/javax.annotation.processing.Processor
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-option:kapt.kotlin.generated=output/kotlin-sources
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
output/kotlin-sources
# java
-cp output/classes:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test
@@ -0,0 +1,48 @@
# copy
../simple/ap
ap
# copy
../simple/Test.kt
Test.kt
# mkdir
output/ap
output/stubs
output/classes
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-processors=apt.SampleApt
-Kapt-option:kapt.test.writeKotlinFiles=true
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# kotlinc
-language-version 2.0
-Xuse-kapt4
-d output/classes
-cp output/classes:output/ap:%KOTLIN_STDLIB%
Test.kt
output/sources
# java
-cp output/classes:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test
@@ -0,0 +1,19 @@
package test
import apt.Anno
import generated.Example as ExampleGenerated
@Anno
class Example() {
private val callback = object : Any() {
val obj = Object()
}
fun call() {
callback.obj
}
}
fun main() {
println("Generated class: " + ExampleGenerated::class.java.name)
}
@@ -0,0 +1,52 @@
# copy
../simple/ap
ap
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# copy
../simple/ap/META-INF/services/javax.annotation.processing.Processor
output/ap/META-INF/services/javax.annotation.processing.Processor
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/classes:%KOTLIN_STDLIB%
Test.kt
output/sources
# javac
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Example.java
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Example
@@ -0,0 +1,11 @@
package test
import apt.Annotation1
import generated.Test123
@Annotation1
class Test
fun main() {
println("Generated class: " + Test123::class.java.name)
}
@@ -0,0 +1,68 @@
package apt
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement
import javax.tools.Diagnostic
annotation class Annotation1
annotation class Annotation2
annotation class Annotation3
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("apt.Annotation1")
class AnnotationProcessor1 : AbstractProcessor() {
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
val elements = roundEnv.getElementsAnnotatedWith(Annotation1::class.java)
for (element in elements) {
val generatedSimpleName = "${element.simpleName}1"
val file = processingEnv.filer.createSourceFile("generated.$generatedSimpleName")
file.openWriter().use {
it.write("package generated;\n@apt.Annotation2\npublic class $generatedSimpleName {}")
}
}
return true
}
}
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("apt.Annotation2")
class AnnotationProcessor2 : AbstractProcessor() {
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
val elements = roundEnv.getElementsAnnotatedWith(Annotation2::class.java)
for (element in elements) {
val generatedSimpleName = "${element.simpleName}2"
val file = processingEnv.filer.createSourceFile("generated.$generatedSimpleName")
file.openWriter().use {
it.write("package generated;\n@apt.Annotation3\npublic class $generatedSimpleName {}")
}
}
return true
}
}
@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("apt.Annotation3")
class AnnotationProcessor3 : AbstractProcessor() {
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
val elements = roundEnv.getElementsAnnotatedWith(Annotation3::class.java)
for (element in elements) {
val generatedSimpleName = "${element.simpleName}3"
val file = processingEnv.filer.createSourceFile("generated.$generatedSimpleName")
file.openWriter().use {
it.write("package generated;\npublic class $generatedSimpleName {}")
}
}
return true
}
}
@@ -0,0 +1,48 @@
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/processors.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-processors=apt.AnnotationProcessor3
-Kapt-processors=apt.AnnotationProcessor2
-Kapt-processors=apt.AnnotationProcessor1
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# javac
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Test1.java
output/sources/generated/Test12.java
output/sources/generated/Test123.java
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/javaClasses:output/classes:%KOTLIN_STDLIB%
Test.kt
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test123
@@ -0,0 +1,67 @@
# copy
../simple/ap
ap
# copy
../simple/Test.kt
Test.kt
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-mode=stubs
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-mode=apt
-Kapt-processors=apt.SampleApt
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
output/sources
Test.kt
# javac
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Function.java
output/sources/generated/Property.java
output/sources/generated/Test.java
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test
@@ -0,0 +1,19 @@
package test
import apt.Anno
import generated.Test as TestGenerated
@Anno
class Test {
@field:Anno
val property: String = ""
@Anno
fun function() {
}
}
fun main() {
println("Generated class: " + TestGenerated::class.java.name)
}
@@ -0,0 +1,34 @@
package apt
import javax.annotation.processing.*
import javax.lang.model.SourceVersion
import javax.lang.model.element.TypeElement
import javax.tools.Diagnostic.Kind.*
import javax.tools.StandardLocation
annotation class Anno
class SampleApt : AbstractProcessor() {
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
val writeKotlinFiles = processingEnv.options["kapt.test.writeKotlinFiles"] == "true"
for (element in roundEnv.getElementsAnnotatedWith(Anno::class.java)) {
val generatedSimpleName = element.simpleName.toString().capitalize()
val file = when (writeKotlinFiles) {
true -> processingEnv.filer.createResource(StandardLocation.SOURCE_OUTPUT, "generated", "$generatedSimpleName.kt")
false -> processingEnv.filer.createSourceFile("generated.$generatedSimpleName")
}
file.openWriter().use {
it.write("package generated;\npublic class $generatedSimpleName {}")
}
}
return true
}
override fun getSupportedOptions() = setOf("kapt.test.writeKotlinFiles")
override fun getSupportedSourceVersion() = SourceVersion.RELEASE_8
override fun getSupportedAnnotationTypes() = setOf("apt.Anno")
}
@@ -0,0 +1,49 @@
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# copy
ap/META-INF/services/javax.annotation.processing.Processor
output/ap/META-INF/services/javax.annotation.processing.Processor
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-mode=stubsAndApt
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# javac
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Function.java
output/sources/generated/Property.java
output/sources/generated/Test.java
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/javaClasses:output/classes:%KOTLIN_STDLIB%
Test.kt
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test
@@ -0,0 +1,54 @@
# copy
../simple/ap
ap
# copy
../simple/Test.kt
Test.kt
# mkdir
output/ap
output/stubs
output/classes
output/javaClasses
output/sources
# kotlinc
-language-version 2.0
-cp %KOTLIN_STDLIB%
-d output/ap
ap/Processor.kt
# kapt
-language-version 2.0
-Xuse-kapt4
-Kapt-stubs=output/stubs
-Kapt-classes=output/classes
-Kapt-sources=output/sources
-Kapt-classpath=output/ap
-Kapt-processors=apt.SampleApt
-d output/classes
-cp output/ap:%KOTLIN_STDLIB%
Test.kt
# kotlinc
-language-version 2.0
-d output/classes
-cp output/ap:output/classes:%KOTLIN_STDLIB%
Test.kt
output/sources
# javac
-cp output/ap
-d output/javaClasses
-proc:none
output/sources/generated/Function.java
output/sources/generated/Property.java
output/sources/generated/Test.java
# java
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
test.TestKt
# after
Generated class: generated.Test