[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
This commit is contained in:
Leonid Startsev
2023-04-24 18:32:13 +02:00
committed by Space Team
parent d757847ed6
commit c4255f9a9e
34 changed files with 797 additions and 157 deletions
@@ -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); 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 @Test
@TestMetadata("AnnotationInAnnotationArguments.kt") @TestMetadata("AnnotationInAnnotationArguments.kt")
public void testAnnotationInAnnotationArguments() throws Exception { public void testAnnotationInAnnotationArguments() throws Exception {
@@ -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); 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 @Test
@TestMetadata("AnnotationInAnnotationArguments.kt") @TestMetadata("AnnotationInAnnotationArguments.kt")
public void testAnnotationInAnnotationArguments() throws Exception { public void testAnnotationInAnnotationArguments() throws Exception {
@@ -164,6 +164,15 @@ abstract class AbstractAnnotationDeserializer(
): List<FirAnnotation> { ): List<FirAnnotation> {
return emptyList() 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<FirAnnotation> abstract fun loadTypeAnnotations(typeProto: ProtoBuf.Type, nameResolver: NameResolver): List<FirAnnotation>
@@ -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
)
}
}
@@ -448,7 +448,20 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
) )
} }
this.containerSource = c.containerSource 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) deprecationsProvider = annotations.getDeprecationsProviderFromAnnotations(c.session, fromJava = false)
proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers, ::loadContextReceiver) proto.contextReceiverTypes(c.typeTable).mapTo(contextReceivers, ::loadContextReceiver)
+1
View File
@@ -17,6 +17,7 @@ dependencies {
compileOnly(project(":compiler:ir.backend.common")) compileOnly(project(":compiler:ir.backend.common"))
compileOnly(project(":compiler:ir.serialization.common")) compileOnly(project(":compiler:ir.serialization.common"))
compileOnly(project(":compiler:fir:fir-serialization")) compileOnly(project(":compiler:fir:fir-serialization"))
compileOnly(project(":compiler:fir:fir-deserialization"))
compileOnly(intellijCore()) compileOnly(intellijCore())
@@ -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.isSealed
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
import org.jetbrains.kotlin.fir.declarations.utils.visibility 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.*
import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock
import org.jetbrains.kotlin.fir.expressions.impl.FirElseIfTrueCondition 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 { override fun visitElvisExpression(elvisExpression: FirElvisExpression, data: Any?): IrElement {
val firLhsVariable = buildProperty { val firLhsVariable = buildProperty {
source = elvisExpression.source source = elvisExpression.source
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.lazy
import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.descriptors.DescriptorVisibility
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.isAnnotationClass
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter 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.*
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall 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.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.types.IrErrorType 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 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
class Fir2IrLazyProperty( class Fir2IrLazyProperty(
components: Fir2IrComponents, private val components: Fir2IrComponents,
override val startOffset: Int, override val startOffset: Int,
override val endOffset: Int, override val endOffset: Int,
override var origin: IrDeclarationOrigin, override var origin: IrDeclarationOrigin,
@@ -93,12 +95,22 @@ class Fir2IrLazyProperty(
} }
private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? { private fun toIrInitializer(initializer: FirExpression?): IrExpressionBody? {
return if (initializer is FirConstExpression<*>) { // Annotations need full initializer information to instantiate them correctly
// TODO: Normally we shouldn't have error type here return when {
val constType = with(typeConverter) { initializer.typeRef.toIrType().takeIf { it !is IrErrorType } ?: type } containingClass?.classKind?.isAnnotationClass == true -> {
factory.createExpressionBody(initializer.toIrConst(constType)) when (val elem = initializer?.accept(Fir2IrVisitor(components, Fir2IrConversionScope()), null)) {
} else { is IrExpressionBody -> elem
null 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
} }
} }
@@ -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) { return when (this) {
is Byte -> buildConstExpression(null, ConstantValueKind.Byte, this).setProperType(session) is Byte -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedByte else ConstantValueKind.Byte, this).setProperType(session)
is Short -> buildConstExpression(null, ConstantValueKind.Short, this).setProperType(session) is Short -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedShort else ConstantValueKind.Short, this).setProperType(session)
is Int -> buildConstExpression(null, ConstantValueKind.Int, this).setProperType(session) is Int -> buildConstExpression(null, if (unsigned) ConstantValueKind.UnsignedInt else ConstantValueKind.Int, this).setProperType(session)
is Long -> buildConstExpression(null, ConstantValueKind.Long, 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 Char -> buildConstExpression(null, ConstantValueKind.Char, this).setProperType(session)
is Float -> buildConstExpression(null, ConstantValueKind.Float, this).setProperType(session) is Float -> buildConstExpression(null, ConstantValueKind.Float, this).setProperType(session)
is Double -> buildConstExpression(null, ConstantValueKind.Double, this).setProperType(session) is Double -> buildConstExpression(null, ConstantValueKind.Double, this).setProperType(session)
@@ -7,157 +7,142 @@ package org.jetbrains.kotlin.fir.java.deserialization
import org.jetbrains.kotlin.SpecialJvmAnnotations import org.jetbrains.kotlin.SpecialJvmAnnotations
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.deserialization.toQualifiedPropertyAccessExpression
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.java.createConstantOrError import org.jetbrains.kotlin.fir.java.createConstantOrError
import org.jetbrains.kotlin.fir.languageVersionSettings 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.getClassDeclaredPropertySymbols
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef 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.java.JvmAbi
import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder import org.jetbrains.kotlin.load.kotlin.*
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass
import org.jetbrains.kotlin.load.kotlin.findKotlinClass
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue import org.jetbrains.kotlin.resolve.constants.ClassLiteralValue
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.utils.toMetadataVersion import org.jetbrains.kotlin.utils.toMetadataVersion
internal class AnnotationsLoader(private val session: FirSession, private val kotlinClassFinder: KotlinClassFinder) { 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<FirExpression>): 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<FirExpression>()
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<FirAnnotation>()
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<FirAnnotation>()
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( private fun loadAnnotation(
annotationClassId: ClassId, result: MutableList<FirAnnotation>, annotationClassId: ClassId, result: MutableList<FirAnnotation>, enumEntryReferenceCreator: (ClassId, Name) -> FirExpression
): KotlinJvmBinaryClass.AnnotationArgumentVisitor { ): KotlinJvmBinaryClass.AnnotationArgumentVisitor {
val lookupTag = annotationClassId.toLookupTag() val lookupTag = annotationClassId.toLookupTag()
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor { return object : AnnotationsLoaderVisitorImpl(enumEntryReferenceCreator) {
private val argumentMap = mutableMapOf<Name, FirExpression>() private val argumentMap = mutableMapOf<Name, FirExpression>()
override fun visit(name: Name?, value: Any?) { override fun visitExpression(name: Name?, expr: FirExpression) {
if (name != null) { if (name != null) argumentMap[name] = expr
argumentMap[name] = createConstant(value)
}
} }
private fun ClassLiteralValue.toFirClassReferenceExpression(): FirClassReferenceExpression { override val visitNullNames: Boolean = false
val resolvedClassTypeRef = classId.toLookupTag().toDefaultResolvedTypeRef()
return buildClassReferenceExpression {
classTypeRef = resolvedClassTypeRef
typeRef = buildResolvedTypeRef {
type = StandardClassIds.KClass.constructClassLikeType(arrayOf(resolvedClassTypeRef.type), false)
}
}
}
private fun ClassId.toEnumEntryReferenceExpression(name: Name): FirExpression { override fun guessArrayTypeIfNeeded(name: Name?, arrayOfElements: List<FirExpression>): FirTypeRef? {
return buildPropertyAccessExpression { // Needed if we load a default value which is another annotation that has array value in it. e.g.:
val entryPropertySymbol = // To instantiate Deprecated() we need a default value for ReplaceWith() that has imports: Array<String> with default value [].
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? {
if (name == null) return null if (name == null) return null
return object : KotlinJvmBinaryClass.AnnotationArrayArgumentVisitor { // Note: generally we are not allowed to resolve anything, as this is might lead to recursive resolve problems
private val elements = mutableListOf<FirExpression>() // However, K1 deserializer did exactly the same and no issues were reported.
val propS = session.symbolProvider.getClassDeclaredPropertySymbols(annotationClassId, name).firstOrNull()
override fun visit(value: Any?) { return propS?.resolvedReturnTypeRef
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<FirAnnotation>()
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<FirAnnotation>()
val visitor = loadAnnotation(classId, list)
return object : KotlinJvmBinaryClass.AnnotationArgumentVisitor by visitor {
override fun visitEnd() {
visitor.visitEnd()
argumentMap[name] = list.single()
}
}
} }
override fun visitEnd() { override fun visitEnd() {
@@ -173,9 +158,35 @@ internal class AnnotationsLoader(private val session: FirSession, private val ko
} }
} }
} }
}
}
private fun createConstant(value: Any?): FirExpression { internal fun loadAnnotationMethodDefaultValue(
return value.createConstantOrError(session) 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<FirExpression>): 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 classReference = getClassCall.argument as? FirClassReferenceExpression ?: return false
val containerType = classReference.classTypeRef.coneType as? ConeClassLikeType ?: return false val containerType = classReference.classTypeRef.coneType as? ConeClassLikeType ?: return false
val classId = containerType.lookupTag.classId val classId = containerType.lookupTag.classId
if (classId.outerClassId == null || if (classId.outerClassId == null || classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME
classId.shortClassName.asString() != JvmAbi.REPEATABLE_ANNOTATION_CONTAINER_NAME
) return false ) return false
val klass = kotlinClassFinder.findKotlinClass(classId, session.languageVersionSettings.languageVersion.toMetadataVersion()) 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<FirAnnotation>, annotationClassId: ClassId, result: MutableList<FirAnnotation>,
): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { ): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
if (annotationClassId in SpecialJvmAnnotations.SPECIAL_ANNOTATIONS) return null 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 = private fun ConeClassLikeLookupTag.toDefaultResolvedTypeRef(): FirResolvedTypeRef =
buildResolvedTypeRef { buildResolvedTypeRef {
type = constructClassType(emptyArray(), isNullable = false) 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
}
} }
@@ -10,10 +10,19 @@ import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer import org.jetbrains.kotlin.fir.deserialization.AbstractAnnotationDeserializer
import org.jetbrains.kotlin.fir.expressions.FirAnnotation 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.expressions.builder.buildAnnotation
import org.jetbrains.kotlin.fir.java.createConstantIfAny
import org.jetbrains.kotlin.fir.languageVersionSettings 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.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.ProtoBuf
import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.metadata.deserialization.*
import org.jetbrains.kotlin.metadata.jvm.JvmProtoBuf 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.protobuf.MessageLite
import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource 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.addToStdlib.runIf
import org.jetbrains.kotlin.utils.toMetadataVersion import org.jetbrains.kotlin.utils.toMetadataVersion
@@ -197,6 +207,24 @@ class JvmBinaryAnnotationDeserializer(
return findJvmBinaryClassAndLoadMemberAnnotations(paramSignature) 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 <T> ConstantValueKind<T>.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 { private fun computeJvmParameterIndexShift(classProto: ProtoBuf.Class?, message: MessageLite): Int {
return when (message) { return when (message) {
is ProtoBuf.Function -> if (message.hasReceiver()) 1 else 0 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 // TODO: Rename this once property constants are recorded as well
private data class MemberAnnotations(val memberAnnotations: MutableMap<MemberSignature, MutableList<FirAnnotation>>) private data class MemberAnnotations(
val memberAnnotations: MutableMap<MemberSignature, MutableList<FirAnnotation>>,
val annotationMethodsDefaultValues: Map<MemberSignature, FirExpression>
)
// TODO: better to be in KotlinDeserializedJvmSymbolsProvider? // TODO: better to be in KotlinDeserializedJvmSymbolsProvider?
private fun FirSession.loadMemberAnnotations( private fun FirSession.loadMemberAnnotations(
@@ -278,6 +309,7 @@ private fun FirSession.loadMemberAnnotations(
): MemberAnnotations { ): MemberAnnotations {
val memberAnnotations = hashMapOf<MemberSignature, MutableList<FirAnnotation>>() val memberAnnotations = hashMapOf<MemberSignature, MutableList<FirAnnotation>>()
val annotationsLoader = AnnotationsLoader(this, kotlinClassFinder) val annotationsLoader = AnnotationsLoader(this, kotlinClassFinder)
val annotationMethodsDefaultValues = hashMapOf<MemberSignature, FirExpression>()
kotlinBinaryClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor { kotlinBinaryClass.visitMembers(object : KotlinJvmBinaryClass.MemberVisitor {
override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor { override fun visitMethod(name: Name, desc: String): KotlinJvmBinaryClass.MethodAnnotationVisitor {
@@ -288,6 +320,7 @@ private fun FirSession.loadMemberAnnotations(
val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc) val signature = MemberSignature.fromFieldNameAndDesc(name.asString(), desc)
if (initializer != null) { if (initializer != null) {
// TODO: load constant // TODO: load constant
// TODO: Given there is FirConstDeserializer, maybe this comment is obsolete?
} }
return MemberAnnotationVisitor(signature) return MemberAnnotationVisitor(signature)
} }
@@ -310,8 +343,7 @@ private fun FirSession.loadMemberAnnotations(
} }
override fun visitAnnotationMemberDefaultValue(): KotlinJvmBinaryClass.AnnotationArgumentVisitor? { override fun visitAnnotationMemberDefaultValue(): KotlinJvmBinaryClass.AnnotationArgumentVisitor? {
// TODO: load annotation default values to properly support annotation instantiation feature return annotationsLoader.loadAnnotationMethodDefaultValue(signature) { annotationMethodsDefaultValues[signature] = it }
return null
} }
} }
@@ -330,5 +362,9 @@ private fun FirSession.loadMemberAnnotations(
} }
}, byteContent) }, byteContent)
return MemberAnnotations(memberAnnotations)
return MemberAnnotations(
memberAnnotations,
annotationMethodsDefaultValues
)
} }
@@ -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<FirAnnotation>
abstract val enumClassId: ClassId
abstract val enumEntryName: Name
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitEnumEntryDeserializedAccessExpression(this, data)
@Suppress("UNCHECKED_CAST")
override fun <E : FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
transformer.transformEnumEntryDeserializedAccessExpression(this, data) as E
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
abstract override fun replaceAnnotations(newAnnotations: List<FirAnnotation>)
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirEnumEntryDeserializedAccessExpression
}
@@ -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<FirAnnotation> = 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()
}
@@ -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<FirAnnotation>,
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 <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
typeRef.accept(visitor, data)
annotations.forEach { it.accept(visitor, data) }
}
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirEnumEntryDeserializedAccessExpressionImpl {
typeRef = typeRef.transform(transformer, data)
transformAnnotations(transformer, data)
return this
}
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirEnumEntryDeserializedAccessExpressionImpl {
annotations.transformInplace(transformer, data)
return this
}
override fun replaceTypeRef(newTypeRef: FirTypeRef) {
typeRef = newTypeRef
}
override fun replaceAnnotations(newAnnotations: List<FirAnnotation>) {
annotations = newAnnotations.toMutableOrEmpty()
}
}
@@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression 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.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -279,6 +280,8 @@ abstract class FirDefaultVisitor<out R, in D> : FirVisitor<R, D>() {
override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R = visitWrappedExpression(wrappedDelegateExpression, data) 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 visitNamedReference(namedReference: FirNamedReference, data: D): R = visitReference(namedReference, data)
override fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase, data: D): R = visitNamedReference(namedReferenceWithCandidateBase, data) override fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase, data: D): R = visitNamedReference(namedReferenceWithCandidateBase, data)
@@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression 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.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -279,6 +280,8 @@ abstract class FirDefaultVisitorVoid : FirVisitorVoid() {
override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) = visitWrappedExpression(wrappedDelegateExpression) override fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression) = visitWrappedExpression(wrappedDelegateExpression)
override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression) = visitExpression(enumEntryDeserializedAccessExpression)
override fun visitNamedReference(namedReference: FirNamedReference) = visitReference(namedReference) override fun visitNamedReference(namedReference: FirNamedReference) = visitReference(namedReference)
override fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase) = visitNamedReference(namedReferenceWithCandidateBase) override fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase) = visitNamedReference(namedReferenceWithCandidateBase)
@@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression 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.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -652,6 +653,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformElement(wrappedDelegateExpression, data) return transformElement(wrappedDelegateExpression, data)
} }
open fun transformEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: D): FirStatement {
return transformElement(enumEntryDeserializedAccessExpression, data)
}
open fun transformNamedReference(namedReference: FirNamedReference, data: D): FirReference { open fun transformNamedReference(namedReference: FirNamedReference, data: D): FirReference {
return transformElement(namedReference, data) return transformElement(namedReference, data)
} }
@@ -1248,6 +1253,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
return transformWrappedDelegateExpression(wrappedDelegateExpression, data) 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 { final override fun visitNamedReference(namedReference: FirNamedReference, data: D): FirReference {
return transformNamedReference(namedReference, data) return transformNamedReference(namedReference, data)
} }
@@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression 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.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -407,6 +408,8 @@ abstract class FirVisitor<out R, in D> {
open fun visitWrappedDelegateExpression(wrappedDelegateExpression: FirWrappedDelegateExpression, data: D): R = visitElement(wrappedDelegateExpression, data) 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 visitNamedReference(namedReference: FirNamedReference, data: D): R = visitElement(namedReference, data)
open fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase, data: D): R = visitElement(namedReferenceWithCandidateBase, data) open fun visitNamedReferenceWithCandidateBase(namedReferenceWithCandidateBase: FirNamedReferenceWithCandidateBase, data: D): R = visitElement(namedReferenceWithCandidateBase, data)
@@ -128,6 +128,7 @@ import org.jetbrains.kotlin.fir.expressions.FirVariableAssignment
import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression import org.jetbrains.kotlin.fir.expressions.FirWhenSubjectExpression
import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression import org.jetbrains.kotlin.fir.expressions.FirDesugaredAssignmentValueReferenceExpression
import org.jetbrains.kotlin.fir.expressions.FirWrappedDelegateExpression 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.FirNamedReference
import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase import org.jetbrains.kotlin.fir.references.FirNamedReferenceWithCandidateBase
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
@@ -651,6 +652,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitElement(wrappedDelegateExpression) visitElement(wrappedDelegateExpression)
} }
open fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression) {
visitElement(enumEntryDeserializedAccessExpression)
}
open fun visitNamedReference(namedReference: FirNamedReference) { open fun visitNamedReference(namedReference: FirNamedReference) {
visitElement(namedReference) visitElement(namedReference)
} }
@@ -1247,6 +1252,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitWrappedDelegateExpression(wrappedDelegateExpression) visitWrappedDelegateExpression(wrappedDelegateExpression)
} }
final override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression, data: Nothing?) {
visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression)
}
final override fun visitNamedReference(namedReference: FirNamedReference, data: Nothing?) { final override fun visitNamedReference(namedReference: FirNamedReference, data: Nothing?) {
visitNamedReference(namedReference) visitNamedReference(namedReference)
} }
@@ -651,6 +651,12 @@ class FirRenderer(
wrappedDelegateExpression.expression.accept(this) wrappedDelegateExpression.expression.accept(this)
} }
override fun visitEnumEntryDeserializedAccessExpression(enumEntryDeserializedAccessExpression: FirEnumEntryDeserializedAccessExpression) {
with(enumEntryDeserializedAccessExpression) {
print("$enumClassId.$enumEntryName")
}
}
override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) { override fun visitNamedArgumentExpression(namedArgumentExpression: FirNamedArgumentExpression) {
print(namedArgumentExpression.name) print(namedArgumentExpression.name)
print(" = ") print(" = ")
@@ -156,6 +156,8 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
val wrappedDelegateExpression by element(Expression, wrappedExpression) val wrappedDelegateExpression by element(Expression, wrappedExpression)
val enumEntryDeserializedAccessExpression by element(Expression, expression)
val namedReference by element(Reference, reference) val namedReference by element(Reference, reference)
val namedReferenceWithCandidateBase by element(Reference, namedReference) val namedReferenceWithCandidateBase by element(Reference, namedReference)
val errorNamedReference by element(Reference, namedReference, diagnosticHolder) val errorNamedReference by element(Reference, namedReference, diagnosticHolder)
@@ -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) { impl(smartCastExpression) {
default("isStable") { default("isStable") {
value = "smartcastStability == SmartcastStability.STABLE_VALUE" value = "smartcastStability == SmartcastStability.STABLE_VALUE"
@@ -644,6 +644,11 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
+field("delegateProvider", expression).withReplace() +field("delegateProvider", expression).withReplace()
} }
enumEntryDeserializedAccessExpression.configure {
+field("enumClassId", classIdType)
+field("enumEntryName", nameType)
}
namedReference.configure { namedReference.configure {
+name +name
} }
@@ -10,4 +10,8 @@ import org.jetbrains.kotlin.fir.tree.generator.model.ArbitraryImportable
val phaseAsResolveStateExtentionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "asResolveState") val phaseAsResolveStateExtentionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "asResolveState")
val resolvePhaseExtensionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "resolvePhase") val resolvePhaseExtensionImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "resolvePhase")
val resolveStateAccessImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "ResolveStateAccess") val resolveStateAccessImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations", "ResolveStateAccess")
val resolvedDeclarationStatusImport = ArbitraryImportable("org.jetbrains.kotlin.fir.declarations.impl", "FirResolvedDeclarationStatusImpl") 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")
@@ -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 // TARGET_BACKEND: JVM_IR
// IGNORE_DEXING // IGNORE_DEXING
// WITH_STDLIB // WITH_STDLIB
@@ -26,6 +23,12 @@ annotation class UnsignedValue(
val uint: UInt = 2147483657U // Int.MAX_VALUE + 10 val uint: UInt = 2147483657U // Int.MAX_VALUE + 10
) )
annotation class Outer(
val array: Array<Inner> = [Inner(1), Inner(2)]
) {
annotation class Inner(val v: Int = 0)
}
// MODULE: app(lib) // MODULE: app(lib)
// FILE: app.kt // FILE: app.kt
@@ -45,6 +48,7 @@ class C {
fun three(): Deprecated = Deprecated("foo") fun three(): Deprecated = Deprecated("foo")
fun four(): OtherArrays = OtherArrays() fun four(): OtherArrays = OtherArrays()
fun five(): UnsignedValue = UnsignedValue() fun five(): UnsignedValue = UnsignedValue()
fun six(): Outer = Outer()
} }
fun box(): String { fun box(): String {
@@ -58,10 +62,13 @@ fun box(): String {
"""@kotlin.Deprecated(level=WARNING, message=foo, replaceWith=@kotlin.ReplaceWith(expression=, imports=[]))""", """@kotlin.Deprecated(level=WARNING, message=foo, replaceWith=@kotlin.ReplaceWith(expression=, imports=[]))""",
C().three().toString() C().three().toString()
) )
assertEquals( val otherArraysStr = C().four().toString()
"""@a.OtherArrays(annotationsArray=[], doublesArray=[], enumArray=[], namesArray=[@kotlin.jvm.JvmName(name=foo)])""", // K1 and K2 have different properties order after metadata deserialization
C().four().toString() 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(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" return "OK"
} }
@@ -3,7 +3,7 @@
@R|test/Ann|(value = String(OK)) public final typealias A2 = R|kotlin/String| @R|test/Ann|(value = String(OK)) public final typealias A2 = R|kotlin/String|
@R|kotlin/annotation/Target|(allowedTargets = <implicitArrayOf>(R|kotlin/annotation/AnnotationTarget.TYPEALIAS|)) public final annotation class Ann : R|kotlin/Annotation| { @R|kotlin/annotation/Target|(allowedTargets = <implicitArrayOf>(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 get(): R|kotlin/String|
public constructor(value: R|kotlin/String| = STUB): R|test/Ann| public constructor(value: R|kotlin/String| = STUB): R|test/Ann|
@@ -0,0 +1,73 @@
public final annotation class A : R|kotlin/Annotation| {
public final val aI: R|kotlin/IntArray| = <implicitArrayOf>(Int(1), Int(2))
public get(): R|kotlin/IntArray|
public final val aS: R|kotlin/Array<kotlin/String>| = <implicitArrayOf>(String(a), String(b))
public get(): R|kotlin/Array<kotlin/String>|
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<*>| = <getClass>(<getClass>(R|kotlin/Int|))
public get(): R|kotlin/reflect/KClass<*>|
public final val kClassArray: R|kotlin/Array<kotlin/reflect/KClass<*>>| = <implicitArrayOf>(<getClass>(<getClass>(R|test/A|)))
public get(): R|kotlin/Array<kotlin/reflect/KClass<*>>|
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<kotlin/reflect/KClass<*>>| = STUB, e: R|test/E| = STUB, anno: R|test/Empty| = STUB, aS: R|kotlin/Array<kotlin/String>| = STUB, aI: R|kotlin/IntArray| = STUB): R|test/A|
}
public final enum class E : R|kotlin/Enum<test/E>| {
private constructor(): R|test/E|
public final static enum entry E0: R|test/E|
public final static fun values(): R|kotlin/Array<test/E>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|test/E| {
}
public final static val entries: R|kotlin/enums/EnumEntries<test/E>|
public get(): R|kotlin/enums/EnumEntries<test/E>|
}
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<kotlin/jvm/JvmStatic>| = <implicitArrayOf>()
public get(): R|kotlin/Array<kotlin/jvm/JvmStatic>|
public final val doublesArray: R|kotlin/DoubleArray| = <implicitArrayOf>(Double(1.5))
public get(): R|kotlin/DoubleArray|
public final val enumArray: R|kotlin/Array<kotlin/text/RegexOption>| = <implicitArrayOf>(kotlin/text/RegexOption.IGNORE_CASE)
public get(): R|kotlin/Array<kotlin/text/RegexOption>|
public final val namesArray: R|kotlin/Array<kotlin/jvm/JvmName>| = <implicitArrayOf>(@R|kotlin/jvm/JvmName|(name = String(foo)) )
public get(): R|kotlin/Array<kotlin/jvm/JvmName>|
public constructor(doublesArray: R|kotlin/DoubleArray| = STUB, enumArray: R|kotlin/Array<kotlin/text/RegexOption>| = STUB, annotationsArray: R|kotlin/Array<kotlin/jvm/JvmStatic>| = STUB, namesArray: R|kotlin/Array<kotlin/jvm/JvmName>| = 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|
}
@@ -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<*>| = <getClass>(<getClass>(R|kotlin/Int|))
public get(): R|kotlin/reflect/KClass<*>|
public final val kClassArray: R|kotlin/Array<kotlin/reflect/KClass<*>>| = <implicitArrayOf>(<getClass>(<getClass>(R|test/A|)))
public get(): R|kotlin/Array<kotlin/reflect/KClass<*>>|
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<kotlin/String>| = <implicitArrayOf>(String(a), String(b))
public get(): R|kotlin/Array<kotlin/String>|
public final val aI: R|kotlin/IntArray| = <implicitArrayOf>(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<kotlin/reflect/KClass<*>>| = STUB, e: R|test/E| = STUB, anno: R|test/Empty| = STUB, aS: R|kotlin/Array<kotlin/String>| = STUB, aI: R|kotlin/IntArray| = STUB): R|test/A|
}
public final enum class E : R|kotlin/Enum<test/E>| {
private constructor(): R|test/E|
public final static enum entry E0: R|test/E|
public final static fun values(): R|kotlin/Array<test/E>| {
}
public final static fun valueOf(value: R|kotlin/String|): R|test/E| {
}
public final static val entries: R|kotlin/enums/EnumEntries<test/E>|
public get(): R|kotlin/enums/EnumEntries<test/E>|
}
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| = <implicitArrayOf>(Double(1.5))
public get(): R|kotlin/DoubleArray|
public final val enumArray: R|kotlin/Array<kotlin/text/RegexOption>| = <implicitArrayOf>(kotlin/text/RegexOption.IGNORE_CASE)
public get(): R|kotlin/Array<kotlin/text/RegexOption>|
public final val annotationsArray: R|kotlin/Array<kotlin/jvm/JvmStatic>| = <implicitArrayOf>()
public get(): R|kotlin/Array<kotlin/jvm/JvmStatic>|
public final val namesArray: R|kotlin/Array<kotlin/jvm/JvmName>| = <implicitArrayOf>(@R|kotlin/jvm/JvmName|(name = String(foo)) )
public get(): R|kotlin/Array<kotlin/jvm/JvmName>|
public constructor(doublesArray: R|kotlin/DoubleArray| = STUB, enumArray: R|kotlin/Array<kotlin/text/RegexOption>| = STUB, annotationsArray: R|kotlin/Array<kotlin/jvm/JvmStatic>| = STUB, namesArray: R|kotlin/Array<kotlin/jvm/JvmName>| = 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|
}
@@ -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<KClass<*>> = [A::class],
val e: E = E.E0,
val anno: Empty = Empty(),
val aS: Array<String> = arrayOf("a", "b"),
val aI: IntArray = intArrayOf(1, 2)
)
annotation class OtherArrays(
val doublesArray: DoubleArray = [1.5],
val enumArray: Array<kotlin.text.RegexOption> = [kotlin.text.RegexOption.IGNORE_CASE],
val annotationsArray: Array<JvmStatic> = [],
val namesArray: Array<JvmName> = [JvmName("foo")]
)
annotation class UnsignedValue(
val uint: UInt = 2147483657U // Int.MAX_VALUE + 10
)
@@ -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<kotlin.reflect.KClass<*>> = ..., /*4*/ e: test.E = ..., /*5*/ anno: test.Empty = ..., /*6*/ aS: kotlin.Array<kotlin.String> = ..., /*7*/ aI: kotlin.IntArray = ...)
public final val aI: kotlin.IntArray = {1, 2}
public final fun `<get-aI>`(): kotlin.IntArray
public final val aS: kotlin.Array<kotlin.String> = {"a", "b"}
public final fun `<get-aS>`(): kotlin.Array<kotlin.String>
public final val anno: test.Empty = test.Empty
public final fun `<get-anno>`(): test.Empty
public final val e: test.E = E.E0
public final fun `<get-e>`(): test.E
public final val i: kotlin.Int = 42
public final fun `<get-i>`(): kotlin.Int
public final val kClass: kotlin.reflect.KClass<*> = kotlin.Int::class
public final fun `<get-kClass>`(): kotlin.reflect.KClass<*>
public final val kClassArray: kotlin.Array<kotlin.reflect.KClass<*>> = {test.A::class}
public final fun `<get-kClassArray>`(): kotlin.Array<kotlin.reflect.KClass<*>>
public final val s: kotlin.String = "foo"
public final fun `<get-s>`(): kotlin.String
}
public final enum class E : kotlin.Enum<test.E> {
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 `<get-name>`(): kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
public final override /*1*/ /*fake_override*/ fun `<get-ordinal>`(): 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<test.E!>!
// Static members
public final /*synthesized*/ val entries: kotlin.enums.EnumEntries<test.E>
public final /*synthesized*/ fun `<get-entries>`(): kotlin.enums.EnumEntries<test.E>
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): test.E
public final /*synthesized*/ fun values(): kotlin.Array<test.E>
}
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<kotlin.text.RegexOption> = ..., /*2*/ annotationsArray: kotlin.Array<kotlin.jvm.JvmStatic> = ..., /*3*/ namesArray: kotlin.Array<kotlin.jvm.JvmName> = ...)
public final val annotationsArray: kotlin.Array<kotlin.jvm.JvmStatic> = {}
public final fun `<get-annotationsArray>`(): kotlin.Array<kotlin.jvm.JvmStatic>
public final val doublesArray: kotlin.DoubleArray = {1.5.toDouble()}
public final fun `<get-doublesArray>`(): kotlin.DoubleArray
public final val enumArray: kotlin.Array<kotlin.text.RegexOption> = {RegexOption.IGNORE_CASE}
public final fun `<get-enumArray>`(): kotlin.Array<kotlin.text.RegexOption>
public final val namesArray: kotlin.Array<kotlin.jvm.JvmName> = {kotlin.jvm.JvmName(name = "foo")}
public final fun `<get-namesArray>`(): kotlin.Array<kotlin.jvm.JvmName>
}
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 `<get-uint>`(): kotlin.UInt
}
@@ -1,8 +1,8 @@
public final annotation class Anno : R|kotlin/Annotation| { 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 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 get(): R|kotlin/Int|
public constructor(value: R|kotlin/String| = STUB, x: R|kotlin/Int| = STUB): R|test/Anno| public constructor(value: R|kotlin/String| = STUB, x: R|kotlin/Int| = STUB): R|test/Anno|
@@ -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); 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") @TestMetadata("AnnotationInAnnotationArguments.kt")
public void testAnnotationInAnnotationArguments() throws Exception { public void testAnnotationInAnnotationArguments() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt"); runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt");
@@ -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); 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") @TestMetadata("AnnotationInAnnotationArguments.kt")
public void testAnnotationInAnnotationArguments() throws Exception { public void testAnnotationInAnnotationArguments() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt"); runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt");
@@ -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); 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") @TestMetadata("AnnotationInAnnotationArguments.kt")
public void testAnnotationInAnnotationArguments() throws Exception { public void testAnnotationInAnnotationArguments() throws Exception {
runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt"); runTest("compiler/testData/loadJava/compiledKotlinWithStdlib/annotations/AnnotationInAnnotationArguments.kt");