[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:
committed by
Space Team
parent
d50d36f16c
commit
5c19cb3fcb
@@ -77,7 +77,10 @@ private fun switchToFallbackModeIfNecessary(arguments: CommonCompilerArguments,
|
|||||||
arguments.skipPrereleaseCheck = true
|
arguments.skipPrereleaseCheck = true
|
||||||
arguments.allowUnstableDependencies = true
|
arguments.allowUnstableDependencies = true
|
||||||
}
|
}
|
||||||
arguments.useKapt4 && !isK2 -> warn("-Xuse-kapt4 flag can be only used with language version 2.0+.")
|
arguments.useKapt4 -> warn(
|
||||||
|
if (isK2) "Kapt 4 is an experimental feature. Use with caution."
|
||||||
|
else "-Xuse-kapt4 flag can be only used with language version 2.0+."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.jvm.abi.AbstractCompareJvmAbiTest
|
|||||||
import org.jetbrains.kotlin.jvm.abi.AbstractCompileAgainstJvmAbiTest
|
import org.jetbrains.kotlin.jvm.abi.AbstractCompileAgainstJvmAbiTest
|
||||||
import org.jetbrains.kotlin.jvm.abi.AbstractJvmAbiContentTest
|
import org.jetbrains.kotlin.jvm.abi.AbstractJvmAbiContentTest
|
||||||
import org.jetbrains.kotlin.kapt.cli.test.AbstractArgumentParsingTest
|
import org.jetbrains.kotlin.kapt.cli.test.AbstractArgumentParsingTest
|
||||||
|
import org.jetbrains.kotlin.kapt.cli.test.AbstractKapt4ToolIntegrationTest
|
||||||
import org.jetbrains.kotlin.kapt.cli.test.AbstractKaptToolIntegrationTest
|
import org.jetbrains.kotlin.kapt.cli.test.AbstractKaptToolIntegrationTest
|
||||||
import org.jetbrains.kotlin.kapt3.test.runners.AbstractClassFileToSourceStubConverterTest
|
import org.jetbrains.kotlin.kapt3.test.runners.AbstractClassFileToSourceStubConverterTest
|
||||||
import org.jetbrains.kotlin.kapt3.test.runners.AbstractIrClassFileToSourceStubConverterTest
|
import org.jetbrains.kotlin.kapt3.test.runners.AbstractIrClassFileToSourceStubConverterTest
|
||||||
@@ -371,10 +372,12 @@ fun main(args: Array<String>) {
|
|||||||
testClass<AbstractArgumentParsingTest> {
|
testClass<AbstractArgumentParsingTest> {
|
||||||
model("argumentParsing", extension = "txt")
|
model("argumentParsing", extension = "txt")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractKaptToolIntegrationTest> {
|
testClass<AbstractKaptToolIntegrationTest> {
|
||||||
model("integration", recursive = false, extension = null)
|
model("integration", recursive = false, extension = null)
|
||||||
}
|
}
|
||||||
|
testClass<AbstractKapt4ToolIntegrationTest> {
|
||||||
|
model("integration-kapt4", recursive = false, extension = null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
testGroup("plugins/kapt3/kapt3-compiler/tests-gen", "plugins/kapt3/kapt3-compiler/testData") {
|
testGroup("plugins/kapt3/kapt3-compiler/tests-gen", "plugins/kapt3/kapt3-compiler/testData") {
|
||||||
|
|||||||
+26
-11
@@ -36,7 +36,8 @@ import kotlin.io.path.deleteExisting
|
|||||||
import kotlin.io.path.outputStream
|
import kotlin.io.path.outputStream
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
abstract class Kapt3BaseIT(val languageVersion: String = "1.9") : KGPBaseTest() {
|
abstract class Kapt3BaseIT : KGPBaseTest() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val KAPT_SUCCESSFUL_MESSAGE = "Annotation processing complete, errors: 0"
|
private const val KAPT_SUCCESSFUL_MESSAGE = "Annotation processing complete, errors: 0"
|
||||||
}
|
}
|
||||||
@@ -44,8 +45,7 @@ abstract class Kapt3BaseIT(val languageVersion: String = "1.9") : KGPBaseTest()
|
|||||||
override val defaultBuildOptions: BuildOptions = super.defaultBuildOptions
|
override val defaultBuildOptions: BuildOptions = super.defaultBuildOptions
|
||||||
.copy(
|
.copy(
|
||||||
kaptOptions = this.kaptOptions(),
|
kaptOptions = this.kaptOptions(),
|
||||||
languageVersion = languageVersion,
|
).copyEnsuringK1()
|
||||||
)
|
|
||||||
|
|
||||||
protected open fun kaptOptions(): BuildOptions.KaptOptions = BuildOptions.KaptOptions(
|
protected open fun kaptOptions(): BuildOptions.KaptOptions = BuildOptions.KaptOptions(
|
||||||
verbose = true,
|
verbose = true,
|
||||||
@@ -74,8 +74,8 @@ abstract class Kapt3BaseIT(val languageVersion: String = "1.9") : KGPBaseTest()
|
|||||||
*
|
*
|
||||||
* then override and disable the test here via `@Disabled`.
|
* then override and disable the test here via `@Disabled`.
|
||||||
*/
|
*/
|
||||||
@DisplayName("Kapt with classloaders cache")
|
@DisplayName("Kapt 3 with classloaders cache")
|
||||||
class Kapt3ClassLoadersCacheIT : Kapt3IT() {
|
open class Kapt3ClassLoadersCacheIT : Kapt3IT() {
|
||||||
override fun kaptOptions(): BuildOptions.KaptOptions = super.kaptOptions().copy(
|
override fun kaptOptions(): BuildOptions.KaptOptions = super.kaptOptions().copy(
|
||||||
classLoadersCacheSize = 10,
|
classLoadersCacheSize = 10,
|
||||||
includeCompileClasspath = false
|
includeCompileClasspath = false
|
||||||
@@ -138,7 +138,7 @@ class Kapt3ClassLoadersCacheIT : Kapt3IT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("Kapt base checks")
|
@DisplayName("Kapt 3 base checks")
|
||||||
@OtherGradlePluginTests
|
@OtherGradlePluginTests
|
||||||
open class Kapt3IT : Kapt3BaseIT() {
|
open class Kapt3IT : Kapt3BaseIT() {
|
||||||
@DisplayName("Kapt is skipped when no annotation processors are added")
|
@DisplayName("Kapt is skipped when no annotation processors are added")
|
||||||
@@ -486,7 +486,7 @@ open class Kapt3IT : Kapt3BaseIT() {
|
|||||||
|
|
||||||
@DisplayName("Should incrementally rebuild on classpath change")
|
@DisplayName("Should incrementally rebuild on classpath change")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testChangeClasspathICRebuild(gradleVersion: GradleVersion) {
|
open fun testChangeClasspathICRebuild(gradleVersion: GradleVersion) {
|
||||||
testICRebuild(gradleVersion) { project ->
|
testICRebuild(gradleVersion) { project ->
|
||||||
project.buildGradle.modify {
|
project.buildGradle.modify {
|
||||||
"$it\ndependencies { implementation 'org.jetbrains.kotlin:kotlin-reflect:' + kotlin_version }"
|
"$it\ndependencies { implementation 'org.jetbrains.kotlin:kotlin-reflect:' + kotlin_version }"
|
||||||
@@ -944,7 +944,7 @@ open class Kapt3IT : Kapt3BaseIT() {
|
|||||||
|
|
||||||
@DisplayName("kapt works with old MPP")
|
@DisplayName("kapt works with old MPP")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun testMPPKaptPresence(gradleVersion: GradleVersion) {
|
open fun testMPPKaptPresence(gradleVersion: GradleVersion) {
|
||||||
project("mpp-kapt-presence".withPrefix, gradleVersion) {
|
project("mpp-kapt-presence".withPrefix, gradleVersion) {
|
||||||
|
|
||||||
build("build") {
|
build("build") {
|
||||||
@@ -1051,7 +1051,7 @@ open class Kapt3IT : Kapt3BaseIT() {
|
|||||||
|
|
||||||
@DisplayName("KT-46651: kapt is tracking source files properly with configuration cache enabled")
|
@DisplayName("KT-46651: kapt is tracking source files properly with configuration cache enabled")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
fun kaptGenerateStubsShouldNotCaptureSourcesStateInConfigurationCache(gradleVersion: GradleVersion) {
|
open fun kaptGenerateStubsShouldNotCaptureSourcesStateInConfigurationCache(gradleVersion: GradleVersion) {
|
||||||
project(
|
project(
|
||||||
"incrementalRebuild".withPrefix,
|
"incrementalRebuild".withPrefix,
|
||||||
gradleVersion,
|
gradleVersion,
|
||||||
@@ -1208,7 +1208,7 @@ open class Kapt3IT : Kapt3BaseIT() {
|
|||||||
|
|
||||||
@DisplayName("Kapt runs in fallback mode with useK2 = true")
|
@DisplayName("Kapt runs in fallback mode with useK2 = true")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
internal fun fallBackModeWithUseK2(gradleVersion: GradleVersion) {
|
open fun fallBackModeWithUseK2(gradleVersion: GradleVersion) {
|
||||||
project("simple".withPrefix, gradleVersion) {
|
project("simple".withPrefix, gradleVersion) {
|
||||||
buildGradle.appendText(
|
buildGradle.appendText(
|
||||||
"""
|
"""
|
||||||
@@ -1237,7 +1237,7 @@ open class Kapt3IT : Kapt3BaseIT() {
|
|||||||
|
|
||||||
@DisplayName("Kapt runs in fallback mode with languageVersion = 2.0")
|
@DisplayName("Kapt runs in fallback mode with languageVersion = 2.0")
|
||||||
@GradleTest
|
@GradleTest
|
||||||
internal fun fallBackModeWithLanguageVersion2_0(gradleVersion: GradleVersion) {
|
open fun fallBackModeWithLanguageVersion2_0(gradleVersion: GradleVersion) {
|
||||||
project("simple".withPrefix, gradleVersion) {
|
project("simple".withPrefix, gradleVersion) {
|
||||||
buildGradle.appendText(
|
buildGradle.appendText(
|
||||||
"""
|
"""
|
||||||
@@ -1347,4 +1347,19 @@ open class Kapt3IT : Kapt3BaseIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DisplayName("Application of annotation processors is repeated as long as new source files are generated")
|
||||||
|
@GradleTest
|
||||||
|
open fun testMultipleProcessingPasses(gradleVersion: GradleVersion) {
|
||||||
|
project("multipass".withPrefix, gradleVersion) {
|
||||||
|
build("build") {
|
||||||
|
assertKaptSuccessful()
|
||||||
|
assertOutputContains("No elements for AnnotationProcessor3")
|
||||||
|
assertOutputContains("No elements for AnnotationProcessor2")
|
||||||
|
assertFileInProjectExists("example/build/generated/source/kapt/main/generated/TestClass1.java")
|
||||||
|
assertFileInProjectExists("example/build/generated/source/kapt/main/generated/TestClass12.java")
|
||||||
|
assertFileInProjectExists("example/build/generated/source/kapt/main/generated/TestClass123.java")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.TestProject
|
||||||
|
import org.junit.jupiter.api.Disabled
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
import kotlin.io.path.appendText
|
||||||
|
import kotlin.io.path.name
|
||||||
|
import kotlin.io.path.walk
|
||||||
|
|
||||||
|
@DisplayName("Kapt 4 base checks")
|
||||||
|
class Kapt4IT : Kapt3IT() {
|
||||||
|
override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
|
||||||
|
|
||||||
|
override fun TestProject.customizeProject() {
|
||||||
|
forceKapt4()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Currently failing. See KT-60950")
|
||||||
|
override fun kaptGenerateStubsShouldNotCaptureSourcesStateInConfigurationCache(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Currently failing. See KT-60951")
|
||||||
|
override fun testChangeClasspathICRebuild(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun useGeneratedKotlinSourceK2(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun fallBackModeWithUseK2(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun fallBackModeWithLanguageVersion2_0(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun testRepeatableAnnotationsWithOldJvmBackend(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't work in 2.0. Neither with Kapt 3 nor with Kapt 4")
|
||||||
|
override fun testMPPKaptPresence(gradleVersion: GradleVersion) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("Kapt 4 with classloaders cache")
|
||||||
|
class Kapt4ClassLoadersCacheIT : Kapt3ClassLoadersCacheIT() {
|
||||||
|
override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
|
||||||
|
|
||||||
|
override fun TestProject.customizeProject() {
|
||||||
|
forceKapt4()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun useGeneratedKotlinSourceK2(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun fallBackModeWithUseK2(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun fallBackModeWithLanguageVersion2_0(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't make sense in Kapt 4")
|
||||||
|
override fun testRepeatableAnnotationsWithOldJvmBackend(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Doesn't work in 2.0. Neither with Kapt 3 nor with Kapt 4")
|
||||||
|
override fun testMPPKaptPresence(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Currently failing. See KT-60950")
|
||||||
|
override fun kaptGenerateStubsShouldNotCaptureSourcesStateInConfigurationCache(gradleVersion: GradleVersion) {}
|
||||||
|
|
||||||
|
@Disabled("Currently failing. See KT-60951")
|
||||||
|
override fun testChangeClasspathICRebuild(gradleVersion: GradleVersion) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TestProject.forceKapt4() {
|
||||||
|
projectPath.walk().forEach {
|
||||||
|
when (it.fileName.name) {
|
||||||
|
"build.gradle" -> it.appendText(
|
||||||
|
"""
|
||||||
|
|
||||||
|
pluginManager.withPlugin('kotlin') {
|
||||||
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
||||||
|
compilerOptions.freeCompilerArgs.addAll(['-Xuse-kapt4', '-Xsuppress-version-warnings'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
"build.gradle.kts" -> it.appendText(
|
||||||
|
"""
|
||||||
|
|
||||||
|
pluginManager.withPlugin("kotlin") {
|
||||||
|
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile::class.java).configureEach {
|
||||||
|
compilerOptions.freeCompilerArgs.addAll(listOf("-Xuse-kapt4", "-Xsuppress-version-warnings"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -15,7 +15,7 @@ import kotlin.io.path.appendText
|
|||||||
|
|
||||||
@DisplayName("android with kapt3 external dependencies tests")
|
@DisplayName("android with kapt3 external dependencies tests")
|
||||||
@AndroidGradlePluginTests
|
@AndroidGradlePluginTests
|
||||||
class Kapt3AndroidExternalIT : Kapt3BaseIT() {
|
open class Kapt3AndroidExternalIT : Kapt3BaseIT() {
|
||||||
|
|
||||||
// Deprecated and doesn't work with Gradle 8 + AGP 8, so keeping max Gradle version as 7.6
|
// Deprecated and doesn't work with Gradle 8 + AGP 8, so keeping max Gradle version as 7.6
|
||||||
// For example: https://github.com/JakeWharton/butterknife/issues/1686
|
// For example: https://github.com/JakeWharton/butterknife/issues/1686
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ import kotlin.io.path.writeText
|
|||||||
|
|
||||||
@DisplayName("android with kapt3 tests")
|
@DisplayName("android with kapt3 tests")
|
||||||
@AndroidGradlePluginTests
|
@AndroidGradlePluginTests
|
||||||
class Kapt3AndroidIT : Kapt3BaseIT() {
|
open class Kapt3AndroidIT : Kapt3BaseIT() {
|
||||||
@DisplayName("KT-15001")
|
@DisplayName("KT-15001")
|
||||||
@GradleAndroidTest
|
@GradleAndroidTest
|
||||||
fun testKt15001(
|
fun testKt15001(
|
||||||
|
|||||||
+2
-2
@@ -78,7 +78,7 @@ open class Kapt3AndroidIncrementalIT : Kapt3BaseIT() {
|
|||||||
|
|
||||||
@DisplayName("incremental compilation works with dagger")
|
@DisplayName("incremental compilation works with dagger")
|
||||||
@GradleAndroidTest
|
@GradleAndroidTest
|
||||||
fun testAndroidDaggerIC(
|
open fun testAndroidDaggerIC(
|
||||||
gradleVersion: GradleVersion,
|
gradleVersion: GradleVersion,
|
||||||
agpVersion: String,
|
agpVersion: String,
|
||||||
jdkVersion: JdkVersions.ProvidedJdk,
|
jdkVersion: JdkVersions.ProvidedJdk,
|
||||||
@@ -205,6 +205,6 @@ open class Kapt3AndroidIncrementalIT : Kapt3BaseIT() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@DisplayName("android with kapt3 incremental build tests with precise compilation outputs backup")
|
@DisplayName("android with kapt3 incremental build tests with precise compilation outputs backup")
|
||||||
class Kapt3AndroidIncrementalWithPreciseBackupIT : Kapt3AndroidIncrementalIT() {
|
open class Kapt3AndroidIncrementalWithPreciseBackupIT : Kapt3AndroidIncrementalIT() {
|
||||||
override val defaultBuildOptions = super.defaultBuildOptions.copy(usePreciseOutputsBackup = true, keepIncrementalCompilationCachesInMemory = true)
|
override val defaultBuildOptions = super.defaultBuildOptions.copy(usePreciseOutputsBackup = true, keepIncrementalCompilationCachesInMemory = true)
|
||||||
}
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.gradle.android
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.forceKapt4
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.TestProject
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
|
||||||
|
@DisplayName("android with kapt4 external dependencies tests")
|
||||||
|
class Kapt4AndroidExternalIT : Kapt3AndroidExternalIT() {
|
||||||
|
override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
|
||||||
|
|
||||||
|
override fun TestProject.customizeProject() {
|
||||||
|
forceKapt4()
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.gradle.android
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.forceKapt4
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.TestProject
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
|
||||||
|
@DisplayName("android with kapt4 tests")
|
||||||
|
class Kapt4AndroidIT : Kapt3AndroidIT() {
|
||||||
|
override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
|
||||||
|
|
||||||
|
override fun TestProject.customizeProject() {
|
||||||
|
forceKapt4()
|
||||||
|
}
|
||||||
|
}
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.gradle.android
|
||||||
|
|
||||||
|
import org.gradle.util.GradleVersion
|
||||||
|
import org.jetbrains.kotlin.gradle.forceKapt4
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.JdkVersions
|
||||||
|
import org.jetbrains.kotlin.gradle.testbase.TestProject
|
||||||
|
import org.junit.jupiter.api.Disabled
|
||||||
|
import org.junit.jupiter.api.DisplayName
|
||||||
|
|
||||||
|
@DisplayName("android with kapt4 incremental build tests")
|
||||||
|
class Kapt4AndroidIncrementalIT : Kapt3AndroidIncrementalIT() {
|
||||||
|
override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
|
||||||
|
|
||||||
|
override fun TestProject.customizeProject() {
|
||||||
|
forceKapt4()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("See KT-61628")
|
||||||
|
override fun testAndroidDaggerIC(gradleVersion: GradleVersion, agpVersion: String, jdkVersion: JdkVersions.ProvidedJdk) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@DisplayName("android with kapt4 incremental build tests with precise compilation outputs backup")
|
||||||
|
class Kapt4AndroidIncrementalWithPreciseBackupIT : Kapt3AndroidIncrementalWithPreciseBackupIT() {
|
||||||
|
override val defaultBuildOptions = super.defaultBuildOptions.copyEnsuringK2()
|
||||||
|
|
||||||
|
override fun TestProject.customizeProject() {
|
||||||
|
forceKapt4()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("See KT-61628")
|
||||||
|
override fun testAndroidDaggerIC(gradleVersion: GradleVersion, agpVersion: String, jdkVersion: JdkVersions.ProvidedJdk) {}
|
||||||
|
}
|
||||||
+2
@@ -35,4 +35,6 @@ abstract class KGPBaseTest {
|
|||||||
|
|
||||||
@TempDir
|
@TempDir
|
||||||
lateinit var workingDir: Path
|
lateinit var workingDir: Path
|
||||||
|
|
||||||
|
internal open fun TestProject.customizeProject() {}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -82,6 +82,8 @@ fun KGPBaseTest.project(
|
|||||||
localRepoDir?.let { testProject.configureLocalRepository(localRepoDir) }
|
localRepoDir?.let { testProject.configureLocalRepository(localRepoDir) }
|
||||||
if (buildJdk != null) testProject.setupNonDefaultJdk(buildJdk)
|
if (buildJdk != null) testProject.setupNonDefaultJdk(buildJdk)
|
||||||
|
|
||||||
|
testProject.customizeProject()
|
||||||
|
|
||||||
val result = runCatching {
|
val result = runCatching {
|
||||||
testProject.test()
|
testProject.test()
|
||||||
}
|
}
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.jetbrains.kotlin.jvm'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
}
|
||||||
+77
@@ -0,0 +1,77 @@
|
|||||||
|
package processors
|
||||||
|
|
||||||
|
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("processors.Annotation1")
|
||||||
|
class AnnotationProcessor1 : AbstractProcessor() {
|
||||||
|
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
|
||||||
|
val elements = roundEnv.getElementsAnnotatedWith(Annotation1::class.java)
|
||||||
|
if (elements.isEmpty()) {
|
||||||
|
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "No elements for ${this::class.java.simpleName}")
|
||||||
|
}
|
||||||
|
for (element in elements) {
|
||||||
|
val generatedSimpleName = "${element.simpleName}1"
|
||||||
|
|
||||||
|
val file = processingEnv.filer.createSourceFile("generated.$generatedSimpleName")
|
||||||
|
|
||||||
|
file.openWriter().use {
|
||||||
|
it.write("package generated;\n@processors.Annotation2\npublic class $generatedSimpleName {}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
|
@SupportedAnnotationTypes("processors.Annotation2")
|
||||||
|
class AnnotationProcessor2 : AbstractProcessor() {
|
||||||
|
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
|
||||||
|
val elements = roundEnv.getElementsAnnotatedWith(Annotation2::class.java)
|
||||||
|
if (elements.isEmpty()) {
|
||||||
|
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "No elements for ${this::class.java.simpleName}")
|
||||||
|
}
|
||||||
|
for (element in elements) {
|
||||||
|
val generatedSimpleName = "${element.simpleName}2"
|
||||||
|
|
||||||
|
val file = processingEnv.filer.createSourceFile("generated.$generatedSimpleName")
|
||||||
|
|
||||||
|
file.openWriter().use {
|
||||||
|
it.write("package generated;\n@processors.Annotation3\npublic class $generatedSimpleName {}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SupportedSourceVersion(SourceVersion.RELEASE_8)
|
||||||
|
@SupportedAnnotationTypes("processors.Annotation3")
|
||||||
|
class AnnotationProcessor3 : AbstractProcessor() {
|
||||||
|
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
|
||||||
|
val elements = roundEnv.getElementsAnnotatedWith(Annotation3::class.java)
|
||||||
|
if (elements.isEmpty()) {
|
||||||
|
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "No elements for ${this::class.java.simpleName}")
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
plugins {
|
||||||
|
id 'org.jetbrains.kotlin.jvm'
|
||||||
|
id 'org.jetbrains.kotlin.kapt'
|
||||||
|
id 'idea'
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
|
||||||
|
implementation project(":annotation-processors")
|
||||||
|
kapt project(":annotation-processors")
|
||||||
|
|
||||||
|
testImplementation'junit:junit:4.13.2'
|
||||||
|
}
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
sourceDirs += files('build/generated/source/kapt/main', 'build/generated/source/kaptKotlin/main')
|
||||||
|
generatedSourceDirs += files('build/generated/source/kapt/main', 'build/generated/source/kaptKotlin/main')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kapt {
|
||||||
|
// The "reverse" order requires three passes
|
||||||
|
annotationProcessors("processors.AnnotationProcessor3", "processors.AnnotationProcessor2", "processors.AnnotationProcessor1")
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package example
|
||||||
|
|
||||||
|
import processors.Annotation1
|
||||||
|
|
||||||
|
@Annotation1
|
||||||
|
class TestClass
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package example
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.Assert.*
|
||||||
|
import generated.TestClass123
|
||||||
|
|
||||||
|
class AnnotationTest {
|
||||||
|
@Test fun testSimple() {
|
||||||
|
assertEquals("TestClass123", TestClass123::class.java.simpleName)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
include ':annotation-processors', ':example'
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.kapt.cli.test
|
||||||
|
|
||||||
|
abstract class AbstractKapt4ToolIntegrationTest : AbstractKaptToolIntegrationTest()
|
||||||
+3
-9
@@ -9,7 +9,6 @@ import com.intellij.openapi.util.SystemInfo
|
|||||||
import org.jetbrains.kotlin.cli.common.arguments.readArgumentsFromArgFile
|
import org.jetbrains.kotlin.cli.common.arguments.readArgumentsFromArgFile
|
||||||
import org.jetbrains.kotlin.test.services.JUnit5Assertions
|
import org.jetbrains.kotlin.test.services.JUnit5Assertions
|
||||||
import org.jetbrains.kotlin.test.util.KtTestUtil
|
import org.jetbrains.kotlin.test.util.KtTestUtil
|
||||||
import org.junit.jupiter.api.Assertions
|
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.TestInfo
|
import org.junit.jupiter.api.TestInfo
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -88,7 +87,7 @@ abstract class AbstractKaptToolIntegrationTest {
|
|||||||
|
|
||||||
private fun runJavac(args: List<String>) {
|
private fun runJavac(args: List<String>) {
|
||||||
val executableName = if (SystemInfo.isWindows) "javac.exe" else "javac"
|
val executableName = if (SystemInfo.isWindows) "javac.exe" else "javac"
|
||||||
val executablePath = File(getJdk8Home(), "bin/" + executableName).absolutePath
|
val executablePath = File(KtTestUtil.getJdk8Home(), "bin/" + executableName).absolutePath
|
||||||
runProcess(executablePath, args)
|
runProcess(executablePath, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +95,7 @@ abstract class AbstractKaptToolIntegrationTest {
|
|||||||
val outputFile = File(tmpdir, "javaOutput.txt")
|
val outputFile = File(tmpdir, "javaOutput.txt")
|
||||||
|
|
||||||
val executableName = if (SystemInfo.isWindows) "java.exe" else "java"
|
val executableName = if (SystemInfo.isWindows) "java.exe" else "java"
|
||||||
val executablePath = File(getJdk8Home(), "bin/" + executableName).absolutePath
|
val executablePath = File(KtTestUtil.getJdk8Home(), "bin/" + executableName).absolutePath
|
||||||
runProcess(executablePath, args, outputFile)
|
runProcess(executablePath, args, outputFile)
|
||||||
|
|
||||||
throw GotResult(outputFile.takeIf { it.isFile }?.readText() ?: "")
|
throw GotResult(outputFile.takeIf { it.isFile }?.readText() ?: "")
|
||||||
@@ -126,18 +125,13 @@ abstract class AbstractKaptToolIntegrationTest {
|
|||||||
private fun transformArguments(args: List<String>): List<String> {
|
private fun transformArguments(args: List<String>): List<String> {
|
||||||
return args.map {
|
return args.map {
|
||||||
val arg = it.replace("%KOTLIN_STDLIB%", File("dist/kotlinc/lib/kotlin-stdlib.jar").absolutePath)
|
val arg = it.replace("%KOTLIN_STDLIB%", File("dist/kotlinc/lib/kotlin-stdlib.jar").absolutePath)
|
||||||
if (SystemInfo.isWindows && (arg.contains("=") || arg.contains(":"))) {
|
if (SystemInfo.isWindows && (arg.contains("=") || arg.contains(":") || arg.contains(";"))) {
|
||||||
"\"" + arg + "\""
|
"\"" + arg + "\""
|
||||||
} else {
|
} else {
|
||||||
arg
|
arg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getJdk8Home(): File {
|
|
||||||
val homePath = System.getenv()["JDK_1_8"] ?: System.getenv()["JDK_18"] ?: error("Can't find JDK 1.8 home, please define JDK_1_8 variable")
|
|
||||||
return File(homePath)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val Section.args get() = readArgumentsFromArgFile(preprocessPathSeparators(content))
|
private val Section.args get() = readArgumentsFromArgFile(preprocessPathSeparators(content))
|
||||||
|
|||||||
@@ -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
|
||||||
+11
@@ -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.
|
||||||
+14
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
+31
@@ -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")
|
||||||
|
}
|
||||||
+44
@@ -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
|
||||||
+1
@@ -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
|
||||||
+19
@@ -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)
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
apt.SampleApt
|
||||||
+37
@@ -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")
|
||||||
|
}
|
||||||
+43
@@ -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
|
||||||
Vendored
+48
@@ -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)
|
||||||
|
}
|
||||||
+68
@@ -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
|
||||||
+67
@@ -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)
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
apt.SampleApt
|
||||||
@@ -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
|
||||||
@@ -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,38 @@
|
|||||||
|
# mkdir
|
||||||
|
output/ap
|
||||||
|
output/stubs
|
||||||
|
output/classes
|
||||||
|
output/javaClasses
|
||||||
|
output/sources
|
||||||
|
|
||||||
|
# kotlinc
|
||||||
|
-cp %KOTLIN_STDLIB%
|
||||||
|
-d output/ap
|
||||||
|
ap/processors.kt
|
||||||
|
|
||||||
|
# kapt
|
||||||
|
-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
|
||||||
|
|
||||||
|
# java
|
||||||
|
-cp output/classes:output/javaClasses:output/ap:%KOTLIN_STDLIB%
|
||||||
|
test.TestKt
|
||||||
|
|
||||||
|
# after
|
||||||
|
Generated class: generated.Test123
|
||||||
+92
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.kapt.cli.test;
|
||||||
|
|
||||||
|
import com.intellij.testFramework.TestDataPath;
|
||||||
|
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||||
|
import org.jetbrains.kotlin.test.TestMetadata;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("plugins/kapt3/kapt3-cli/testData/integration-kapt4")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Kapt4ToolIntegrationTestGenerated extends AbstractKapt4ToolIntegrationTest {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInIntegration_kapt4() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/kapt3/kapt3-cli/testData/integration-kapt4"), Pattern.compile("^([^\\.]+)$"), null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("argfile")
|
||||||
|
public void testArgfile() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/argfile/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("compileModeUnsupported")
|
||||||
|
public void testCompileModeUnsupported() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/compileModeUnsupported/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("correctErrorTypesOn")
|
||||||
|
public void testCorrectErrorTypesOn() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/correctErrorTypesOn/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("defaultPackage")
|
||||||
|
public void testDefaultPackage() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/defaultPackage/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kotlinFileGeneration")
|
||||||
|
public void testKotlinFileGeneration() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/kotlinFileGeneration/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kotlinFileGenerationDefaultOutput")
|
||||||
|
public void testKotlinFileGenerationDefaultOutput() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/kotlinFileGenerationDefaultOutput/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt33800")
|
||||||
|
public void testKt33800() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/kt33800/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipass")
|
||||||
|
public void testMultipass() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/multipass/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("separateStubAptCompilation")
|
||||||
|
public void testSeparateStubAptCompilation() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/separateStubAptCompilation/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simple")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/simple/");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("withoutService")
|
||||||
|
public void testWithoutService() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration-kapt4/withoutService/");
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -78,6 +78,12 @@ public class KaptToolIntegrationTestGenerated extends AbstractKaptToolIntegratio
|
|||||||
runTest("plugins/kapt3/kapt3-cli/testData/integration/kt33800/");
|
runTest("plugins/kapt3/kapt3-cli/testData/integration/kt33800/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("multipass")
|
||||||
|
public void testMultipass() throws Exception {
|
||||||
|
runTest("plugins/kapt3/kapt3-cli/testData/integration/multipass/");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("separateStubAptCompilation")
|
@TestMetadata("separateStubAptCompilation")
|
||||||
public void testSeparateStubAptCompilation() throws Exception {
|
public void testSeparateStubAptCompilation() throws Exception {
|
||||||
|
|||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2023 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 org.jetbrains.kotlin.kapt3
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.ProcessorLoader
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
|
import org.jetbrains.kotlin.util.ServiceLoaderLite
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
import javax.annotation.processing.Processor
|
||||||
|
|
||||||
|
class EfficientProcessorLoader(options: KaptOptions, logger: KaptLogger) : ProcessorLoader(options, logger) {
|
||||||
|
override fun doLoadProcessors(classpath: LinkedHashSet<File>, classLoader: ClassLoader): List<Processor> =
|
||||||
|
when (classLoader) {
|
||||||
|
is URLClassLoader -> ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
|
||||||
|
else -> super.doLoadProcessors(classpath, classLoader)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,11 +59,8 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||||
import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension
|
import org.jetbrains.kotlin.resolve.jvm.extensions.PartialAnalysisHandlerExtension
|
||||||
import org.jetbrains.kotlin.util.ServiceLoaderLite
|
|
||||||
import org.jetbrains.kotlin.utils.kapt.MemoryLeakDetector
|
import org.jetbrains.kotlin.utils.kapt.MemoryLeakDetector
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.net.URLClassLoader
|
|
||||||
import javax.annotation.processing.Processor
|
|
||||||
|
|
||||||
class ClasspathBasedKapt3Extension(
|
class ClasspathBasedKapt3Extension(
|
||||||
options: KaptOptions,
|
options: KaptOptions,
|
||||||
@@ -76,16 +73,8 @@ class ClasspathBasedKapt3Extension(
|
|||||||
private var processorLoader: ProcessorLoader? = null
|
private var processorLoader: ProcessorLoader? = null
|
||||||
|
|
||||||
override fun loadProcessors(): LoadedProcessors {
|
override fun loadProcessors(): LoadedProcessors {
|
||||||
val efficientProcessorLoader = object : ProcessorLoader(options, logger) {
|
this.processorLoader = EfficientProcessorLoader(options, logger)
|
||||||
override fun doLoadProcessors(classpath: LinkedHashSet<File>, classLoader: ClassLoader): List<Processor> =
|
return processorLoader!!.loadProcessors()
|
||||||
when (classLoader) {
|
|
||||||
is URLClassLoader -> ServiceLoaderLite.loadImplementations(Processor::class.java, classLoader)
|
|
||||||
else -> super.doLoadProcessors(classpath, classLoader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.processorLoader = efficientProcessorLoader
|
|
||||||
return efficientProcessorLoader.loadProcessors()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun analysisCompleted(
|
override fun analysisCompleted(
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ dependencies {
|
|||||||
compileOnly(project(":compiler:frontend.java"))
|
compileOnly(project(":compiler:frontend.java"))
|
||||||
compileOnly(project(":compiler:plugin-api"))
|
compileOnly(project(":compiler:plugin-api"))
|
||||||
implementation(project(":kotlin-annotation-processing-compiler"))
|
implementation(project(":kotlin-annotation-processing-compiler"))
|
||||||
|
compileOnly(project(":kotlin-annotation-processing-base"))
|
||||||
compileOnly(project(":analysis:analysis-api-standalone"))
|
compileOnly(project(":analysis:analysis-api-standalone"))
|
||||||
compileOnly(toolsJarApi())
|
compileOnly(toolsJarApi())
|
||||||
|
|
||||||
|
|||||||
-5
@@ -1,6 +1 @@
|
|||||||
#
|
|
||||||
# Copyright 2010-2023 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
org.jetbrains.kotlin.kapt4.Kapt4CompilerPluginRegistrar
|
org.jetbrains.kotlin.kapt4.Kapt4CompilerPluginRegistrar
|
||||||
|
|||||||
@@ -5,19 +5,171 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.kapt4
|
package org.jetbrains.kotlin.kapt4
|
||||||
|
|
||||||
|
import com.sun.tools.javac.tree.JCTree
|
||||||
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisApiInternals
|
||||||
|
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeTokenProvider
|
||||||
|
import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider
|
||||||
|
import org.jetbrains.kotlin.analysis.api.standalone.KtAlwaysAccessibleLifetimeTokenProvider
|
||||||
|
import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
|
||||||
|
import org.jetbrains.kotlin.base.kapt3.*
|
||||||
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot
|
||||||
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
|
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys.USE_FIR
|
||||||
import org.jetbrains.kotlin.fir.extensions.FirAnalysisHandlerExtension
|
import org.jetbrains.kotlin.fir.extensions.FirAnalysisHandlerExtension
|
||||||
|
import org.jetbrains.kotlin.kapt3.EfficientProcessorLoader
|
||||||
import org.jetbrains.kotlin.kapt3.KAPT_OPTIONS
|
import org.jetbrains.kotlin.kapt3.KAPT_OPTIONS
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.Kapt
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.doAnnotationProcessing
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
|
import org.jetbrains.kotlin.kapt3.base.util.getPackageNameJava9Aware
|
||||||
|
import org.jetbrains.kotlin.kapt3.util.MessageCollectorBackedKaptLogger
|
||||||
|
import org.jetbrains.kotlin.kapt3.util.prettyPrint
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
private class Kapt4AnalysisHandlerExtension : FirAnalysisHandlerExtension() {
|
||||||
class Kapt4AnalysisHandlerExtension : FirAnalysisHandlerExtension() {
|
|
||||||
override fun isApplicable(configuration: CompilerConfiguration): Boolean =
|
override fun isApplicable(configuration: CompilerConfiguration): Boolean =
|
||||||
configuration.getBoolean(CommonConfigurationKeys.USE_FIR) && configuration[KAPT_OPTIONS] != null
|
configuration.getBoolean(USE_FIR) && configuration[KAPT_OPTIONS] != null
|
||||||
|
|
||||||
|
@OptIn(KtAnalysisApiInternals::class)
|
||||||
override fun doAnalysis(configuration: CompilerConfiguration): Boolean {
|
override fun doAnalysis(configuration: CompilerConfiguration): Boolean {
|
||||||
TODO("Not yet implemented")
|
val optionsBuilder = configuration[KAPT_OPTIONS]!!
|
||||||
|
val logger = MessageCollectorBackedKaptLogger(
|
||||||
|
KaptFlag.VERBOSE in optionsBuilder.flags,
|
||||||
|
KaptFlag.INFO_AS_WARNINGS in optionsBuilder.flags,
|
||||||
|
configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)!!
|
||||||
|
)
|
||||||
|
|
||||||
|
if (optionsBuilder.mode == AptMode.WITH_COMPILATION) {
|
||||||
|
logger.error("KAPT \"compile\" mode is not supported in Kotlin 2.x. Run kapt with -Kapt-mode=stubsAndApt and use kotlinc for the final compilation step.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val oldLanguageVersionSettings = configuration.languageVersionSettings
|
||||||
|
val updatedConfiguration = configuration.copy().apply {
|
||||||
|
languageVersionSettings = object : LanguageVersionSettings by oldLanguageVersionSettings {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override fun <T> getFlag(flag: AnalysisFlag<T>): T =
|
||||||
|
when (flag) {
|
||||||
|
JvmAnalysisFlags.generatePropertyAnnotationsMethods -> true as T
|
||||||
|
else -> oldLanguageVersionSettings.getFlag(flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val standaloneAnalysisAPISession =
|
||||||
|
buildStandaloneAnalysisAPISession(classLoader = Kapt4AnalysisHandlerExtension::class.java.classLoader) {
|
||||||
|
@Suppress("DEPRECATION") // TODO: KT-61319 Kapt: remove usages of deprecated buildKtModuleProviderByCompilerConfiguration
|
||||||
|
buildKtModuleProviderByCompilerConfiguration(updatedConfiguration)
|
||||||
|
|
||||||
|
registerProjectService(KtLifetimeTokenProvider::class.java, KtAlwaysAccessibleLifetimeTokenProvider())
|
||||||
|
}
|
||||||
|
|
||||||
|
val (module, psiFiles) = standaloneAnalysisAPISession.modulesWithFiles.entries.single()
|
||||||
|
|
||||||
|
optionsBuilder.apply {
|
||||||
|
projectBaseDir = projectBaseDir ?: module.project.basePath?.let(::File)
|
||||||
|
val contentRoots = configuration[CLIConfigurationKeys.CONTENT_ROOTS] ?: emptyList()
|
||||||
|
compileClasspath.addAll(contentRoots.filterIsInstance<JvmClasspathRoot>().map { it.file })
|
||||||
|
javaSourceRoots.addAll(contentRoots.filterIsInstance<JavaSourceRoot>().map { it.file })
|
||||||
|
classesOutputDir = classesOutputDir ?: configuration.get(JVMConfigurationKeys.OUTPUT_DIRECTORY)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!optionsBuilder.checkOptions(logger, configuration)) return false
|
||||||
|
val options = optionsBuilder.build()
|
||||||
|
if (options[KaptFlag.VERBOSE]) {
|
||||||
|
logger.info(options.logString())
|
||||||
|
}
|
||||||
|
|
||||||
|
var context: Kapt4ContextForStubGeneration? = null
|
||||||
|
return try {
|
||||||
|
KtAnalysisSessionProvider.getInstance(module.project).analyze(module) {
|
||||||
|
context = Kapt4ContextForStubGeneration(options, withJdk = false, logger, this, psiFiles.filterIsInstance<KtFile>())
|
||||||
|
|
||||||
|
if (options.mode.generateStubs)
|
||||||
|
generateStubs(context!!)
|
||||||
|
|
||||||
|
if (options.mode.runAnnotationProcessing)
|
||||||
|
runProcessors(context!!, options, logger)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.exception(e)
|
||||||
|
false
|
||||||
|
} finally {
|
||||||
|
context?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateStubs(context: Kapt4ContextForStubGeneration) {
|
||||||
|
val generator = with(context) { Kapt4StubGenerator() }
|
||||||
|
val stubs = generator.generateStubs().values.filterNotNull().toList()
|
||||||
|
for (kaptStub in stubs) {
|
||||||
|
val stub = kaptStub.file
|
||||||
|
val className = (stub.defs.first { it is JCTree.JCClassDecl } as JCTree.JCClassDecl).simpleName.toString()
|
||||||
|
|
||||||
|
val packageName = stub.getPackageNameJava9Aware()?.toString() ?: ""
|
||||||
|
val stubsOutputDir = context.options.stubsOutputDir
|
||||||
|
val packageDir = if (packageName.isEmpty()) stubsOutputDir else File(stubsOutputDir, packageName.replace('.', '/'))
|
||||||
|
packageDir.mkdirs()
|
||||||
|
|
||||||
|
val sourceFile = File(packageDir, "$className.java")
|
||||||
|
sourceFile.writeText(stub.prettyPrint(context.context))
|
||||||
|
|
||||||
|
kaptStub.writeMetadataIfNeeded(forSource = sourceFile)
|
||||||
|
}
|
||||||
|
File(context.options.stubsOutputDir, "error").apply { mkdirs() }.resolve("NonExistentClass.java")
|
||||||
|
.writeText("package error;\npublic class NonExistentClass {}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun runProcessors(
|
||||||
|
context: Kapt4ContextForStubGeneration,
|
||||||
|
options: KaptOptions,
|
||||||
|
logger: KaptLogger,
|
||||||
|
) {
|
||||||
|
val sources = options.collectJavaSourceFiles(context.sourcesToReprocess)
|
||||||
|
if (sources.isEmpty()) return
|
||||||
|
EfficientProcessorLoader(options, logger).use {
|
||||||
|
context.doAnnotationProcessing(sources, it.loadProcessors().processors)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun KaptOptions.Builder.checkOptions(logger: KaptLogger, configuration: CompilerConfiguration): Boolean {
|
||||||
|
if (classesOutputDir == null && configuration.get(JVMConfigurationKeys.OUTPUT_JAR) != null) {
|
||||||
|
logger.error("Kapt does not support specifying JAR file outputs. Please specify the classes output directory explicitly.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processingClasspath.isEmpty()) {
|
||||||
|
// Skip annotation processing if no annotation processors were provided
|
||||||
|
logger.info("No annotation processors provided. Skip KAPT processing.")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourcesOutputDir == null || classesOutputDir == null || stubsOutputDir == null) {
|
||||||
|
if (mode != AptMode.WITH_COMPILATION) {
|
||||||
|
val nonExistentOptionName = when {
|
||||||
|
sourcesOutputDir == null -> "Sources output directory"
|
||||||
|
classesOutputDir == null -> "Classes output directory"
|
||||||
|
stubsOutputDir == null -> "Stubs output directory"
|
||||||
|
else -> throw IllegalStateException()
|
||||||
|
}
|
||||||
|
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME)
|
||||||
|
?: configuration.get(JVMConfigurationKeys.MODULES).orEmpty().joinToString()
|
||||||
|
|
||||||
|
logger.warn("$nonExistentOptionName is not specified for $moduleName, skipping annotation processing")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Kapt.checkJavacComponentsAccess(logger)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,20 +9,33 @@ import com.sun.tools.javac.tree.TreeMaker
|
|||||||
import com.sun.tools.javac.util.Context
|
import com.sun.tools.javac.util.Context
|
||||||
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
import org.jetbrains.kotlin.analysis.api.KtAnalysisSession
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
|
import org.jetbrains.kotlin.asJava.findFacadeClass
|
||||||
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
import org.jetbrains.kotlin.kapt3.base.KaptContext
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.KaptLogger
|
||||||
|
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
internal class Kapt4ContextForStubGeneration(
|
internal class Kapt4ContextForStubGeneration(
|
||||||
options: KaptOptions,
|
options: KaptOptions,
|
||||||
withJdk: Boolean,
|
withJdk: Boolean,
|
||||||
logger: KaptLogger,
|
logger: KaptLogger,
|
||||||
val analysisSession: KtAnalysisSession,
|
val analysisSession: KtAnalysisSession,
|
||||||
val classes: Iterable<KtLightClass>
|
val files: List<KtFile>,
|
||||||
) : KaptContext(options, withJdk, logger) {
|
) : KaptContext(options, withJdk, logger) {
|
||||||
|
val classes: Iterable<KtLightClass> = buildSet {
|
||||||
|
files.flatMapTo(this) { file ->
|
||||||
|
file.children.filterIsInstance<KtClassOrObject>().mapNotNull {
|
||||||
|
it.toLightClass()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files.mapNotNullTo(this) { ktFile -> ktFile.findFacadeClass() }.distinct()
|
||||||
|
}
|
||||||
|
|
||||||
internal val treeMaker = TreeMaker.instance(context) as Kapt4TreeMaker
|
internal val treeMaker = TreeMaker.instance(context) as Kapt4TreeMaker
|
||||||
|
|
||||||
override fun preregisterTreeMaker(context: Context) {
|
override fun preregisterTreeMaker(context: Context) {
|
||||||
Kapt4TreeMaker.preRegister(context)
|
Kapt4TreeMaker.preRegister(context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,16 +13,12 @@ import org.jetbrains.kotlin.analysis.api.lifetime.KtReadActionConfinementLifetim
|
|||||||
import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider
|
import org.jetbrains.kotlin.analysis.api.session.KtAnalysisSessionProvider
|
||||||
import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
|
import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.findFacadeClass
|
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
|
||||||
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
import org.jetbrains.kotlin.base.kapt3.KaptOptions
|
||||||
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
|
import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoots
|
||||||
import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots
|
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.kapt3.base.util.WriterBackedKaptLogger
|
import org.jetbrains.kotlin.kapt3.base.util.WriterBackedKaptLogger
|
||||||
import org.jetbrains.kotlin.kapt3.test.KaptMessageCollectorProvider
|
import org.jetbrains.kotlin.kapt3.test.KaptMessageCollectorProvider
|
||||||
import org.jetbrains.kotlin.kapt3.test.kaptOptionsProvider
|
import org.jetbrains.kotlin.kapt3.test.kaptOptionsProvider
|
||||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.test.model.*
|
import org.jetbrains.kotlin.test.model.*
|
||||||
import org.jetbrains.kotlin.test.services.*
|
import org.jetbrains.kotlin.test.services.*
|
||||||
@@ -78,16 +74,6 @@ private fun run(
|
|||||||
buildKtModuleProviderByCompilerConfiguration(configuration)
|
buildKtModuleProviderByCompilerConfiguration(configuration)
|
||||||
}
|
}
|
||||||
val (module, psiFiles) = standaloneAnalysisAPISession.modulesWithFiles.entries.single()
|
val (module, psiFiles) = standaloneAnalysisAPISession.modulesWithFiles.entries.single()
|
||||||
val ktFiles = psiFiles.filterIsInstance<KtFile>()
|
|
||||||
|
|
||||||
val lightClasses = buildSet {
|
|
||||||
ktFiles.flatMapTo(this) { file ->
|
|
||||||
file.children.filterIsInstance<KtClassOrObject>().mapNotNull {
|
|
||||||
it.toLightClass()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ktFiles.mapNotNullTo(this) { ktFile -> ktFile.findFacadeClass() }.distinct()
|
|
||||||
}
|
|
||||||
|
|
||||||
return KtAnalysisSessionProvider.getInstance(module.project).analyze(module) {
|
return KtAnalysisSessionProvider.getInstance(module.project).analyze(module) {
|
||||||
val context = Kapt4ContextForStubGeneration(
|
val context = Kapt4ContextForStubGeneration(
|
||||||
@@ -95,7 +81,7 @@ private fun run(
|
|||||||
withJdk = false,
|
withJdk = false,
|
||||||
WriterBackedKaptLogger(isVerbose = false),
|
WriterBackedKaptLogger(isVerbose = false),
|
||||||
this@analyze,
|
this@analyze,
|
||||||
lightClasses
|
psiFiles.filterIsInstance<KtFile>()
|
||||||
)
|
)
|
||||||
val generator = with(context) { Kapt4StubGenerator() }
|
val generator = with(context) { Kapt4StubGenerator() }
|
||||||
context to generator.generateStubs()
|
context to generator.generateStubs()
|
||||||
@@ -111,4 +97,3 @@ internal data class Kapt4ContextBinaryArtifact(
|
|||||||
override val kind: BinaryKind<Kapt4ContextBinaryArtifact>
|
override val kind: BinaryKind<Kapt4ContextBinaryArtifact>
|
||||||
get() = Kind
|
get() = Kind
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -303,3 +303,19 @@
|
|||||||
|
|
||||||
# This class is needed for test framework
|
# This class is needed for test framework
|
||||||
-keep class com.intellij.openapi.util.text.StringUtil { *; }
|
-keep class com.intellij.openapi.util.text.StringUtil { *; }
|
||||||
|
|
||||||
|
|
||||||
|
# This is used from standalone analysis API, which is NOT a part of the compiler but is bundled into kotlin-annotation-processing.
|
||||||
|
-keepclassmembers class com.intellij.openapi.vfs.VirtualFileManager {
|
||||||
|
com.intellij.openapi.vfs.VirtualFile findFileByNioPath(java.nio.file.Path);
|
||||||
|
}
|
||||||
|
-keepclassmembers class com.intellij.openapi.application.Application {
|
||||||
|
void addApplicationListener(com.intellij.openapi.application.ApplicationListener, com.intellij.openapi.Disposable);
|
||||||
|
}
|
||||||
|
-keepclassmembers class com.intellij.openapi.extensions.ExtensionPointName {
|
||||||
|
java.util.List getExtensionList(com.intellij.openapi.extensions.AreaInstance);
|
||||||
|
}
|
||||||
|
-keepclassmembers class kotlinx.collections.immutable.ExtensionsKt {
|
||||||
|
kotlinx.collections.immutable.PersistentMap toPersistentHashMap(java.util.Map);
|
||||||
|
kotlinx.collections.immutable.PersistentSet persistentHashSetOf(java.lang.Object[]);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user