Kapt: add flag kapt.use.jvm.ir for enabling JVM IR support
#KT-49682
This commit is contained in:
@@ -85,11 +85,6 @@ public class JVMConfigurationKeys {
|
||||
public static final CompilerConfigurationKey<Boolean> IR =
|
||||
CompilerConfigurationKey.create("IR");
|
||||
|
||||
// Temporary option to make it possible to test kapt with JVM IR. As soon as all tests start to pass, it can be removed,
|
||||
// and the backend (old or IR) will be deduced from the compiler arguments provided by the user.
|
||||
public static final CompilerConfigurationKey<Boolean> USE_KAPT_WITH_JVM_IR =
|
||||
CompilerConfigurationKey.create("Enable JVM IR for kapt");
|
||||
|
||||
public static final CompilerConfigurationKey<Boolean> USE_PSI_CLASS_FILES_READING =
|
||||
CompilerConfigurationKey.create("use a slower (PSI-based) class files reading implementation");
|
||||
|
||||
|
||||
+1
-4
@@ -203,10 +203,7 @@ open class JvmIrCodegenFactory(
|
||||
// We need to compile all files we reference in Klibs
|
||||
irModuleFragment.files.addAll(dependencies.flatMap { it.files })
|
||||
|
||||
if (!input.configuration.getBoolean(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT) && !input.configuration.getBoolean(
|
||||
JVMConfigurationKeys.USE_KAPT_WITH_JVM_IR
|
||||
)
|
||||
) {
|
||||
if (!input.configuration.getBoolean(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT)) {
|
||||
val originalBindingContext = input.bindingContext as? CleanableBindingContext
|
||||
?: error("BindingContext should be cleanable in JVM IR to avoid leaking memory: ${input.bindingContext}")
|
||||
originalBindingContext.clear()
|
||||
|
||||
@@ -187,8 +187,7 @@ object GenerationUtils {
|
||||
configureGenerationState: GenerationState.Builder.() -> Unit = {},
|
||||
): GenerationState {
|
||||
val isIrBackend =
|
||||
(classBuilderFactory.classBuilderMode == ClassBuilderMode.FULL && configuration.getBoolean(JVMConfigurationKeys.IR)) ||
|
||||
configuration.getBoolean(JVMConfigurationKeys.USE_KAPT_WITH_JVM_IR)
|
||||
configuration.getBoolean(JVMConfigurationKeys.IR)
|
||||
val generationState = GenerationState.Builder(
|
||||
project, classBuilderFactory, analysisResult.moduleDescriptor, analysisResult.bindingContext,
|
||||
configuration
|
||||
|
||||
+8
-1
@@ -24,6 +24,7 @@ import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isInfoAsWarnings
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isKaptKeepKdocCommentsInStubs
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isKaptVerbose
|
||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isUseJvmIr
|
||||
import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
|
||||
@@ -119,6 +120,10 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
||||
return getBooleanOptionValue(BooleanOption.KAPT_KEEP_KDOC_COMMENTS_IN_STUBS)
|
||||
}
|
||||
|
||||
fun Project.isUseJvmIr(): Boolean {
|
||||
return getBooleanOptionValue(BooleanOption.KAPT_USE_JVM_IR)
|
||||
}
|
||||
|
||||
fun Project.classLoadersCacheSize(): Int = findPropertySafe(CLASSLOADERS_CACHE_SIZE)?.toString()?.toInt() ?: 0
|
||||
|
||||
fun Project.disableClassloaderCacheForProcessors(): Set<String> {
|
||||
@@ -219,7 +224,8 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
||||
),
|
||||
KAPT_INFO_AS_WARNINGS("kapt.info.as.warnings", false),
|
||||
KAPT_INCLUDE_COMPILE_CLASSPATH("kapt.include.compile.classpath", true),
|
||||
KAPT_KEEP_KDOC_COMMENTS_IN_STUBS("kapt.keep.kdoc.comments.in.stubs", true)
|
||||
KAPT_KEEP_KDOC_COMMENTS_IN_STUBS("kapt.keep.kdoc.comments.in.stubs", true),
|
||||
KAPT_USE_JVM_IR("kapt.use.jvm.ir", false),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -573,6 +579,7 @@ internal fun buildKaptSubpluginOptions(
|
||||
pluginOptions += SubpluginOption("keepKdocCommentsInStubs", "${project.isKaptKeepKdocCommentsInStubs()}")
|
||||
pluginOptions += SubpluginOption("showProcessorTimings", "${kaptExtension.showProcessorStats}")
|
||||
pluginOptions += SubpluginOption("detectMemoryLeaks", kaptExtension.detectMemoryLeaks)
|
||||
pluginOptions += SubpluginOption("useJvmIr", "${project.isUseJvmIr()}")
|
||||
pluginOptions += SubpluginOption("infoAsWarnings", "${project.isInfoAsWarnings()}")
|
||||
pluginOptions += FilesSubpluginOption("stubs", kaptStubsDir)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
+1
-19
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -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,
|
||||
|
||||
+29
-1
@@ -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) {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user