From f05c72d48f46d43f0a1197db29180b0c7c9b89be Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Wed, 16 Feb 2022 10:37:48 +0100 Subject: [PATCH] KAPT+IR: Properly process annotations and backing field annotations --- .../ir/descriptors/IrBasedDescriptors.kt | 2 +- .../ir/expressions/IrConstructorCall.kt | 3 + .../expressions/impl/IrConstructorCallImpl.kt | 2 + .../kotlin/ir/util/ConstantValueGenerator.kt | 3 +- .../stubs/ClassFileToSourceStubConverter.kt | 6 +- .../kapt3/test/AbstractIrKotlinKapt3Test.kt | 12 + .../converter/annotationWithFqNames.kt | 1 - .../converter/annotationsWithConstants.kt | 1 - .../converter/annotationsWithConstants_ir.txt | 383 ++++++++++++++++++ .../testData/converter/enumImports.kt | 1 - .../testData/converter/enumInCompanion_ir.txt | 4 +- .../converter/importsForErrorTypes.kt | 1 - .../testData/converter/primitiveTypes.kt | 2 - .../testData/converter/primitiveTypes_ir.txt | 77 ++++ 14 files changed, 486 insertions(+), 12 deletions(-) create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants_ir.txt create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes_ir.txt diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt index d249723a9b2..01843624f97 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBasedDescriptors.kt @@ -52,7 +52,7 @@ abstract class IrBasedDeclarationDescriptor(val owner: T) : D symbol.owner.valueParameters.map { it.name to getValueArgument(it.index) } .filter { it.second != null } .associate { it.first to it.second!!.toConstantValue() }, - /*TODO*/ SourceElement.NO_SOURCE + source ) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstructorCall.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstructorCall.kt index fe21a5018af..9437d58e9d5 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstructorCall.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstructorCall.kt @@ -5,12 +5,15 @@ package org.jetbrains.kotlin.ir.expressions +import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.visitors.IrElementVisitor abstract class IrConstructorCall : IrFunctionAccessExpression() { abstract override val symbol: IrConstructorSymbol + abstract val source: SourceElement + abstract val constructorTypeArgumentsCount: Int override fun accept(visitor: IrElementVisitor, data: D): R = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstructorCallImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstructorCallImpl.kt index 9d2265caac3..911db07fa47 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstructorCallImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrConstructorCallImpl.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.ir.expressions.impl +import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.expressions.IrConstructorCall @@ -23,6 +24,7 @@ class IrConstructorCallImpl( override val constructorTypeArgumentsCount: Int, valueArgumentsCount: Int, override val origin: IrStatementOrigin? = null, + override val source: SourceElement = SourceElement.NO_SOURCE ) : IrConstructorCall() { override val typeArgumentsByIndex: Array = arrayOfNulls(typeArgumentsCount) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt index b97d304d98d..cc9269a7bb7 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/ConstantValueGenerator.kt @@ -170,7 +170,8 @@ abstract class ConstantValueGenerator( primaryConstructorSymbol, valueArgumentsCount = primaryConstructorDescriptor.valueParameters.size, typeArgumentsCount = annotationClassDescriptor.declaredTypeParameters.size, - constructorTypeArgumentsCount = 0 + constructorTypeArgumentsCount = 0, + source = annotationDescriptor.source ) val substitutor = TypeConstructorSubstitution.create(annotationType).buildSubstitutor() diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 1be0a47b2f8..f7d06fe8b9e 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -120,6 +120,8 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati private val mutableBindings = mutableMapOf() + private val isIrBackend = kaptContext.generationState.isIrBackend + val bindings: Map get() = mutableBindings @@ -691,8 +693,8 @@ class ClassFileToSourceStubConverter(val kaptContext: KaptContextForStubGenerati val origin = kaptContext.origins[field] val descriptor = origin?.descriptor - val fieldAnnotations = when (descriptor) { - is PropertyDescriptor -> descriptor.backingField?.annotations + val fieldAnnotations = when { + !isIrBackend && descriptor is PropertyDescriptor -> descriptor.backingField?.annotations else -> descriptor?.annotations } ?: Annotations.EMPTY diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractIrKotlinKapt3Test.kt b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractIrKotlinKapt3Test.kt index cf0adfe1cc5..6d1ce907e77 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractIrKotlinKapt3Test.kt +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/AbstractIrKotlinKapt3Test.kt @@ -5,12 +5,24 @@ package org.jetbrains.kotlin.kapt3.test +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.test.TargetBackend open class AbstractIrClassFileToSourceStubConverterTest : AbstractClassFileToSourceStubConverterTest() { override val backend = TargetBackend.JVM_IR + + override fun updateConfiguration(configuration: CompilerConfiguration) { + configuration.put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, true) + super.updateConfiguration(configuration) + } } abstract class AbstractIrKotlinKaptContextTest : AbstractKotlinKaptContextTest() { override val backend = TargetBackend.JVM_IR + + override fun updateConfiguration(configuration: CompilerConfiguration) { + configuration.put(JVMConfigurationKeys.DO_NOT_CLEAR_BINDING_CONTEXT, true) + super.updateConfiguration(configuration) + } } diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/annotationWithFqNames.kt b/plugins/kapt3/kapt3-compiler/testData/converter/annotationWithFqNames.kt index 505620b9b33..bfaf705e6d9 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/annotationWithFqNames.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/annotationWithFqNames.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // CORRECT_ERROR_TYPES // NO_VALIDATION diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants.kt b/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants.kt index ae757e37aec..c51f0edc5cd 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR //FILE: lib/R.java package lib; diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants_ir.txt b/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants_ir.txt new file mode 100644 index 00000000000..e07aa0130d7 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/annotationsWithConstants_ir.txt @@ -0,0 +1,383 @@ +package app; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +public abstract @interface Anno { + + public abstract boolean a1(); + + public abstract byte a2(); + + public abstract int a3(); + + public abstract short a4(); + + public abstract long a5(); + + public abstract char a6(); + + public abstract float a7(); + + public abstract double a8(); + + public abstract java.lang.String a9(); +} + +//////////////////// + +package app; + +public class B { + + public B() { + super(); + } + + public static class id { + + public id() { + super(); + } + public static final int textView = 200; + } + public static final boolean a1 = false; + public static final byte a2 = 1; + public static final int a3 = 2; + public static final short a4 = 3; + public static final long a5 = 4L; + public static final char a6 = '5'; + public static final float a7 = 6.0F; + public static final double a8 = 7.0; + public static final String a9 = "A"; +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +public abstract @interface Bind { + + public abstract int id(); +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Target(value = {java.lang.annotation.ElementType.FIELD}) +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +@kotlin.annotation.Target(allowedTargets = {kotlin.annotation.AnnotationTarget.FIELD}) +public abstract @interface BindField { + + public abstract int id(); +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +public final class JJ { + @org.jetbrains.annotations.NotNull() + private static final java.lang.String b = null; + @org.jetbrains.annotations.NotNull() + public static final app.JJ INSTANCE = null; + + private JJ() { + super(); + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String getB() { + return null; + } + + @org.jetbrains.annotations.NotNull() + public final java.lang.String c() { + return null; + } +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +public abstract @interface MultiValue { + + public abstract int[] ids(); +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +public abstract @interface MultiValueByte { + + public abstract byte[] ids(); +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +@java.lang.annotation.Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +public abstract @interface MultiValueString { + + public abstract java.lang.String[] ids(); +} + +//////////////////// + +package app; + +import java.lang.System; + +@kotlin.Metadata() +public final class MyActivity { + @BindField(id = lib.R.id.textView) + private final int a = 0; + @BindField(id = lib.R.id.textView) + private final int b = 0; + @BindField(id = app.R.layout.mainActivity) + private final int c = 0; + @BindField(id = app.R.layout.mainActivity) + private final int d = 0; + @BindField(id = app.R2.layout.mainActivity) + private final int e = 0; + @BindField(id = app.B.id.textView) + private final int f = 0; + public final int propA = app.B.id.textView; + private final int propB = app.B.id.textView; + private int propC = app.B.id.textView; + @kotlin.jvm.JvmField() + public final int propD = app.B.id.textView; + @kotlin.jvm.JvmField() + public int propE = app.B.id.textView; + private final int propF = 0; + + public MyActivity() { + super(); + } + + public final int getA() { + return 0; + } + + public final int getB() { + return 0; + } + + public final int getC() { + return 0; + } + + public final int getD() { + return 0; + } + + public final int getE() { + return 0; + } + + public final int getF() { + return 0; + } + + @Bind(id = lib.R.id.textView) + public final void foo() { + } + + @Bind(id = lib.R.id.textView) + public final void foo2() { + } + + @Bind(id = app.R.layout.mainActivity) + public final void foo3() { + } + + @Bind(id = app.R.layout.mainActivity) + public final void foo4() { + } + + @Anno(a1 = app.B.a1, a2 = app.B.a2, a3 = app.B.a3, a4 = app.B.a4, a5 = app.B.a5, a6 = app.B.a6, a7 = app.B.a7, a8 = app.B.a8, a9 = "A") + @Bind(id = app.R2.layout.mainActivity) + public final void foo5() { + } + + @Bind(id = app.B.id.textView) + public final void plainIntConstant() { + } + + @MultiValue(ids = {}) + public final void multi0() { + } + + @MultiValue(ids = {app.B.id.textView}) + public final void multi1() { + } + + @MultiValue(ids = {app.B.id.textView, app.B.a3}) + public final void multi2() { + } + + @MultiValue(ids = {app.B.id.textView, app.B.a3}) + public final void multi3() { + } + + @MultiValueString(ids = {"A"}) + public final void multi4() { + } + + @MultiValueByte(ids = {app.B.a2}) + public final void multi5() { + } + + @lib.OnClick(value = {app.B.id.textView}) + public final void multiJava1() { + } + + @lib.OnClick(value = {app.B.id.textView, app.R.layout.mainActivity}) + public final void multiJava2() { + } + + public final int getPropB() { + return 0; + } + + public final int getPropC() { + return 0; + } + + public final void setPropC(int p0) { + } + + public final int getPropF() { + return 0; + } + + @Bind(id = lib.R.id.textView) + @java.lang.Deprecated() + public static void getA$annotations() { + } + + @Bind(id = lib.R.id.textView) + @java.lang.Deprecated() + public static void getB$annotations() { + } + + @Bind(id = app.R.layout.mainActivity) + @java.lang.Deprecated() + public static void getC$annotations() { + } + + @Bind(id = app.R.layout.mainActivity) + @java.lang.Deprecated() + public static void getD$annotations() { + } + + @Anno(a1 = app.B.a1, a2 = app.B.a2, a3 = app.B.a3, a4 = app.B.a4, a5 = app.B.a5, a6 = app.B.a6, a7 = app.B.a7, a8 = app.B.a8, a9 = "A") + @Bind(id = app.R2.layout.mainActivity) + @java.lang.Deprecated() + public static void getE$annotations() { + } + + @Bind(id = app.B.id.textView) + @java.lang.Deprecated() + public static void getF$annotations() { + } +} + +//////////////////// + +package app; + +public class R { + + public R() { + super(); + } + + public static class layout { + + public layout() { + super(); + } + public static final int mainActivity = 100; + } +} + +//////////////////// + +package app; + +public class R2 { + + public R2() { + super(); + } + + public static class layout { + + public layout() { + super(); + } + public static final int mainActivity = 100; + } +} + +//////////////////// + +package lib; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(value = ElementType.METHOD) +@Retention(value = RetentionPolicy.RUNTIME) +public @interface OnClick { + + int[] value() default {}; +} + +//////////////////// + +package lib; + +public class R { + + public R() { + super(); + } + + public static class id { + + public id() { + super(); + } + public static final int textView = 100; + } +} diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/enumImports.kt b/plugins/kapt3/kapt3-compiler/testData/converter/enumImports.kt index 3c6c50bf393..92fc140947f 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/enumImports.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/enumImports.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // CORRECT_ERROR_TYPES package kapt diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/enumInCompanion_ir.txt b/plugins/kapt3/kapt3-compiler/testData/converter/enumInCompanion_ir.txt index 7ec0e2619d9..75234eb51d4 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/enumInCompanion_ir.txt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/enumInCompanion_ir.txt @@ -69,7 +69,7 @@ import java.lang.System; @kotlin.Metadata() public final class Test3 { @org.jetbrains.annotations.NotNull() - private final Test3.Amigo.Example foo = null; + private final Test3.Amigo.Example foo = Test3.Amigo.Example.FOO; public Test3() { super(); @@ -101,7 +101,7 @@ import java.lang.System; @kotlin.Metadata() public final class Test4 { - private final int foo = 0; + private final int foo = 1; @org.jetbrains.annotations.NotNull() public static final Test4.Companion Companion = null; diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/importsForErrorTypes.kt b/plugins/kapt3/kapt3-compiler/testData/converter/importsForErrorTypes.kt index 74abdbf08ca..db85c971ee8 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/importsForErrorTypes.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/importsForErrorTypes.kt @@ -1,4 +1,3 @@ -// IGNORE_BACKEND: JVM_IR // CORRECT_ERROR_TYPES import java.util.concurrent.* diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes.kt b/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes.kt index 0840bdde4ee..f6db55e43b5 100644 --- a/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes.kt +++ b/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes.kt @@ -1,5 +1,3 @@ -// IGNORE_BACKEND: JVM_IR - object PrimitiveTypes { const val booleanFalse: Boolean = false const val booleanTrue: Boolean = true diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes_ir.txt b/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes_ir.txt new file mode 100644 index 00000000000..6e0f842cd8c --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/primitiveTypes_ir.txt @@ -0,0 +1,77 @@ +import java.lang.System; + +@kotlin.Metadata() +public final class PrimitiveTypes { + public static final boolean booleanFalse = false; + public static final boolean booleanTrue = true; + public static final int int0 = 0; + public static final int intMinus1000 = -1000; + public static final int intMinValue = -2147483648; + public static final int intMaxValue = 2147483647; + public static final int intHex = -1; + public static final byte byte0 = (byte)0; + public static final byte byte50 = (byte)50; + public static final short short5 = (short)5; + public static final char charC = 'C'; + public static final char char0 = '\u0000'; + public static final char char10 = '\n'; + public static final char char13 = '\r'; + public static final long long0 = 0L; + public static final long longMaxValue = 9223372036854775807L; + public static final long longMinValue = -9223372036854775808L; + public static final long longHex = 4294967295L; + public static final float float54 = 5.4F; + private static final float floatMaxValue = 3.4028235E38F; + private static final float floatNan = 0.0F / 0.0F; + private static final float floatPositiveInfinity = 1.0F / 0.0F; + private static final float floatNegativeInfinity = -1.0F / 0.0F; + public static final double double54 = 5.4; + private static final double doubleMaxValue = 1.7976931348623157E308; + private static final double doubleNan = 0.0 / 0.0; + private static final double doublePositiveInfinity = 1.0 / 0.0; + private static final double doubleNegativeInfinity = -1.0 / 0.0; + @org.jetbrains.annotations.NotNull() + public static final java.lang.String stringHelloWorld = "Hello, world!"; + @org.jetbrains.annotations.NotNull() + public static final java.lang.String stringQuotes = "quotes \" \'\'quotes"; + @org.jetbrains.annotations.NotNull() + public static final java.lang.String stringRN = "\r\n"; + @org.jetbrains.annotations.NotNull() + public static final PrimitiveTypes INSTANCE = null; + + private PrimitiveTypes() { + super(); + } + + public final float getFloatMaxValue() { + return 0.0F; + } + + public final float getFloatNan() { + return 0.0F; + } + + public final float getFloatPositiveInfinity() { + return 0.0F; + } + + public final float getFloatNegativeInfinity() { + return 0.0F; + } + + public final double getDoubleMaxValue() { + return 0.0; + } + + public final double getDoubleNan() { + return 0.0; + } + + public final double getDoublePositiveInfinity() { + return 0.0; + } + + public final double getDoubleNegativeInfinity() { + return 0.0; + } +}