From c4255f9a9e6ed87e25124372da85de68d4918946 Mon Sep 17 00:00:00 2001 From: Leonid Startsev Date: Mon, 24 Apr 2023 18:32:13 +0200 Subject: [PATCH] [K2] Instantiation of annotations having default values for properties This commit adds missing pieces for the puzzle: Annotation instantiation feature uses IrProperty's initializer to instantiate properties from other modules that have default values which weren't specified on call site. To support this feature properly, Fir2IrVisitor should fill LazyIrProperty's backing field initializer with information from Fir. To get this information into Fir, FirMemberDeserializer should be able to read it from KotlinJvmBinaryClass with AnnotationLoaderVisitorImpl. (klibs are unsupported for now) There's a catch with enum entries references: we can't access session.SymbolProvider to resolve it because we're still at the deserialization stage, and it can cause StackOverflow if enum is nested in the same class (see RequiresOptIn.Level). To mitigate this, a new FirEnumEntryDeserializedAccessExpression is produced instead; it is later replaced with the correct reference in the Fir2IrVisitor. ^KT-58137 Fixed Also add test to loadJava folder with annotations default values that verifies metadata loading --- .../FirLoadK1CompiledKotlinGenerated.java | 6 + .../FirLoadK2CompiledKotlinGenerated.java | 6 + .../AbstractAnnotationDeserializer.kt | 9 + .../FirEnumEntryDeserializerAccessUtil.kt | 51 ++++ .../deserialization/FirMemberDeserializer.kt | 15 +- compiler/fir/fir2ir/build.gradle.kts | 1 + .../kotlin/fir/backend/Fir2IrVisitor.kt | 8 + .../kotlin/fir/lazy/Fir2IrLazyProperty.kt | 26 +- .../jetbrains/kotlin/fir/java/JavaUtils.kt | 10 +- .../java/deserialization/AnnotationsLoader.kt | 278 ++++++++++-------- .../JvmBinaryAnnotationDeserializer.kt | 46 ++- ...irEnumEntryDeserializedAccessExpression.kt | 38 +++ ...ntryDeserializedAccessExpressionBuilder.kt | 67 +++++ ...umEntryDeserializedAccessExpressionImpl.kt | 59 ++++ .../kotlin/fir/visitors/FirDefaultVisitor.kt | 3 + .../fir/visitors/FirDefaultVisitorVoid.kt | 3 + .../kotlin/fir/visitors/FirTransformer.kt | 9 + .../kotlin/fir/visitors/FirVisitor.kt | 3 + .../kotlin/fir/visitors/FirVisitorVoid.kt | 9 + .../kotlin/fir/renderer/FirRenderer.kt | 6 + .../fir/tree/generator/FirTreeBuilder.kt | 2 + .../generator/ImplementationConfigurator.kt | 8 + .../fir/tree/generator/NodeConfigurator.kt | 5 + .../kotlin/fir/tree/generator/importables.kt | 6 +- .../instances/multimoduleCreation.kt | 19 +- .../typealias/Annotations.fir.txt | 2 +- .../annotationClassDefaultValues.fir.k1.txt | 73 +++++ .../annotationClassDefaultValues.fir.k2.txt | 73 +++++ .../annotationClassDefaultValues.kt | 31 ++ .../annotationClassDefaultValues.txt | 63 ++++ .../classMembers/EnumEntry.fir.txt | 4 +- .../jvm/compiler/LoadJavaTestGenerated.java | 5 + .../compiler/ir/IrLoadJavaTestGenerated.java | 5 + .../LoadJavaUsingJavacTestGenerated.java | 5 + 34 files changed, 797 insertions(+), 157 deletions(-) create mode 100644 compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirEnumEntryDeserializerAccessUtil.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirEnumEntryDeserializedAccessExpression.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirEnumEntryDeserializedAccessExpressionBuilder.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEnumEntryDeserializedAccessExpressionImpl.kt create mode 100644 compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k1.txt create mode 100644 compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k2.txt create mode 100644 compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt create mode 100644 compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.txt diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK1CompiledKotlinGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK1CompiledKotlinGenerated.java index d21f79f39ca..3156acf1d72 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK1CompiledKotlinGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK1CompiledKotlinGenerated.java @@ -3216,6 +3216,12 @@ public class FirLoadK1CompiledKotlinGenerated extends AbstractFirLoadK1CompiledK KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("annotationClassDefaultValues.kt") + public void testAnnotationClassDefaultValues() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt"); + } + @Test @TestMetadata("AnnotationInAnnotationArguments.kt") public void testAnnotationInAnnotationArguments() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK2CompiledKotlinGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK2CompiledKotlinGenerated.java index e647b196cca..3837f33eab0 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK2CompiledKotlinGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLoadK2CompiledKotlinGenerated.java @@ -3216,6 +3216,12 @@ public class FirLoadK2CompiledKotlinGenerated extends AbstractFirLoadK2CompiledK KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("annotationClassDefaultValues.kt") + public void testAnnotationClassDefaultValues() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt"); + } + @Test @TestMetadata("AnnotationInAnnotationArguments.kt") public void testAnnotationInAnnotationArguments() throws Exception { diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt index 168392138c0..c06bd239b93 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt @@ -164,6 +164,15 @@ abstract class AbstractAnnotationDeserializer( ): List { return emptyList() } + open fun loadAnnotationPropertyDefaultValue( + containerSource: DeserializedContainerSource?, + propertyProto: ProtoBuf.Property, + expectedPropertyType: FirTypeRef, + nameResolver: NameResolver, + typeTable: TypeTable + ): FirExpression? { + return null + } abstract fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirEnumEntryDeserializerAccessUtil.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirEnumEntryDeserializerAccessUtil.kt new file mode 100644 index 00000000000..885e3a98b37 --- /dev/null +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirEnumEntryDeserializerAccessUtil.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.deserialization + +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.utils.isStatic +import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression +import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression +import org.jetbrains.kotlin.fir.expressions.builder.buildPropertyAccessExpression +import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference +import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols +import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl +import org.jetbrains.kotlin.fir.types.toLookupTag + +fun FirEnumEntryDeserializedAccessExpression.toQualifiedPropertyAccessExpression(session: FirSession): FirPropertyAccessExpression = + buildPropertyAccessExpression { + val entryPropertySymbol = session.symbolProvider.getClassDeclaredPropertySymbols( + enumClassId, enumEntryName, + ).firstOrNull { it.isStatic } + + calleeReference = when { + entryPropertySymbol != null -> { + buildResolvedNamedReference { + this.name = enumEntryName + resolvedSymbol = entryPropertySymbol + } + } + else -> { + buildErrorNamedReference { + diagnostic = ConeSimpleDiagnostic( + "Strange deserialized enum value: $enumClassId.$enumEntryName", + DiagnosticKind.Java, + ) + } + } + } + + typeRef = buildResolvedTypeRef { + type = ConeClassLikeTypeImpl( + enumClassId.toLookupTag(), emptyArray(), isNullable = false + ) + } + } diff --git a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt index ef43c7c5bba..fec6a010ca2 100644 --- a/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt +++ b/compiler/fir/fir-deserialization/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt @@ -448,7 +448,20 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { ) } this.containerSource = c.containerSource - this.initializer = c.constDeserializer.loadConstant(proto, symbol.callableId, c.nameResolver) + this.initializer = when { + Flags.HAS_CONSTANT.get(proto.flags) -> c.constDeserializer.loadConstant(proto, symbol.callableId, c.nameResolver) + // classSymbol?.classKind?.isAnnotationClass throws 'Fir is not initialized for FirRegularClassSymbol kotlin/String' + classProto != null && Flags.CLASS_KIND.get(classProto.flags) == ProtoBuf.Class.Kind.ANNOTATION_CLASS -> { + c.annotationDeserializer.loadAnnotationPropertyDefaultValue( + c.containerSource, + proto, + returnTypeRef, + local.nameResolver, + local.typeTable + ) + } + else -> null + } deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(c.session, fromJava = false) proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers, ::loadContextReceiver) diff --git a/compiler/fir/fir2ir/build.gradle.kts b/compiler/fir/fir2ir/build.gradle.kts index ad8b76cc95c..9c2cbfc5b0d 100644 --- a/compiler/fir/fir2ir/build.gradle.kts +++ b/compiler/fir/fir2ir/build.gradle.kts @@ -17,6 +17,7 @@ dependencies { compileOnly(project(":compiler:ir.backend.common")) compileOnly(project(":compiler:ir.serialization.common")) compileOnly(project(":compiler:fir:fir-serialization")) + compileOnly(project(":compiler:fir:fir-deserialization")) compileOnly(intellijCore()) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index 937a490bacd..2968bf9470e 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.isSealed import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.deserialization.toQualifiedPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition @@ -952,6 +953,13 @@ class Fir2IrVisitor( } } + override fun visitEnumEntryDeserializedAccessExpression( + enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, + data: Any? + ): IrElement { + return visitPropertyAccessExpression(enumEntryDeserializedAccessExpression.toQualifiedPropertyAccessExpression(session), data) + } + override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: Any?): IrElement { val firLhsVariable = buildProperty { source = elvisExpression.source diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt index b81cd1c0d7a..2ae4e416dd2 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyProperty.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lazy import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.descriptors.isAnnotationClass import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter @@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar import org.jetbrains.kotlin.ir.expressions.IrConstructorCall +import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.types.IrErrorType @@ -32,7 +34,7 @@ import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource class Fir2IrLazyProperty( - components: Fir2IrComponents, + private val components: Fir2IrComponents, override val startOffset: Int, override val endOffset: Int, override var origin: IrDeclarationOrigin, @@ -93,12 +95,22 @@ class Fir2IrLazyProperty( } private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? { - return if (initializer is FirConstExpression<*>) { - // TODO: Normally we shouldn't have error type here - val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type } - factory.createExpressionBody(initializer.toIrConst(constType)) - } else { - null + // 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 + } + } + // Setting initializers to every other class causes some cryptic errors in lowerings + initializer is FirConstExpression<*> -> { + // TODO: Normally we shouldn't have error type here + val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type } + factory.createExpressionBody(initializer.toIrConst(constType)) + } + else -> null } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt index 3d716554f52..66215d7faf9 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/JavaUtils.kt @@ -61,12 +61,12 @@ internal fun Any?.createConstantOrError(session: FirSession): FirExpression { } } -internal fun Any?.createConstantIfAny(session: FirSession): FirExpression? { +internal fun Any?.createConstantIfAny(session: FirSession, unsigned: Boolean = false): FirExpression? { return when (this) { - is Byte -> buildConstExpression(null, ConstantValueKind.Byte, this).setProperType(session) - is Short -> buildConstExpression(null, ConstantValueKind.Short, this).setProperType(session) - is Int -> buildConstExpression(null, ConstantValueKind.Int, this).setProperType(session) - is Long -> buildConstExpression(null, ConstantValueKind.Long, this).setProperType(session) + is Byte -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedByte else ConstantValueKind.Byte, this).setProperType(session) + is Short -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedShort else ConstantValueKind.Short, this).setProperType(session) + is Int -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedInt else ConstantValueKind.Int, this).setProperType(session) + is Long -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedLong else ConstantValueKind.Long, this).setProperType(session) is Char -> buildConstExpression(null, ConstantValueKind.Char, this).setProperType(session) is Float -> buildConstExpression(null, ConstantValueKind.Float, this).setProperType(session) is Double -> buildConstExpression(null, ConstantValueKind.Double, this).setProperType(session) diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt index de7b4882a48..5ad4e0aa168 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/AnnotationsLoader.kt @@ -7,157 +7,142 @@ package org.jetbrains.kotlin.fir.java.deserialization import org.jetbrains.kotlin.SpecialJvmAnnotations import org.jetbrains.kotlin.fir.FirSession -import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic -import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.deserialization.toQualifiedPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.java.createConstantOrError import org.jetbrains.kotlin.fir.languageVersionSettings -import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference -import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.providers.getClassDeclaredPropertySymbols import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef -import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder -import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass -import org.jetbrains.kotlin.load.kotlin.findKotlinClass +import org.jetbrains.kotlin.load.kotlin.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue +import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.utils.toMetadataVersion internal class AnnotationsLoader(private val session: FirSession, private val kotlinClassFinder: KotlinClassFinder) { + private abstract inner class AnnotationsLoaderVisitorImpl(val enumEntryReferenceCreator: (ClassId, Name) -> FirExpression) : KotlinJvmBinaryClass.AnnotationArgumentVisitor { + abstract fun visitExpression(name: Name?, expr: FirExpression) + + abstract val visitNullNames: Boolean + + abstract fun guessArrayTypeIfNeeded(name: Name?, arrayOfElements: List): FirTypeRef? + + override fun visit(name: Name?, value: Any?) { + visitExpression(name, createConstant(value)) + } + + private fun ClassLiteralValue.toFirClassReferenceExpression(): FirClassReferenceExpression { + val resolvedClassTypeRef = classId.toLookupTag().toDefaultResolvedTypeRef() + return buildClassReferenceExpression { + classTypeRef = resolvedClassTypeRef + typeRef = buildResolvedTypeRef { + type = StandardClassIds.KClass.constructClassLikeType(arrayOf(resolvedClassTypeRef.type), false) + } + } + } + + override fun visitClassLiteral(name: Name?, value: ClassLiteralValue) { + visitExpression(name, buildGetClassCall { + val argument = value.toFirClassReferenceExpression() + argumentList = buildUnaryArgumentList(argument) + typeRef = argument.typeRef + }) + } + + override fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name) { + if (name == null && !visitNullNames) return + visitExpression(name, enumEntryReferenceCreator(enumClassId, enumEntryName)) + } + + override fun visitArray(name: Name?): KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor? { + if (name == null && !visitNullNames) return null + return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor { + private val elements = mutableListOf() + + override fun visit(value: Any?) { + elements.add(createConstant(value)) + } + + override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) { + elements.add(enumEntryReferenceCreator(enumClassId, enumEntryName)) + } + + override fun visitClassLiteral(value: ClassLiteralValue) { + elements.add(buildGetClassCall { + val argument = value.toFirClassReferenceExpression() + argumentList = buildUnaryArgumentList(argument) + typeRef = argument.typeRef + }) + } + + override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor { + val list = mutableListOf() + val visitor = loadAnnotation(classId, list, enumEntryReferenceCreator) + return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor { + override fun visitEnd() { + visitor.visitEnd() + elements.add(list.single()) + } + } + } + + override fun visitEnd() { + visitExpression(name, buildArrayOfCall { + guessArrayTypeIfNeeded(name, elements)?.let { typeRef = it } + argumentList = buildArgumentList { + arguments += elements + } + }) + } + } + } + + override fun visitAnnotation(name: Name?, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { + if (name == null && !visitNullNames) return null + val list = mutableListOf() + val visitor = loadAnnotation(classId, list, enumEntryReferenceCreator) + return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor { + override fun visitEnd() { + visitor.visitEnd() + visitExpression(name, list.single()) + } + } + } + + private fun createConstant(value: Any?): FirExpression { + return value.createConstantOrError(session) + } + } + private fun loadAnnotation( - annotationClassId: ClassId, result: MutableList, + annotationClassId: ClassId, result: MutableList, enumEntryReferenceCreator: (ClassId, Name) -> FirExpression ): KotlinJvmBinaryClass.AnnotationArgumentVisitor { val lookupTag = annotationClassId.toLookupTag() - return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor { + return object : AnnotationsLoaderVisitorImpl(enumEntryReferenceCreator) { private val argumentMap = mutableMapOf() - override fun visit(name: Name?, value: Any?) { - if (name != null) { - argumentMap[name] = createConstant(value) - } + override fun visitExpression(name: Name?, expr: FirExpression) { + if (name != null) argumentMap[name] = expr } - private fun ClassLiteralValue.toFirClassReferenceExpression(): FirClassReferenceExpression { - val resolvedClassTypeRef = classId.toLookupTag().toDefaultResolvedTypeRef() - return buildClassReferenceExpression { - classTypeRef = resolvedClassTypeRef - typeRef = buildResolvedTypeRef { - type = StandardClassIds.KClass.constructClassLikeType(arrayOf(resolvedClassTypeRef.type), false) - } - } - } + override val visitNullNames: Boolean = false - private fun ClassId.toEnumEntryReferenceExpression(name: Name): FirExpression { - return buildPropertyAccessExpression { - val entryPropertySymbol = - session.symbolProvider.getClassDeclaredPropertySymbols( - this@toEnumEntryReferenceExpression, name, - ).firstOrNull() - - calleeReference = when { - entryPropertySymbol != null -> { - buildResolvedNamedReference { - this.name = name - resolvedSymbol = entryPropertySymbol - } - } - else -> { - buildErrorNamedReference { - diagnostic = ConeSimpleDiagnostic( - "Strange deserialized enum value: ${this@toEnumEntryReferenceExpression}.$name", - DiagnosticKind.Java, - ) - } - } - } - - typeRef = buildResolvedTypeRef { - type = ConeClassLikeTypeImpl( - this@toEnumEntryReferenceExpression.toLookupTag(), - emptyArray(), - isNullable = false - ) - } - } - } - - override fun visitClassLiteral(name: Name?, value: ClassLiteralValue) { - if (name == null) return - argumentMap[name] = buildGetClassCall { - val argument = value.toFirClassReferenceExpression() - argumentList = buildUnaryArgumentList(argument) - typeRef = argument.typeRef - } - } - - override fun visitEnum(name: Name?, enumClassId: ClassId, enumEntryName: Name) { - if (name == null) return - argumentMap[name] = enumClassId.toEnumEntryReferenceExpression(enumEntryName) - } - - override fun visitArray(name: Name?): KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor? { + override fun guessArrayTypeIfNeeded(name: Name?, arrayOfElements: List): FirTypeRef? { + // Needed if we load a default value which is another annotation that has array value in it. e.g.: + // To instantiate Deprecated() we need a default value for ReplaceWith() that has imports: Array with default value []. if (name == null) return null - return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor { - private val elements = mutableListOf() - - override fun visit(value: Any?) { - elements.add(createConstant(value)) - } - - override fun visitEnum(enumClassId: ClassId, enumEntryName: Name) { - elements.add(enumClassId.toEnumEntryReferenceExpression(enumEntryName)) - } - - override fun visitClassLiteral(value: ClassLiteralValue) { - elements.add( - buildGetClassCall { - val argument = value.toFirClassReferenceExpression() - argumentList = buildUnaryArgumentList(argument) - typeRef = argument.typeRef - } - ) - } - - override fun visitAnnotation(classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor { - val list = mutableListOf() - val visitor = loadAnnotation(classId, list) - return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor { - override fun visitEnd() { - visitor.visitEnd() - elements.add(list.single()) - } - } - } - - override fun visitEnd() { - argumentMap[name] = buildArrayOfCall { - argumentList = buildArgumentList { - arguments += elements - } - } - } - } - } - - override fun visitAnnotation(name: Name?, classId: ClassId): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { - if (name == null) return null - val list = mutableListOf() - val visitor = loadAnnotation(classId, list) - return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor { - override fun visitEnd() { - visitor.visitEnd() - argumentMap[name] = list.single() - } - } + // Note: generally we are not allowed to resolve anything, as this is might lead to recursive resolve problems + // However, K1 deserializer did exactly the same and no issues were reported. + val propS = session.symbolProvider.getClassDeclaredPropertySymbols(annotationClassId, name).firstOrNull() + return propS?.resolvedReturnTypeRef } override fun visitEnd() { @@ -173,9 +158,35 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko } } } + } + } - private fun createConstant(value: Any?): FirExpression { - return value.createConstantOrError(session) + internal fun loadAnnotationMethodDefaultValue( + methodSignature: MemberSignature, + consumeResult: (FirExpression) -> Unit + ): KotlinJvmBinaryClass.AnnotationArgumentVisitor { + return object : AnnotationsLoaderVisitorImpl(this::toEnumEntryReferenceExpressionUnresolved) { + var defaultValue: FirExpression? = null + + override fun visitExpression(name: Name?, expr: FirExpression) { + defaultValue = expr + } + + override val visitNullNames: Boolean = true + + override fun guessArrayTypeIfNeeded(name: Name?, arrayOfElements: List): FirTypeRef { + val descName = methodSignature.signature.substringAfterLast(')').removePrefix("[") + val targetClassId = JvmPrimitiveType.getByDesc(descName)?.primitiveType?.typeFqName?.let { ClassId.topLevel(it) } + ?: FileBasedKotlinClass.resolveNameByInternalName( + descName.removePrefix("L").removeSuffix(";"), + // It seems that some inner classes info is required, but so far there are no problems with them (see six() in multimoduleCreation test) + FileBasedKotlinClass.InnerClassesInfo() + ) + return targetClassId.toLookupTag().constructClassType(arrayOf(), false).createOutArrayType().toFirResolvedTypeRef() + } + + override fun visitEnd() { + defaultValue?.let(consumeResult) } } } @@ -187,8 +198,7 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko val classReference = getClassCall.argument as? FirClassReferenceExpression ?: return false val containerType = classReference.classTypeRef.coneType as? ConeClassLikeType ?: return false val classId = containerType.lookupTag.classId - if (classId.outerClassId == null || - classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME + if (classId.outerClassId == null || classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME ) return false val klass = kotlinClassFinder.findKotlinClass(classId, session.languageVersionSettings.languageVersion.toMetadataVersion()) @@ -199,11 +209,21 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko annotationClassId: ClassId, result: MutableList, ): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { if (annotationClassId in SpecialJvmAnnotations.SPECIAL_ANNOTATIONS) return null - return loadAnnotation(annotationClassId, result) + // Note: we shouldn't resolve enum entries here either: KT-58294 + return loadAnnotation(annotationClassId, result, this::toEnumEntryReferenceExpressionWithResolve) } private fun ConeClassLikeLookupTag.toDefaultResolvedTypeRef(): FirResolvedTypeRef = buildResolvedTypeRef { type = constructClassType(emptyArray(), isNullable = false) } + + private fun toEnumEntryReferenceExpressionWithResolve(classId: ClassId, name: Name): FirPropertyAccessExpression = + toEnumEntryReferenceExpressionUnresolved(classId, name).toQualifiedPropertyAccessExpression(session) + + private fun toEnumEntryReferenceExpressionUnresolved(classId: ClassId, name: Name): FirEnumEntryDeserializedAccessExpression = + buildEnumEntryDeserializedAccessExpression { + enumClassId = classId + enumEntryName = name + } } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt index 719b53b1caa..d7f556f3cd5 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/deserialization/JvmBinaryAnnotationDeserializer.kt @@ -10,10 +10,19 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirConstExpression +import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotation +import org.jetbrains.kotlin.fir.java.createConstantIfAny import org.jetbrains.kotlin.fir.languageVersionSettings +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.coneType +import org.jetbrains.kotlin.fir.types.isUnsignedType import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.kotlin.* +import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass +import org.jetbrains.kotlin.load.kotlin.MemberSignature +import org.jetbrains.kotlin.load.kotlin.getPropertySignature import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf @@ -24,6 +33,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.protobuf.MessageLite import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource +import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.toMetadataVersion @@ -197,6 +207,24 @@ class JvmBinaryAnnotationDeserializer( return findJvmBinaryClassAndLoadMemberAnnotations(paramSignature) } + override fun loadAnnotationPropertyDefaultValue( + containerSource: DeserializedContainerSource?, + propertyProto: ProtoBuf.Property, + expectedPropertyType: FirTypeRef, + nameResolver: NameResolver, + typeTable: TypeTable + ): FirExpression? { + val signature = getCallableSignature(propertyProto, nameResolver, typeTable, CallableKind.PROPERTY_GETTER) ?: return null + val firExpr = annotationInfo.annotationMethodsDefaultValues[signature] + return if (firExpr is FirConstExpression<*> && expectedPropertyType.coneType.isUnsignedType && firExpr.kind.isSignedNumber) + firExpr.value.createConstantIfAny(session, unsigned = true) + else + firExpr + } + + private val ConstantValueKind.isSignedNumber: Boolean + get() = this is ConstantValueKind.Byte || this is ConstantValueKind.Short || this is ConstantValueKind.Int || this is ConstantValueKind.Long + private fun computeJvmParameterIndexShift(classProto: ProtoBuf.Class?, message: MessageLite): Int { return when (message) { is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0 @@ -268,7 +296,10 @@ class JvmBinaryAnnotationDeserializer( } // TODO: Rename this once property constants are recorded as well -private data class MemberAnnotations(val memberAnnotations: MutableMap>) +private data class MemberAnnotations( + val memberAnnotations: MutableMap>, + val annotationMethodsDefaultValues: Map +) // TODO: better to be in KotlinDeserializedJvmSymbolsProvider? private fun FirSession.loadMemberAnnotations( @@ -278,6 +309,7 @@ private fun FirSession.loadMemberAnnotations( ): MemberAnnotations { val memberAnnotations = hashMapOf>() val annotationsLoader = AnnotationsLoader(this, kotlinClassFinder) + val annotationMethodsDefaultValues = hashMapOf() kotlinBinaryClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor { override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor { @@ -288,6 +320,7 @@ private fun FirSession.loadMemberAnnotations( val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc) if (initializer != null) { // TODO: load constant + // TODO: Given there is FirConstDeserializer, maybe this comment is obsolete? } return MemberAnnotationVisitor(signature) } @@ -310,8 +343,7 @@ private fun FirSession.loadMemberAnnotations( } override fun visitAnnotationMemberDefaultValue(): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { - // TODO: load annotation default values to properly support annotation instantiation feature - return null + return annotationsLoader.loadAnnotationMethodDefaultValue(signature) { annotationMethodsDefaultValues[signature] = it } } } @@ -330,5 +362,9 @@ private fun FirSession.loadMemberAnnotations( } }, byteContent) - return MemberAnnotations(memberAnnotations) + + return MemberAnnotations( + memberAnnotations, + annotationMethodsDefaultValues + ) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirEnumEntryDeserializedAccessExpression.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirEnumEntryDeserializedAccessExpression.kt new file mode 100644 index 00000000000..8265aefa6fd --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/FirEnumEntryDeserializedAccessExpression.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.fir.expressions + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirElement +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.fir.visitors.* + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +abstract class FirEnumEntryDeserializedAccessExpression : FirExpression() { + abstract override val source: KtSourceElement? + abstract override val typeRef: FirTypeRef + abstract override val annotations: List + abstract val enumClassId: ClassId + abstract val enumEntryName: Name + + override fun accept(visitor: FirVisitor, data: D): R = visitor.visitEnumEntryDeserializedAccessExpression(this, data) + + @Suppress("UNCHECKED_CAST") + override fun transform(transformer: FirTransformer, data: D): E = + transformer.transformEnumEntryDeserializedAccessExpression(this, data) as E + + abstract override fun replaceTypeRef(newTypeRef: FirTypeRef) + + abstract override fun replaceAnnotations(newAnnotations: List) + + abstract override fun transformAnnotations(transformer: FirTransformer, data: D): FirEnumEntryDeserializedAccessExpression +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirEnumEntryDeserializedAccessExpressionBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirEnumEntryDeserializedAccessExpressionBuilder.kt new file mode 100644 index 00000000000..477f5d2c0d7 --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/builder/FirEnumEntryDeserializedAccessExpressionBuilder.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("DuplicatedCode") + +package org.jetbrains.kotlin.fir.expressions.builder + +import kotlin.contracts.* +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder +import org.jetbrains.kotlin.fir.builder.FirBuilderDsl +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression +import org.jetbrains.kotlin.fir.expressions.builder.FirExpressionBuilder +import org.jetbrains.kotlin.fir.expressions.impl.FirEnumEntryDeserializedAccessExpressionImpl +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.constructClassType +import org.jetbrains.kotlin.fir.types.toLookupTag +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +@FirBuilderDsl +class FirEnumEntryDeserializedAccessExpressionBuilder : FirAnnotationContainerBuilder, FirExpressionBuilder { + override val annotations: MutableList = mutableListOf() + lateinit var enumClassId: ClassId + lateinit var enumEntryName: Name + + override fun build(): FirEnumEntryDeserializedAccessExpression { + return FirEnumEntryDeserializedAccessExpressionImpl( + annotations.toMutableOrEmpty(), + enumClassId, + enumEntryName, + ) + } + + @Deprecated("Modification of 'source' has no impact for FirEnumEntryDeserializedAccessExpressionBuilder", level = DeprecationLevel.HIDDEN) + override var source: KtSourceElement? + get() = throw IllegalStateException() + set(_) { + throw IllegalStateException() + } + + @Deprecated("Modification of 'typeRef' has no impact for FirEnumEntryDeserializedAccessExpressionBuilder", level = DeprecationLevel.HIDDEN) + override var typeRef: FirTypeRef + get() = throw IllegalStateException() + set(_) { + throw IllegalStateException() + } +} + +@OptIn(ExperimentalContracts::class) +inline fun buildEnumEntryDeserializedAccessExpression(init: FirEnumEntryDeserializedAccessExpressionBuilder.() -> Unit): FirEnumEntryDeserializedAccessExpression { + contract { + callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + return FirEnumEntryDeserializedAccessExpressionBuilder().apply(init).build() +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEnumEntryDeserializedAccessExpressionImpl.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEnumEntryDeserializedAccessExpressionImpl.kt new file mode 100644 index 00000000000..68652ae6b39 --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/expressions/impl/FirEnumEntryDeserializedAccessExpressionImpl.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("DuplicatedCode") + +package org.jetbrains.kotlin.fir.expressions.impl + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef +import org.jetbrains.kotlin.fir.types.constructClassType +import org.jetbrains.kotlin.fir.types.toLookupTag +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.fir.MutableOrEmptyList +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +internal class FirEnumEntryDeserializedAccessExpressionImpl( + override var annotations: MutableOrEmptyList, + override val enumClassId: ClassId, + override val enumEntryName: Name, +) : FirEnumEntryDeserializedAccessExpression() { + override val source: KtSourceElement? get() = null + override var typeRef: FirTypeRef = buildResolvedTypeRef { type = enumClassId.toLookupTag().constructClassType(emptyArray(), false) } + + override fun acceptChildren(visitor: FirVisitor, data: D) { + typeRef.accept(visitor, data) + annotations.forEach { it.accept(visitor, data) } + } + + override fun transformChildren(transformer: FirTransformer, data: D): FirEnumEntryDeserializedAccessExpressionImpl { + typeRef = typeRef.transform(transformer, data) + transformAnnotations(transformer, data) + return this + } + + override fun transformAnnotations(transformer: FirTransformer, data: D): FirEnumEntryDeserializedAccessExpressionImpl { + annotations.transformInplace(transformer, data) + return this + } + + override fun replaceTypeRef(newTypeRef: FirTypeRef) { + typeRef = newTypeRef + } + + override fun replaceAnnotations(newAnnotations: List) { + annotations = newAnnotations.toMutableOrEmpty() + } +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt index f1f7fa8d6a1..c77e4bc6b7b 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitor.kt @@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -279,6 +280,8 @@ abstract class FirDefaultVisitor : FirVisitor() { override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R = visitWrappedExpression(wrappedDelegateExpression, data) + override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: D): R = visitExpression(enumEntryDeserializedAccessExpression, data) + override fun visitNamedReference(namedReference: FirNamedReference, data: D): R = visitReference(namedReference, data) override fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase, data: D): R = visitNamedReference(namedReferenceWithCandidateBase, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt index 215d987d6c5..27661ddb2de 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirDefaultVisitorVoid.kt @@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -279,6 +280,8 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() { override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) = visitWrappedExpression(wrappedDelegateExpression) + override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression) = visitExpression(enumEntryDeserializedAccessExpression) + override fun visitNamedReference(namedReference: FirNamedReference) = visitReference(namedReference) override fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase) = visitNamedReference(namedReferenceWithCandidateBase) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt index 8bd4e9bf562..afa10b3225d 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirTransformer.kt @@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -652,6 +653,10 @@ abstract class FirTransformer : FirVisitor() { return transformElement(wrappedDelegateExpression, data) } + open fun transformEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: D): FirStatement { + return transformElement(enumEntryDeserializedAccessExpression, data) + } + open fun transformNamedReference(namedReference: FirNamedReference, data: D): FirReference { return transformElement(namedReference, data) } @@ -1248,6 +1253,10 @@ abstract class FirTransformer : FirVisitor() { return transformWrappedDelegateExpression(wrappedDelegateExpression, data) } + final override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: D): FirStatement { + return transformEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression, data) + } + final override fun visitNamedReference(namedReference: FirNamedReference, data: D): FirReference { return transformNamedReference(namedReference, data) } diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt index 0b89adcd31e..694f11b6ce4 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitor.kt @@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -407,6 +408,8 @@ abstract class FirVisitor { open fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R = visitElement(wrappedDelegateExpression, data) + open fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: D): R = visitElement(enumEntryDeserializedAccessExpression, data) + open fun visitNamedReference(namedReference: FirNamedReference, data: D): R = visitElement(namedReference, data) open fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase, data: D): R = visitElement(namedReferenceWithCandidateBase, data) diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt index 96b5253b745..dfb5f6a5530 100644 --- a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/visitors/FirVisitorVoid.kt @@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression +import org.jetbrains.kotlin.fir.expressions.FirEnumEntryDeserializedAccessExpression import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -651,6 +652,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitElement(wrappedDelegateExpression) } + open fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression) { + visitElement(enumEntryDeserializedAccessExpression) + } + open fun visitNamedReference(namedReference: FirNamedReference) { visitElement(namedReference) } @@ -1247,6 +1252,10 @@ abstract class FirVisitorVoid : FirVisitor() { visitWrappedDelegateExpression(wrappedDelegateExpression) } + final override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: Nothing?) { + visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression) + } + final override fun visitNamedReference(namedReference: FirNamedReference, data: Nothing?) { visitNamedReference(namedReference) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt index 03f1edf0a76..648fbdfe3e9 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt @@ -651,6 +651,12 @@ class FirRenderer( wrappedDelegateExpression.expression.accept(this) } + override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression) { + with(enumEntryDeserializedAccessExpression) { + print("$enumClassId.$enumEntryName") + } + } + override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) { print(namedArgumentExpression.name) print(" = ") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt index 55b013b831e..d6c9e328a5e 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/FirTreeBuilder.kt @@ -156,6 +156,8 @@ object FirTreeBuilder : AbstractFirTreeBuilder() { val wrappedDelegateExpression by element(Expression, wrappedExpression) + val enumEntryDeserializedAccessExpression by element(Expression, expression) + val namedReference by element(Reference, reference) val namedReferenceWithCandidateBase by element(Reference, namedReference) val errorNamedReference by element(Reference, namedReference, diagnosticHolder) diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index b5540269065..6756f81e3dd 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -394,6 +394,14 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() } } + impl(enumEntryDeserializedAccessExpression) { + noSource() + default("typeRef") { + value = "buildResolvedTypeRef { type = enumClassId.toLookupTag().constructClassType(emptyArray(), false) }" + useTypes(buildResolvedTypeRefImport, toLookupTagImport, constructClassTypeImport) + } + } + impl(smartCastExpression) { default("isStable") { value = "smartcastStability == SmartcastStability.STABLE_VALUE" diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt index d3d382e7567..e0e94e6bd3c 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/NodeConfigurator.kt @@ -644,6 +644,11 @@ object NodeConfigurator : AbstractFieldConfigurator(FirTreeBuild +field("delegateProvider", expression).withReplace() } + enumEntryDeserializedAccessExpression.configure { + +field("enumClassId", classIdType) + +field("enumEntryName", nameType) + } + namedReference.configure { +name } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/importables.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/importables.kt index b2f5182d072..ad24f1ea228 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/importables.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/importables.kt @@ -10,4 +10,8 @@ import org.jetbrains.kotlin.fir.tree.generator.model.ArbitraryImportable val phaseAsResolveStateExtentionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "asResolveState") val resolvePhaseExtensionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "resolvePhase") val resolveStateAccessImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "ResolveStateAccess") -val resolvedDeclarationStatusImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations.impl", "FirResolvedDeclarationStatusImpl") \ No newline at end of file +val resolvedDeclarationStatusImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations.impl", "FirResolvedDeclarationStatusImpl") + +val buildResolvedTypeRefImport = ArbitraryImportable("org.jetbrains.kotlin.fir.types.builder", "buildResolvedTypeRef") +val constructClassTypeImport = ArbitraryImportable("org.jetbrains.kotlin.fir.types", "constructClassType") +val toLookupTagImport = ArbitraryImportable("org.jetbrains.kotlin.fir.types", "toLookupTag") diff --git a/compiler/testData/codegen/box/annotations/instances/multimoduleCreation.kt b/compiler/testData/codegen/box/annotations/instances/multimoduleCreation.kt index 1b949275abd..b329564f863 100644 --- a/compiler/testData/codegen/box/annotations/instances/multimoduleCreation.kt +++ b/compiler/testData/codegen/box/annotations/instances/multimoduleCreation.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND_K2: JVM_IR, JS_IR -// FIR status: IllegalStateException: Usage of default value argument for this annotation is not yet possible. -// Please specify value for 'A.kClass' explicitly // TARGET_BACKEND: JVM_IR // IGNORE_DEXING // WITH_STDLIB @@ -26,6 +23,12 @@ annotation class UnsignedValue( val uint: UInt = 2147483657U // Int.MAX_VALUE + 10 ) +annotation class Outer( + val array: Array = [Inner(1), Inner(2)] +) { + annotation class Inner(val v: Int = 0) +} + // MODULE: app(lib) // FILE: app.kt @@ -45,6 +48,7 @@ class C { fun three(): Deprecated = Deprecated("foo") fun four(): OtherArrays = OtherArrays() fun five(): UnsignedValue = UnsignedValue() + fun six(): Outer = Outer() } fun box(): String { @@ -58,10 +62,13 @@ fun box(): String { """@kotlin.Deprecated(level=WARNING, message=foo, replaceWith=@kotlin.ReplaceWith(expression=, imports=[]))""", C().three().toString() ) - assertEquals( - """@a.OtherArrays(annotationsArray=[], doublesArray=[], enumArray=[], namesArray=[@kotlin.jvm.JvmName(name=foo)])""", - C().four().toString() + val otherArraysStr = C().four().toString() + // K1 and K2 have different properties order after metadata deserialization + assertTrue( + otherArraysStr == """@a.OtherArrays(doublesArray=[], enumArray=[], annotationsArray=[], namesArray=[@kotlin.jvm.JvmName(name=foo)])""" || + otherArraysStr == """@a.OtherArrays(annotationsArray=[], doublesArray=[], enumArray=[], namesArray=[@kotlin.jvm.JvmName(name=foo)])""" ) assertEquals(Int.MAX_VALUE.toUInt() + 10.toUInt(), C().five().uint) + assertEquals("""@a.Outer(array=[@a.Outer.Inner(v=1), @a.Outer.Inner(v=2)])""", C().six().toString()) return "OK" } diff --git a/compiler/testData/loadJava/compiledKotlin/typealias/Annotations.fir.txt b/compiler/testData/loadJava/compiledKotlin/typealias/Annotations.fir.txt index 92c3c6e253f..309dcf885c2 100644 --- a/compiler/testData/loadJava/compiledKotlin/typealias/Annotations.fir.txt +++ b/compiler/testData/loadJava/compiledKotlin/typealias/Annotations.fir.txt @@ -3,7 +3,7 @@ @R|test/Ann|(value = String(OK)) public final typealias A2 = R|kotlin/String| @R|kotlin/annotation/Target|(allowedTargets = (R|kotlin/annotation/AnnotationTarget.TYPEALIAS|)) public final annotation class Ann : R|kotlin/Annotation| { - public final val value: R|kotlin/String| + public final val value: R|kotlin/String| = String() public get(): R|kotlin/String| public constructor(value: R|kotlin/String| = STUB): R|test/Ann| diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k1.txt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k1.txt new file mode 100644 index 00000000000..4d0502291f0 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k1.txt @@ -0,0 +1,73 @@ +public final annotation class A : R|kotlin/Annotation| { + public final val aI: R|kotlin/IntArray| = (Int(1), Int(2)) + public get(): R|kotlin/IntArray| + + public final val aS: R|kotlin/Array| = (String(a), String(b)) + public get(): R|kotlin/Array| + + public final val anno: R|test/Empty| = @R|test/Empty|() + public get(): R|test/Empty| + + public final val e: R|test/E| = test/E.E0 + public get(): R|test/E| + + public final val i: R|kotlin/Int| = Int(42) + public get(): R|kotlin/Int| + + public final val kClass: R|kotlin/reflect/KClass<*>| = ((R|kotlin/Int|)) + public get(): R|kotlin/reflect/KClass<*>| + + public final val kClassArray: R|kotlin/Array>| = (((R|test/A|))) + public get(): R|kotlin/Array>| + + public final val s: R|kotlin/String| = String(foo) + public get(): R|kotlin/String| + + public constructor(i: R|kotlin/Int| = STUB, s: R|kotlin/String| = STUB, kClass: R|kotlin/reflect/KClass<*>| = STUB, kClassArray: R|kotlin/Array>| = STUB, e: R|test/E| = STUB, anno: R|test/Empty| = STUB, aS: R|kotlin/Array| = STUB, aI: R|kotlin/IntArray| = STUB): R|test/A| + +} + +public final enum class E : R|kotlin/Enum| { + private constructor(): R|test/E| + + public final static enum entry E0: R|test/E| + public final static fun values(): R|kotlin/Array| { + } + + public final static fun valueOf(value: R|kotlin/String|): R|test/E| { + } + + public final static val entries: R|kotlin/enums/EnumEntries| + public get(): R|kotlin/enums/EnumEntries| + +} + +public final annotation class Empty : R|kotlin/Annotation| { + public constructor(): R|test/Empty| + +} + +public final annotation class OtherArrays : R|kotlin/Annotation| { + public final val annotationsArray: R|kotlin/Array| = () + public get(): R|kotlin/Array| + + public final val doublesArray: R|kotlin/DoubleArray| = (Double(1.5)) + public get(): R|kotlin/DoubleArray| + + public final val enumArray: R|kotlin/Array| = (kotlin/text/RegexOption.IGNORE_CASE) + public get(): R|kotlin/Array| + + public final val namesArray: R|kotlin/Array| = (@R|kotlin/jvm/JvmName|(name = String(foo)) ) + public get(): R|kotlin/Array| + + public constructor(doublesArray: R|kotlin/DoubleArray| = STUB, enumArray: R|kotlin/Array| = STUB, annotationsArray: R|kotlin/Array| = STUB, namesArray: R|kotlin/Array| = STUB): R|test/OtherArrays| + +} + +public final annotation class UnsignedValue : R|kotlin/Annotation| { + public final val uint: R|kotlin/UInt| = UInt(-2147483639) + public get(): R|kotlin/UInt| + + public constructor(uint: R|kotlin/UInt| = STUB): R|test/UnsignedValue| + +} diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k2.txt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k2.txt new file mode 100644 index 00000000000..eb7b8548779 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.fir.k2.txt @@ -0,0 +1,73 @@ +public final annotation class A : R|kotlin/Annotation| { + public final val i: R|kotlin/Int| = Int(42) + public get(): R|kotlin/Int| + + public final val s: R|kotlin/String| = String(foo) + public get(): R|kotlin/String| + + public final val kClass: R|kotlin/reflect/KClass<*>| = ((R|kotlin/Int|)) + public get(): R|kotlin/reflect/KClass<*>| + + public final val kClassArray: R|kotlin/Array>| = (((R|test/A|))) + public get(): R|kotlin/Array>| + + public final val e: R|test/E| = test/E.E0 + public get(): R|test/E| + + public final val anno: R|test/Empty| = @R|test/Empty|() + public get(): R|test/Empty| + + public final val aS: R|kotlin/Array| = (String(a), String(b)) + public get(): R|kotlin/Array| + + public final val aI: R|kotlin/IntArray| = (Int(1), Int(2)) + public get(): R|kotlin/IntArray| + + public constructor(i: R|kotlin/Int| = STUB, s: R|kotlin/String| = STUB, kClass: R|kotlin/reflect/KClass<*>| = STUB, kClassArray: R|kotlin/Array>| = STUB, e: R|test/E| = STUB, anno: R|test/Empty| = STUB, aS: R|kotlin/Array| = STUB, aI: R|kotlin/IntArray| = STUB): R|test/A| + +} + +public final enum class E : R|kotlin/Enum| { + private constructor(): R|test/E| + + public final static enum entry E0: R|test/E| + public final static fun values(): R|kotlin/Array| { + } + + public final static fun valueOf(value: R|kotlin/String|): R|test/E| { + } + + public final static val entries: R|kotlin/enums/EnumEntries| + public get(): R|kotlin/enums/EnumEntries| + +} + +public final annotation class Empty : R|kotlin/Annotation| { + public constructor(): R|test/Empty| + +} + +public final annotation class OtherArrays : R|kotlin/Annotation| { + public final val doublesArray: R|kotlin/DoubleArray| = (Double(1.5)) + public get(): R|kotlin/DoubleArray| + + public final val enumArray: R|kotlin/Array| = (kotlin/text/RegexOption.IGNORE_CASE) + public get(): R|kotlin/Array| + + public final val annotationsArray: R|kotlin/Array| = () + public get(): R|kotlin/Array| + + public final val namesArray: R|kotlin/Array| = (@R|kotlin/jvm/JvmName|(name = String(foo)) ) + public get(): R|kotlin/Array| + + public constructor(doublesArray: R|kotlin/DoubleArray| = STUB, enumArray: R|kotlin/Array| = STUB, annotationsArray: R|kotlin/Array| = STUB, namesArray: R|kotlin/Array| = STUB): R|test/OtherArrays| + +} + +public final annotation class UnsignedValue : R|kotlin/Annotation| { + public final val uint: R|kotlin/UInt| = UInt(-2147483639) + public get(): R|kotlin/UInt| + + public constructor(uint: R|kotlin/UInt| = STUB): R|test/UnsignedValue| + +} diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt new file mode 100644 index 00000000000..6417eeda7ae --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt @@ -0,0 +1,31 @@ +// NO_CHECK_SOURCE_VS_BINARY +//^ While compiling source with K1, we do not store annotation default values, but we load them when reading compiled files both in K1 and K2 +// This test verifies exactly loading of default values + +package test + +import kotlin.reflect.KClass +enum class E { E0 } +annotation class Empty + +annotation class A( + val i: Int = 42, + val s: String = "foo", + val kClass: KClass<*> = Int::class, + val kClassArray: Array> = [A::class], + val e: E = E.E0, + val anno: Empty = Empty(), + val aS: Array = arrayOf("a", "b"), + val aI: IntArray = intArrayOf(1, 2) +) + +annotation class OtherArrays( + val doublesArray: DoubleArray = [1.5], + val enumArray: Array = [kotlin.text.RegexOption.IGNORE_CASE], + val annotationsArray: Array = [], + val namesArray: Array = [JvmName("foo")] +) + +annotation class UnsignedValue( + val uint: UInt = 2147483657U // Int.MAX_VALUE + 10 +) diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.txt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.txt new file mode 100644 index 00000000000..d3b01026fb2 --- /dev/null +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.txt @@ -0,0 +1,63 @@ +package test + +public final annotation class A : kotlin.Annotation { + /*primary*/ public constructor A(/*0*/ i: kotlin.Int = ..., /*1*/ s: kotlin.String = ..., /*2*/ kClass: kotlin.reflect.KClass<*> = ..., /*3*/ kClassArray: kotlin.Array> = ..., /*4*/ e: test.E = ..., /*5*/ anno: test.Empty = ..., /*6*/ aS: kotlin.Array = ..., /*7*/ aI: kotlin.IntArray = ...) + public final val aI: kotlin.IntArray = {1, 2} + public final fun ``(): kotlin.IntArray + public final val aS: kotlin.Array = {"a", "b"} + public final fun ``(): kotlin.Array + public final val anno: test.Empty = test.Empty + public final fun ``(): test.Empty + public final val e: test.E = E.E0 + public final fun ``(): test.E + public final val i: kotlin.Int = 42 + public final fun ``(): kotlin.Int + public final val kClass: kotlin.reflect.KClass<*> = kotlin.Int::class + public final fun ``(): kotlin.reflect.KClass<*> + public final val kClassArray: kotlin.Array> = {test.A::class} + public final fun ``(): kotlin.Array> + public final val s: kotlin.String = "foo" + public final fun ``(): kotlin.String +} + +public final enum class E : kotlin.Enum { + enum entry E0 + + /*primary*/ private constructor E() + @kotlin.internal.IntrinsicConstEvaluation public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ fun ``(): kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + public final override /*1*/ /*fake_override*/ fun ``(): kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: test.E): kotlin.Int + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + + // Static members + public final /*synthesized*/ val entries: kotlin.enums.EnumEntries + public final /*synthesized*/ fun ``(): kotlin.enums.EnumEntries + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.E + public final /*synthesized*/ fun values(): kotlin.Array +} + +public final annotation class Empty : kotlin.Annotation { + /*primary*/ public constructor Empty() +} + +public final annotation class OtherArrays : kotlin.Annotation { + /*primary*/ public constructor OtherArrays(/*0*/ doublesArray: kotlin.DoubleArray = ..., /*1*/ enumArray: kotlin.Array = ..., /*2*/ annotationsArray: kotlin.Array = ..., /*3*/ namesArray: kotlin.Array = ...) + public final val annotationsArray: kotlin.Array = {} + public final fun ``(): kotlin.Array + public final val doublesArray: kotlin.DoubleArray = {1.5.toDouble()} + public final fun ``(): kotlin.DoubleArray + public final val enumArray: kotlin.Array = {RegexOption.IGNORE_CASE} + public final fun ``(): kotlin.Array + public final val namesArray: kotlin.Array = {kotlin.jvm.JvmName(name = "foo")} + public final fun ``(): kotlin.Array +} + +public final annotation class UnsignedValue : kotlin.Annotation { + /*primary*/ public constructor UnsignedValue(/*0*/ uint: kotlin.UInt = ...) + public final val uint: kotlin.UInt = -2147483639.toUInt() + public final fun ``(): kotlin.UInt +} diff --git a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/classMembers/EnumEntry.fir.txt b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/classMembers/EnumEntry.fir.txt index 030696e1e5a..3fb04058025 100644 --- a/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/classMembers/EnumEntry.fir.txt +++ b/compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/classMembers/EnumEntry.fir.txt @@ -1,8 +1,8 @@ public final annotation class Anno : R|kotlin/Annotation| { - public final val value: R|kotlin/String| + public final val value: R|kotlin/String| = String(0) public get(): R|kotlin/String| - public final val x: R|kotlin/Int| + public final val x: R|kotlin/Int| = Int(0) public get(): R|kotlin/Int| public constructor(value: R|kotlin/String| = STUB, x: R|kotlin/Int| = STUB): R|test/Anno| diff --git a/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index 627d97e8058..30fd7515377 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -4575,6 +4575,11 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @TestMetadata("annotationClassDefaultValues.kt") + public void testAnnotationClassDefaultValues() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt"); + } + @TestMetadata("AnnotationInAnnotationArguments.kt") public void testAnnotationInAnnotationArguments() throws Exception { runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/ir/IrLoadJavaTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/ir/IrLoadJavaTestGenerated.java index 0a5eeb85801..2eb85ce66d4 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/ir/IrLoadJavaTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/ir/IrLoadJavaTestGenerated.java @@ -4576,6 +4576,11 @@ public class IrLoadJavaTestGenerated extends AbstractIrLoadJavaTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @TestMetadata("annotationClassDefaultValues.kt") + public void testAnnotationClassDefaultValues() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt"); + } + @TestMetadata("AnnotationInAnnotationArguments.kt") public void testAnnotationInAnnotationArguments() throws Exception { runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt"); diff --git a/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java index 318511b453e..e62b787a0b5 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/jvm/compiler/javac/LoadJavaUsingJavacTestGenerated.java @@ -4575,6 +4575,11 @@ public class LoadJavaUsingJavacTestGenerated extends AbstractLoadJavaUsingJavacT KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations"), Pattern.compile("^(.+)\\.kt$"), null, true); } + @TestMetadata("annotationClassDefaultValues.kt") + public void testAnnotationClassDefaultValues() throws Exception { + runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/annotationClassDefaultValues.kt"); + } + @TestMetadata("AnnotationInAnnotationArguments.kt") public void testAnnotationInAnnotationArguments() throws Exception { runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt");