Support instantiation of Java annotations with defaults
For annotations defined in Java, IrProperties do not contain initializers in backing fields, as annotation properties are represented as Java methods. Therefore, it is not possible to use initializer values as default values for constructor parameters. However, K2 stores default values in annotation's constructor parameters, so it is possible to fix this issue if they're properly transfered to the IR and inspected in JvmAnnotationImplementationTransformer #KT-47702 Fixed #KT-47702 tag fixed-in-k2
This commit is contained in:
committed by
Space Team
parent
cc2bc5e8b1
commit
7f795f212f
@@ -795,3 +795,13 @@ fun FirCallableDeclaration.contextReceiversForFunctionOrContainingProperty(): Li
|
||||
fun IrActualizedResult?.extractFirDeclarations(): Set<FirDeclaration>? {
|
||||
return this?.actualizedExpectDeclarations?.mapNotNullTo(mutableSetOf()) { ((it as IrMetadataSourceOwner).metadata as FirMetadataSource).fir }
|
||||
}
|
||||
|
||||
// This method is intended to be used for default values of annotation parameters (compile-time strings, numbers, enum values, KClasses)
|
||||
// where they are needed and may produce incorrect results for values that may be encountered outside annotations.
|
||||
fun FirExpression.asCompileTimeIrInitializer(components: Fir2IrComponents): IrExpressionBody? {
|
||||
return when (val elem = this.accept(Fir2IrVisitor(components, Fir2IrConversionScope()), null)) {
|
||||
is IrExpressionBody -> elem
|
||||
is IrExpression -> components.irFactory.createExpressionBody(elem)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
+19
-9
@@ -47,6 +47,7 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin.GeneratedByPlugi
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.IrLazyClass
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
@@ -1346,6 +1347,11 @@ class Fir2IrDeclarationStorage(
|
||||
useStubForDefaultValueStub: Boolean = true,
|
||||
typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT,
|
||||
skipDefaultParameter: Boolean = false,
|
||||
// Use this parameter if you want to insert the actual default value instead of the stub (overrides useStubForDefaultValueStub parameter).
|
||||
// This parameter is intended to be used for default values of annotation parameters where they are needed and
|
||||
// may produce incorrect results for values that may be encountered outside annotations.
|
||||
// Does not do anything if valueParameter.defaultValue is already FirExpressionStub.
|
||||
forcedDefaultValueConversion: Boolean = false,
|
||||
): IrValueParameter = convertCatching(valueParameter) {
|
||||
val origin = valueParameter.computeIrOrigin()
|
||||
val type = valueParameter.returnTypeRef.toIrType(typeOrigin)
|
||||
@@ -1366,16 +1372,20 @@ class Fir2IrDeclarationStorage(
|
||||
isNoinline = valueParameter.isNoinline,
|
||||
isHidden = false,
|
||||
).apply {
|
||||
if (!skipDefaultParameter && valueParameter.defaultValue.let {
|
||||
it != null && (useStubForDefaultValueStub || it !is FirExpressionStub)
|
||||
val defaultValue = valueParameter.defaultValue
|
||||
if (!skipDefaultParameter && defaultValue != null) {
|
||||
this.defaultValue = when {
|
||||
forcedDefaultValueConversion && defaultValue !is FirExpressionStub ->
|
||||
defaultValue.asCompileTimeIrInitializer(components)
|
||||
useStubForDefaultValueStub || defaultValue !is FirExpressionStub ->
|
||||
factory.createExpressionBody(
|
||||
IrErrorExpressionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, type,
|
||||
"Stub expression for default value of ${valueParameter.name}"
|
||||
)
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
) {
|
||||
this.defaultValue = factory.createExpressionBody(
|
||||
IrErrorExpressionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, type,
|
||||
"Stub expression for default value of ${valueParameter.name}"
|
||||
)
|
||||
)
|
||||
}
|
||||
annotationGenerator.generate(this, valueParameter)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.isAnnotationClass
|
||||
import org.jetbrains.kotlin.ir.util.parentClassOrNull
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -110,7 +111,8 @@ class Fir2IrLazyConstructor(
|
||||
fir.valueParameters.mapIndexedTo(this) { index, valueParameter ->
|
||||
declarationStorage.createIrParameter(
|
||||
valueParameter, index + contextReceiverParametersCount,
|
||||
useStubForDefaultValueStub = (parent as? IrClass)?.name != Name.identifier("Enum")
|
||||
useStubForDefaultValueStub = (parent as? IrClass)?.name != Name.identifier("Enum"),
|
||||
forcedDefaultValueConversion = (parent as? IrClass)?.isAnnotationClass == true,
|
||||
).apply {
|
||||
this.parent = this@Fir2IrLazyConstructor
|
||||
}
|
||||
|
||||
@@ -94,13 +94,7 @@ class Fir2IrLazyProperty(
|
||||
private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? {
|
||||
// Annotations need full initializer information to instantiate them correctly
|
||||
return when {
|
||||
containingClass?.classKind?.isAnnotationClass == true -> {
|
||||
when (val elem = initializer?.accept(Fir2IrVisitor(components, Fir2IrConversionScope()), null)) {
|
||||
is IrExpressionBody -> elem
|
||||
is IrExpression -> factory.createExpressionBody(elem)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
containingClass?.classKind?.isAnnotationClass == true -> initializer?.asCompileTimeIrInitializer(components)
|
||||
// Setting initializers to every other class causes some cryptic errors in lowerings
|
||||
initializer is FirConstExpression<*> -> {
|
||||
val constType = with(typeConverter) { initializer.typeRef.toIrType() }
|
||||
|
||||
+12
@@ -582,6 +582,18 @@ public class FirLightTreeBlackBoxCodegenTestGenerated extends AbstractFirLightTr
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaAnnotationDefault.kt")
|
||||
public void testJavaAnnotationDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotationDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaExistingAnnotation.kt")
|
||||
public void testJavaExistingAnnotation() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaExistingAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinExistingAnnotation.kt")
|
||||
public void testKotlinExistingAnnotation() throws Exception {
|
||||
|
||||
+12
@@ -582,6 +582,18 @@ public class FirPsiBlackBoxCodegenTestGenerated extends AbstractFirPsiBlackBoxCo
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaAnnotationDefault.kt")
|
||||
public void testJavaAnnotationDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotationDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaExistingAnnotation.kt")
|
||||
public void testJavaExistingAnnotation() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaExistingAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinExistingAnnotation.kt")
|
||||
public void testKotlinExistingAnnotation() throws Exception {
|
||||
|
||||
@@ -17,8 +17,8 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildArrayLiteral
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildConstExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildErrorExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.expectedConeType
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.createArrayType
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.load.java.RXJAVA3_ANNOTATIONS
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
|
||||
@@ -54,8 +54,19 @@ val JavaClass.classKind: ClassKind
|
||||
fun JavaClass.hasMetadataAnnotation(): Boolean =
|
||||
annotations.any { it.isResolvedTo(JvmAnnotationNames.METADATA_FQ_NAME) }
|
||||
|
||||
internal fun Any?.createConstantOrError(session: FirSession): FirExpression {
|
||||
return createConstantIfAny(session) ?: buildErrorExpression {
|
||||
internal fun Any?.createConstantOrError(session: FirSession, expectedTypeRef: FirTypeRef? = null): FirExpression {
|
||||
val coneType = expectedTypeRef?.coneTypeOrNull
|
||||
val value = if (this is Int && coneType != null) {
|
||||
// special case for Java literals in annotation default values:
|
||||
// literal value is always integer, but an expected parameter type can be any other number type
|
||||
when {
|
||||
coneType.isByte -> this.toByte()
|
||||
coneType.isShort -> this.toShort()
|
||||
coneType.isLong -> this.toLong()
|
||||
else -> this
|
||||
}
|
||||
} else this
|
||||
return value.createConstantIfAny(session) ?: buildErrorExpression {
|
||||
diagnostic = ConeSimpleDiagnostic("Unknown value in JavaLiteralAnnotationArgument: $this", DiagnosticKind.Java)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,7 +84,10 @@ internal fun JavaAnnotationArgument.toFirExpression(
|
||||
session: FirSession, javaTypeParameterStack: JavaTypeParameterStack, expectedTypeRef: FirTypeRef?
|
||||
): FirExpression {
|
||||
return when (this) {
|
||||
is JavaLiteralAnnotationArgument -> value.createConstantOrError(session)
|
||||
is JavaLiteralAnnotationArgument -> value.createConstantOrError(
|
||||
session,
|
||||
expectedTypeRef?.resolveIfJavaType(session, javaTypeParameterStack)
|
||||
)
|
||||
is JavaArrayAnnotationArgument -> buildArrayLiteral {
|
||||
val argumentTypeRef = expectedTypeRef?.let {
|
||||
typeRef = if (it is FirJavaTypeRef) buildResolvedTypeRef {
|
||||
@@ -275,7 +278,9 @@ private fun JavaAnnotation.toFirAnnotationCall(session: FirSession): FirAnnotati
|
||||
|
||||
classId == StandardClassIds.Annotations.Java.Deprecated -> {
|
||||
mapOf(
|
||||
StandardClassIds.Annotations.ParameterNames.deprecatedMessage to "Deprecated in Java".createConstantOrError(session)
|
||||
StandardClassIds.Annotations.ParameterNames.deprecatedMessage to "Deprecated in Java".createConstantOrError(
|
||||
session,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+16
-6
@@ -116,6 +116,7 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
generatedConstructor: IrConstructor
|
||||
) {
|
||||
implementor.implementAnnotationPropertiesAndConstructor(
|
||||
annotationClass,
|
||||
annotationClass.getAnnotationProperties(),
|
||||
implClass,
|
||||
generatedConstructor,
|
||||
@@ -231,6 +232,7 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
}
|
||||
|
||||
fun implementAnnotationPropertiesAndConstructor(
|
||||
annotationClass: IrClass,
|
||||
annotationProperties: List<IrProperty>,
|
||||
implClass: IrClass,
|
||||
generatedConstructor: IrConstructor,
|
||||
@@ -248,6 +250,11 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
|
||||
generatedConstructor.body = ctorBody
|
||||
|
||||
// For annotations defined in Java, IrProperties do not contain initializers in backing fields, as annotation properties are represented as Java methods
|
||||
// (that are later converted to synthetic properties w/o fields).
|
||||
// However, K2 stores default values in annotation's constructor parameters.
|
||||
val fallbackPrimaryCtorParamsMap = annotationClass.primaryConstructor?.valueParameters?.associateBy { it.name }.orEmpty()
|
||||
|
||||
annotationProperties.forEach { property ->
|
||||
val propType = property.getter!!.returnType
|
||||
val storedFieldType = propType.kClassToJClassIfNeeded()
|
||||
@@ -266,12 +273,15 @@ class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext,
|
||||
|
||||
val defaultExpression = property.backingField?.initializer?.expression
|
||||
val newDefaultValue: IrExpressionBody? =
|
||||
if (defaultExpression is IrGetValue && defaultExpression.symbol.owner is IrValueParameter) {
|
||||
// INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
(defaultExpression.symbol.owner as IrValueParameter).defaultValue
|
||||
} else if (defaultExpression != null) {
|
||||
property.backingField!!.initializer
|
||||
} else null
|
||||
// INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
when {
|
||||
defaultExpression is IrGetValue && defaultExpression.symbol.owner is IrValueParameter ->
|
||||
(defaultExpression.symbol.owner as IrValueParameter).defaultValue
|
||||
defaultExpression != null -> property.backingField!!.initializer
|
||||
propName in fallbackPrimaryCtorParamsMap ->
|
||||
fallbackPrimaryCtorParamsMap[propName]?.defaultValue?.takeIf { it.expression !is IrErrorExpression }
|
||||
else -> null
|
||||
}
|
||||
parameter.defaultValue = newDefaultValue?.deepCopyWithVariables()
|
||||
?.also { if (defaultValueTransformer != null) it.transformChildrenVoid(defaultValueTransformer) }
|
||||
|
||||
|
||||
@@ -20,12 +20,6 @@ public @interface C {
|
||||
String v2();
|
||||
}
|
||||
|
||||
// FILE: D.java
|
||||
|
||||
public @interface D {
|
||||
String value() default "hello";
|
||||
}
|
||||
|
||||
// FILE: b.kt
|
||||
|
||||
fun box(): String {
|
||||
@@ -34,10 +28,5 @@ fun box(): String {
|
||||
assert(b.value == "OK")
|
||||
val c = C(v2 = "v2", v1 = intArrayOf(1))
|
||||
assert(c.v2 == "v2")
|
||||
// TODO(KT-47702): Looks like we have to force users either to pass default java parameters explicitly
|
||||
// or hack LazyJavaClassDescriptor/JavaPropertyDescriptor to load annotation param default value,
|
||||
// because it is not stored currently anywhere.
|
||||
// val d = D()
|
||||
val d = D("OK").value
|
||||
return d
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_K1: JVM_IR
|
||||
|
||||
// WITH_STDLIB
|
||||
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||
|
||||
// FILE: A.java
|
||||
public @interface A {
|
||||
String value() default "OK";
|
||||
}
|
||||
|
||||
// FILE: ChildAnnotation.java
|
||||
@interface ChildAnnotation {
|
||||
String value();
|
||||
}
|
||||
|
||||
// FILE: D.java
|
||||
public @interface D {
|
||||
//Primitive types
|
||||
boolean booleanValue() default false;
|
||||
byte byteValue() default 1;
|
||||
short shortValue() default 2;
|
||||
int intValue() default 3;
|
||||
long longValue() default 4;
|
||||
float floatValue() default 5.0f;
|
||||
double doubleValue() default 6.0;
|
||||
char charValue() default 'a';
|
||||
|
||||
// String
|
||||
String stringValue() default "default";
|
||||
|
||||
// Class type
|
||||
Class<?> classValue() default Object.class;
|
||||
|
||||
// Enum type
|
||||
MyEnum enumValue() default MyEnum.FIRST;
|
||||
|
||||
// Annotation
|
||||
ChildAnnotation annotationValue() default @ChildAnnotation(value = "child") ;
|
||||
|
||||
// Arrays of the above
|
||||
boolean[] booleanArrayValue() default { false, true };
|
||||
byte[] byteArrayValue() default { 1, 2 };
|
||||
short[] shortArrayValue() default { 3, 4 };
|
||||
int[] intArrayValue() default { 5, 6 };
|
||||
long[] longArrayValue() default { 7, 8 };
|
||||
float[] floatArrayValue() default { 9.0f, 10.0f };
|
||||
double[] doubleArrayValue() default { 11.0, 12.0 };
|
||||
char[] charArrayValue() default { 'x', 'y' };
|
||||
String[] stringArrayValue() default { "Hello", "World" };
|
||||
Class<?>[] classArrayValue() default { Object.class, String.class };
|
||||
MyEnum[] enumArrayValue() default { MyEnum.FIRST, MyEnum.SECOND };
|
||||
ChildAnnotation[] annotationArrayValue() default { @ChildAnnotation(value = "child1"), @ChildAnnotation(value = "child2") };
|
||||
|
||||
// other annotation with default value
|
||||
A annotationWithDefault() default @A;
|
||||
}
|
||||
|
||||
// Supporting enum
|
||||
enum MyEnum { FIRST, SECOND }
|
||||
|
||||
// FILE: b.kt
|
||||
|
||||
fun box(): String {
|
||||
val d = D()
|
||||
val str = d.toString()
|
||||
val golden = """@D(booleanValue=false, byteValue=1, shortValue=2, intValue=3, longValue=4, floatValue=5.0, doubleValue=6.0, charValue=a, stringValue=default, """+
|
||||
"""classValue=class java.lang.Object, enumValue=FIRST, annotationValue=@ChildAnnotation(value=child), booleanArrayValue=[false, true], byteArrayValue=[1, 2], """ +
|
||||
"""shortArrayValue=[3, 4], intArrayValue=[5, 6], longArrayValue=[7, 8], floatArrayValue=[9.0, 10.0], doubleArrayValue=[11.0, 12.0], charArrayValue=[x, y], stringArrayValue=[Hello, World], """ +
|
||||
"""classArrayValue=[class java.lang.Object, class java.lang.String], enumArrayValue=[FIRST, SECOND], annotationArrayValue=[@ChildAnnotation(value=child1), @ChildAnnotation(value=child2)], """ +
|
||||
"""annotationWithDefault=@A(value=OK))"""
|
||||
if (str != golden) return str
|
||||
if (d.longValue != 4L) return d.longValue.toString()
|
||||
if (d.annotationValue.value != "child") return d.annotationValue.value
|
||||
if (d.doubleArrayValue[0] != 11.0) return d.doubleArrayValue[0].toString()
|
||||
if (d.classArrayValue[1] != String::class) return d.classArrayValue.contentToString()
|
||||
return d.annotationWithDefault.value
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// IGNORE_BACKEND_K1: JVM_IR
|
||||
// IGNORE_DEXING
|
||||
// WITH_STDLIB
|
||||
// !LANGUAGE: +InstantiationOfAnnotationClasses
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: LibAnnotation.java
|
||||
|
||||
package a;
|
||||
|
||||
public @interface LibAnnotation {
|
||||
long longValue() default 4;
|
||||
String stringValue() default "OK";
|
||||
Class<?> classValue() default String.class;
|
||||
float[] floatArrayValue() default { 9.0f, 10.0f };
|
||||
}
|
||||
|
||||
// MODULE: app(lib)
|
||||
// FILE: app.kt
|
||||
|
||||
package test
|
||||
|
||||
import a.*
|
||||
|
||||
fun box(): String {
|
||||
val l = LibAnnotation()
|
||||
if (l.toString() != "@a.LibAnnotation(longValue=4, stringValue=OK, classValue=class java.lang.String, floatArrayValue=[9.0, 10.0])")
|
||||
return l.toString()
|
||||
return "OK"
|
||||
}
|
||||
+12
@@ -582,6 +582,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaAnnotationDefault.kt")
|
||||
public void testJavaAnnotationDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotationDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaExistingAnnotation.kt")
|
||||
public void testJavaExistingAnnotation() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaExistingAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinExistingAnnotation.kt")
|
||||
public void testKotlinExistingAnnotation() throws Exception {
|
||||
|
||||
+12
@@ -582,6 +582,18 @@ public class IrBlackBoxCodegenWithIrInlinerTestGenerated extends AbstractIrBlack
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaAnnotationDefault.kt")
|
||||
public void testJavaAnnotationDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotationDefault.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaExistingAnnotation.kt")
|
||||
public void testJavaExistingAnnotation() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaExistingAnnotation.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kotlinExistingAnnotation.kt")
|
||||
public void testKotlinExistingAnnotation() throws Exception {
|
||||
|
||||
+10
@@ -430,6 +430,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/innerAnnotationInstantiation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaAnnotationDefault.kt")
|
||||
public void ignoreJavaAnnotationDefault() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotationDefault.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("javaExistingAnnotation.kt")
|
||||
public void ignoreJavaExistingAnnotation() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/instances/javaExistingAnnotation.kt");
|
||||
}
|
||||
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
|
||||
}
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ class SerialInfoImplJvmIrGenerator(
|
||||
visibility = DescriptorVisibilities.PUBLIC
|
||||
}
|
||||
|
||||
implementor.implementAnnotationPropertiesAndConstructor(properties, subclass, ctor, null)
|
||||
implementor.implementAnnotationPropertiesAndConstructor(annotationClass, properties, subclass, ctor, null)
|
||||
}
|
||||
|
||||
private fun createPackage(packageName: String): IrPackageFragment =
|
||||
|
||||
Reference in New Issue
Block a user