Kapt: add flag kapt.use.jvm.ir for enabling JVM IR support

#KT-49682
This commit is contained in:
Alexander Udalov
2022-05-31 14:39:44 +02:00
parent 65c7a7f939
commit 7e9d7c895a
13 changed files with 133 additions and 44 deletions
@@ -126,6 +126,7 @@ enum class KaptFlag(val description: String, val defaultValue: Boolean = false)
INCREMENTAL_APT("Incremental annotation processing (apt mode)"),
STRIP_METADATA("Strip @Metadata annotations from stubs"),
KEEP_KDOC_COMMENTS_IN_STUBS("Keep KDoc comments in stubs", defaultValue = true),
USE_JVM_IR("Use JVM IR backend")
;
}
@@ -207,6 +207,13 @@ enum class KaptCliOption(
"Keep KDoc comments in stubs"
),
USE_JVM_IR(
"useJvmIr",
"true | false",
"Use JVM IR backend",
cliToolOption = CliToolOption("-Kapt-use-jvm-ir", FLAG)
),
DETECT_MEMORY_LEAKS_OPTION("detectMemoryLeaks", "true | false", "Detect memory leaks in annotation processors"),
INCLUDE_COMPILE_CLASSPATH(
"includeCompileClasspath",
@@ -262,19 +262,18 @@ abstract class AbstractKapt3Extension(
): KaptContextForStubGeneration {
val builderFactory = OriginCollectingClassBuilderFactory(ClassBuilderMode.KAPT3)
val configuration = compilerConfiguration.copy().apply {
put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, true)
}
val targetId = TargetId(
name = compilerConfiguration[CommonConfigurationKeys.MODULE_NAME] ?: module.name.asString(),
name = configuration[CommonConfigurationKeys.MODULE_NAME] ?: module.name.asString(),
type = "java-production"
)
val isIrBackend = compilerConfiguration.getBoolean(JVMConfigurationKeys.USE_KAPT_WITH_JVM_IR)
val generationState = GenerationState.Builder(
project,
builderFactory,
module,
bindingContext,
compilerConfiguration
).targetId(targetId)
val isIrBackend = options.flags[KaptFlag.USE_JVM_IR]
val generationState = GenerationState.Builder(project, builderFactory, module, bindingContext, configuration)
.targetId(targetId)
.isIrBackend(isIrBackend)
.build()
@@ -283,7 +282,7 @@ abstract class AbstractKapt3Extension(
files,
generationState,
if (isIrBackend)
JvmIrCodegenFactory(compilerConfiguration, compilerConfiguration.get(CLIConfigurationKeys.PHASE_CONFIG))
JvmIrCodegenFactory(configuration, configuration[CLIConfigurationKeys.PHASE_CONFIG])
else DefaultCodegenFactory
)
}
@@ -127,6 +127,8 @@ class Kapt3CommandLineProcessor : CommandLineProcessor {
STRICT_MODE_OPTION -> setFlag(KaptFlag.STRICT, value)
STRIP_METADATA_OPTION -> setFlag(KaptFlag.STRIP_METADATA, value)
KEEP_KDOC_COMMENTS_IN_STUBS -> setFlag(KaptFlag.KEEP_KDOC_COMMENTS_IN_STUBS, value)
USE_JVM_IR -> setFlag(KaptFlag.USE_JVM_IR, value)
SHOW_PROCESSOR_STATS -> setFlag(KaptFlag.SHOW_PROCESSOR_STATS, value)
DUMP_PROCESSOR_STATS -> processorsStatsReportFile = File(value)
INCLUDE_COMPILE_CLASSPATH -> setFlag(KaptFlag.INCLUDE_COMPILE_CLASSPATH, value)
@@ -176,7 +176,7 @@ abstract class AbstractKotlinKapt3IntegrationTest : KotlinKapt3TestBase() {
.trimTrailingWhitespacesAndAddNewlineAtEOF()
.let { AbstractClassFileToSourceStubConverterTest.removeMetadataAnnotationContents(it) }
KotlinTestUtils.assertEqualsToFile(txtFile, actual)
checkTxtAccordingToBackend(txtFile, actual)
} finally {
options.sourcesOutputDir.deleteRecursively()
options.incrementalDataOutputDir?.deleteRecursively()
@@ -37,8 +37,6 @@ import org.jetbrains.kotlin.codegen.ClassBuilderMode
import org.jetbrains.kotlin.codegen.CodegenTestFiles
import org.jetbrains.kotlin.codegen.GenerationUtils
import org.jetbrains.kotlin.codegen.OriginCollectingClassBuilderFactory
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
import org.jetbrains.kotlin.kapt.base.test.JavaKaptContextTest
import org.jetbrains.kotlin.kapt3.Kapt3ComponentRegistrar.KaptComponentContributor
@@ -170,14 +168,6 @@ abstract class AbstractKotlinKapt3Test : KotlinKapt3TestBase() {
}
}
override fun updateConfiguration(configuration: CompilerConfiguration) {
super.updateConfiguration(configuration)
if (backend.isIR) {
configuration.put(JVMConfigurationKeys.USE_KAPT_WITH_JVM_IR, true)
}
}
protected fun convert(
kaptContext: KaptContextForStubGeneration,
javaFiles: List<File>,
@@ -333,15 +323,7 @@ open class AbstractClassFileToSourceStubConverterTest : AbstractKotlinKapt3Test(
}
}
val irTxtFile = File(txtFile.parentFile, txtFile.nameWithoutExtension + "_ir.txt")
val expectedFile =
if (backend.isIR && irTxtFile.exists()) irTxtFile
else txtFile
KotlinTestUtils.assertEqualsToFile(expectedFile, actual)
if (backend.isIR && txtFile.exists() && irTxtFile.exists() && txtFile.readText() == irTxtFile.readText()) {
fail("JVM and JVM_IR golden files are identical. Remove $irTxtFile.")
}
checkTxtAccordingToBackend(txtFile, actual)
}
}
@@ -10,7 +10,6 @@ import javax.annotation.processing.ProcessingEnvironment
import javax.annotation.processing.RoundEnvironment
import javax.lang.model.element.TypeElement
// For now, just run one simple test to make sure Kapt launches at all with IR switched on.
class IrKotlinKapt3IntegrationTests : AbstractIrKotlinKapt3IntegrationTest(), CustomJdkTestLauncher {
override fun test(
name: String,
@@ -7,6 +7,9 @@ package org.jetbrains.kotlin.kapt3.test
import org.jetbrains.kotlin.base.kapt3.KaptFlag
import org.jetbrains.kotlin.codegen.CodegenTestCase
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File
@@ -48,6 +51,27 @@ abstract class KotlinKapt3TestBase : CodegenTestCase() {
return KtTestUtil.tmpDir(name).also(directoriesToCleanup::add)
}
protected fun checkTxtAccordingToBackend(txtFile: File, actual: String) {
val irTxtFile = File(txtFile.parentFile, txtFile.nameWithoutExtension + "_ir.txt")
val expectedFile =
if (backend.isIR && irTxtFile.exists()) irTxtFile
else txtFile
KotlinTestUtils.assertEqualsToFile(expectedFile, actual)
if (backend.isIR && txtFile.exists() && irTxtFile.exists() && txtFile.readText() == irTxtFile.readText()) {
fail("JVM and JVM_IR golden files are identical. Remove $irTxtFile.")
}
}
override fun updateConfiguration(configuration: CompilerConfiguration) {
super.updateConfiguration(configuration)
if (backend.isIR) {
configuration.put(JVMConfigurationKeys.IR, true)
configuration.put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, true)
}
}
override fun doTest(filePath: String) {
val testFile = File(filePath)
@@ -57,6 +81,10 @@ abstract class KotlinKapt3TestBase : CodegenTestCase() {
addOrRemoveFlag(KaptFlag.STRICT, testFile)
addOrRemoveFlag(KaptFlag.DUMP_DEFAULT_PARAMETER_VALUES, testFile)
if (backend.isIR) {
kaptFlagsToAdd.add(KaptFlag.USE_JVM_IR)
}
super.doTest(filePath)
}
}
}
@@ -0,0 +1,73 @@
package error;
public final class NonExistentClass {
}
////////////////////
package test;
import java.lang.System;
/**
* KDoc comment.
*/
@kotlin.Suppress(names = {"UNRESOLVED_REFERENCE"})
@kotlin.Metadata()
public final class Simple {
public Simple() {
super();
}
@MyAnnotation()
public final void myMethod() {
}
public final int heavyMethod() {
return 0;
}
}
////////////////////
package test;
import java.lang.System;
@kotlin.Metadata()
public enum EnumClass {
/*public static final*/ BLACK /* = new BLACK() */,
/*public static final*/ WHITE /* = new WHITE() */;
EnumClass() {
}
}
////////////////////
package test;
import java.lang.System;
@kotlin.Metadata()
@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
public abstract @interface MyAnnotation {
}
////////////////////
package test;
import java.lang.System;
@kotlin.Metadata()
public enum EnumClass2 {
/*public static final*/ WHITE /* = new WHITE(null) */,
/*public static final*/ RED /* = new RED(null) */;
@org.jetbrains.annotations.NotNull()
private final java.lang.String blah = null;
EnumClass2(java.lang.String blah) {
}
}