From e7f1cef3a1120cbc4f0727fdbf063b1843fc29d5 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Fri, 24 Sep 2021 20:44:55 +0300 Subject: [PATCH] Correctly rearrange arguments for annotation constructors copied from another module It won't fix KT-48181 completely, but it will allow to create such annotations if all value arguments are specified. For the full fix, we need to read default annotation values from classfiles in jar. #KT-48181 In progress --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++++ .../AnnotationImplementationTransformer.kt | 20 ++++++++++++++-- .../instances/kotlinExistingAnnotation.kt | 23 +++++++++++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/annotations/instances/kotlinExistingAnnotation.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index a589881e463..294c0315772 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -455,6 +455,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt"); } + @Test + @TestMetadata("kotlinExistingAnnotation.kt") + public void testKotlinExistingAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/kotlinExistingAnnotation.kt"); + } + @Test @TestMetadata("multifileEqHc.kt") public void testMultifileEqHc() throws Exception { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt index 30d2aa70029..b70cd74b122 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/AnnotationImplementationTransformer.kt @@ -12,7 +12,8 @@ import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.builders.declarations.* +import org.jetbrains.kotlin.ir.builders.declarations.addConstructor +import org.jetbrains.kotlin.ir.builders.declarations.buildClass import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrConstructorCall import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -56,13 +57,28 @@ abstract class AnnotationImplementationTransformer(val context: BackendContext, implClass.defaultType, ctor.symbol, ) - newCall.copyTypeAndValueArgumentsFrom(expression) + moveValueArgumentsUsingNames(expression, newCall) newCall.transformChildrenVoid() // for annotations in annotations return newCall } open fun IrClass.platformSetup() {} + private fun moveValueArgumentsUsingNames(source: IrConstructorCall, destination: IrConstructorCall) { + val argumentsByName = source.getArgumentsWithIr().associateBy( + { (param, _) -> param.name }, + { (_, value) -> value } + ) + + destination.symbol.owner.valueParameters.forEachIndexed { index, parameter -> + val valueArg = argumentsByName[parameter.name] + if (parameter.defaultValue == null && valueArg == null) + error("Usage of default value argument for this annotation is not yet possible.\n" + + "Please specify value for '${source.type.classOrNull?.owner?.name}.${parameter.name}' explicitly") + destination.putValueArgument(index, valueArg) + } + } + private fun createAnnotationImplementation(annotationClass: IrClass): IrClass { val localDeclarationParent = currentClass?.scope?.getLocalDeclarationParent() as? IrClass val parentFqName = annotationClass.fqNameWhenAvailable!!.asString().replace('.', '_') diff --git a/compiler/testData/codegen/box/annotations/instances/kotlinExistingAnnotation.kt b/compiler/testData/codegen/box/annotations/instances/kotlinExistingAnnotation.kt new file mode 100644 index 00000000000..f75af1eaf8a --- /dev/null +++ b/compiler/testData/codegen/box/annotations/instances/kotlinExistingAnnotation.kt @@ -0,0 +1,23 @@ +// IGNORE_BACKEND_FIR: JVM_IR +// TARGET_BACKEND: JVM_IR + +// WITH_RUNTIME +// !LANGUAGE: +InstantiationOfAnnotationClasses + +fun f(): Metadata = Metadata( + kind = 0, + metadataVersion = intArrayOf(), + data1 = arrayOf(), + data2 = arrayOf(), + extraString = "", + packageName = "foo", + extraInt = 0, + bytecodeVersion = intArrayOf(1, 0, 3), +) + +fun box(): String { + val m = f() + if (m.toString() == """@kotlin.Metadata(bytecodeVersion=[1, 0, 3], data1=[], data2=[], extraInt=0, extraString=, kind=0, metadataVersion=[], packageName=foo)""") + return "OK" + return m.toString() +} \ No newline at end of file diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 7ef3db8a5a7..e160fc79670 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -455,6 +455,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt"); } + @Test + @TestMetadata("kotlinExistingAnnotation.kt") + public void testKotlinExistingAnnotation() throws Exception { + runTest("compiler/testData/codegen/box/annotations/instances/kotlinExistingAnnotation.kt"); + } + @Test @TestMetadata("multifileEqHc.kt") public void testMultifileEqHc() throws Exception {