diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt index fc899f9dd0e..3ce4bf2658f 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/PropertyAndAccessor.txt @@ -17,7 +17,7 @@ public final annotation class B : R|kotlin/Annotation| { public abstract interface I : R|kotlin/Any| { public abstract var getterAndSetter: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(: R|kotlin/Int|): R|kotlin/Unit| public abstract var propertyAndGetter: R|kotlin/Int| public get(): R|kotlin/Int| @@ -25,6 +25,6 @@ public abstract interface I : R|kotlin/Any| { public abstract var propertyAndSetter: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(: R|kotlin/Int|): R|kotlin/Unit| } diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt index df9e7dfa2d6..370baf4c7cd 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/annotations/withUseSiteTarget/ReceiverTarget.txt @@ -6,7 +6,7 @@ public final class A : R|kotlin/Any| { public final var R|kotlin/String|.myLength3: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(v: R|kotlin/Int|): R|kotlin/Unit| public constructor(): R|test/A| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInClassStaticFields.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInClassStaticFields.txt index 2aebb26c584..a1c01812abb 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInClassStaticFields.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInClassStaticFields.txt @@ -12,7 +12,7 @@ public final class Test : R|kotlin/Any| { public final var prop2: R|kotlin/Int| public get(): R|kotlin/Int| - protected set(value: R|kotlin/Int|): R|kotlin/Unit| + protected set(: R|kotlin/Int|): R|kotlin/Unit| public final val prop3: R|kotlin/Int| public get(): R|kotlin/Int| @@ -27,7 +27,7 @@ public final class Test : R|kotlin/Any| { public final var prop7: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(i: R|kotlin/Int|): R|kotlin/Unit| private constructor(): R|test/Test.Companion| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInTraitStaticFields.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInTraitStaticFields.txt index bc0a1859613..d6ff42670cd 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInTraitStaticFields.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/classObject/ClassObjectInTraitStaticFields.txt @@ -10,7 +10,7 @@ public abstract interface Test : R|kotlin/Any| { public final var prop2: R|kotlin/Int| public get(): R|kotlin/Int| - protected set(value: R|kotlin/Int|): R|kotlin/Unit| + protected set(: R|kotlin/Int|): R|kotlin/Unit| public final val prop3: R|kotlin/Int| public get(): R|kotlin/Int| @@ -25,7 +25,7 @@ public abstract interface Test : R|kotlin/Any| { public final var prop7: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(i: R|kotlin/Int|): R|kotlin/Unit| private constructor(): R|test/Test.Companion| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt index 2d682a51c57..02082641b98 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarInClass.txt @@ -1,7 +1,7 @@ public final class ExtPropInClass : R|kotlin/Any| { public final var R|kotlin/Int|.itIs: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(p: R|kotlin/Int|): R|kotlin/Unit| public constructor(): R|test/ExtPropInClass| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt index 2307e36a632..b52fdbf0359 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTInClass.txt @@ -1,7 +1,7 @@ public final class ExtValInClass

: R|kotlin/Any| { public final var R|kotlin/Int|.asas: R|P| public get(): R|P| - public set(value: R|P|): R|kotlin/Unit| + public set(p: R|P|): R|kotlin/Unit| public constructor

(): R|test/ExtValInClass

| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt index 8062ac3845a..1e7605e1d0b 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarIntTQInClass.txt @@ -1,7 +1,7 @@ public final class ExtValInClass

: R|kotlin/Any| { public final var R|kotlin/Int|.asas: R|P?| public get(): R|P?| - public set(value: R|P?|): R|kotlin/Unit| + public set(p: R|P?|): R|kotlin/Unit| public constructor

(): R|test/ExtValInClass

| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt index 1f4a4e58946..c800dbf7b82 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTIntInClass.txt @@ -1,7 +1,7 @@ public final class ExtValPIntInClass

: R|kotlin/Any| { public final var R|P|.asas: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(p: R|kotlin/Int|): R|kotlin/Unit| public constructor

(): R|test/ExtValPIntInClass

| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt index bfc9a67dae0..4fab7434828 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/ExtVarTQIntInClass.txt @@ -1,7 +1,7 @@ public final class ExtValPIntInClass

: R|kotlin/Any| { public final var R|P?|.asas: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(p: R|kotlin/Int|): R|kotlin/Unit| public constructor

(): R|test/ExtValPIntInClass

| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/VarWithDelegated.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/VarWithDelegated.txt index e56a53ac2b3..beb63fdc7d5 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/VarWithDelegated.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/VarWithDelegated.txt @@ -1,7 +1,7 @@ public final class A : R|kotlin/Any| { public final var a: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(: R|kotlin/Int|): R|kotlin/Unit| public constructor(): R|test/A| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarModality.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarModality.txt index e9a9b1d9dd5..3b01cf57dd4 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarModality.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarModality.txt @@ -13,7 +13,7 @@ public open class ClassVarModality : R|kotlin/Any| { internal final var property4: R|kotlin/Int| internal get(): R|kotlin/Int| - private set(value: R|kotlin/Int|): R|kotlin/Unit| + private set(: R|kotlin/Int|): R|kotlin/Unit| public constructor(): R|test/ClassVarModality| @@ -22,7 +22,7 @@ public open class ClassVarModality : R|kotlin/Any| { public abstract class ClassVarModalityAbstract : R|kotlin/Any| { public abstract var property1: R|java/util/Date| public get(): R|java/util/Date| - public set(value: R|java/util/Date|): R|kotlin/Unit| + public set(: R|java/util/Date|): R|kotlin/Unit| public constructor(): R|test/ClassVarModalityAbstract| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt index 6a157da5f2d..c2b8f2ea2c2 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/prop/defaultAccessors/ClassVarWithSet.txt @@ -1,39 +1,39 @@ public final class ClassVal : R|kotlin/Any| { public final var property1: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(: R|kotlin/Int|): R|kotlin/Unit| public final var property10: R|kotlin/Int| public get(): R|kotlin/Int| - protected set(value: R|kotlin/Int|): R|kotlin/Unit| + protected set(: R|kotlin/Int|): R|kotlin/Unit| public final var property11: R|kotlin/Int| public get(): R|kotlin/Int| - internal set(value: R|kotlin/Int|): R|kotlin/Unit| + internal set(: R|kotlin/Int|): R|kotlin/Unit| public final var property2: R|java/lang/Object| public get(): R|java/lang/Object| - protected set(value: R|java/lang/Object|): R|kotlin/Unit| + protected set(: R|java/lang/Object|): R|kotlin/Unit| public final var property3: R|java/lang/Object| public get(): R|java/lang/Object| - private set(value: R|java/lang/Object|): R|kotlin/Unit| + private set(: R|java/lang/Object|): R|kotlin/Unit| protected final var property4: R|kotlin/String| protected get(): R|kotlin/String| - protected set(value: R|kotlin/String|): R|kotlin/Unit| + protected set(: R|kotlin/String|): R|kotlin/Unit| protected final var property5: R|kotlin/String| protected get(): R|kotlin/String| - private set(value: R|kotlin/String|): R|kotlin/Unit| + private set(: R|kotlin/String|): R|kotlin/Unit| public final var property8: R|kotlin/Int| public get(): R|kotlin/Int| - public set(value: R|kotlin/Int|): R|kotlin/Unit| + public set(: R|kotlin/Int|): R|kotlin/Unit| public final var property9: R|kotlin/Int| public get(): R|kotlin/Int| - private set(value: R|kotlin/Int|): R|kotlin/Unit| + private set(: R|kotlin/Int|): R|kotlin/Unit| public constructor(): R|test/ClassVal| diff --git a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/visibility/PrivateClassMembers.txt b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/visibility/PrivateClassMembers.txt index 9b9a1d3dfb2..ca9abaa4bf6 100644 --- a/compiler/fir/analysis-tests/testData/loadCompiledKotlin/visibility/PrivateClassMembers.txt +++ b/compiler/fir/analysis-tests/testData/loadCompiledKotlin/visibility/PrivateClassMembers.txt @@ -6,7 +6,7 @@ public final class PrivateClassMembers : R|kotlin/Any| { private final var r: R|kotlin/Int| private get(): R|kotlin/Int| - private set(value: R|kotlin/Int|): R|kotlin/Unit| + private set(: R|kotlin/Int|): R|kotlin/Unit| private final val v: R|kotlin/Int| private get(): R|kotlin/Int| diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt index 9bd94eb6895..825d7be4c79 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/AbstractAnnotationDeserializer.kt @@ -56,6 +56,26 @@ abstract class AbstractAnnotationDeserializer( return annotations.map { deserializeAnnotation(it, nameResolver) } } + fun loadPropertyGetterAnnotations( + propertyProto: ProtoBuf.Property, + nameResolver: NameResolver, + getterFlags: Int + ): List { + if (!Flags.HAS_ANNOTATIONS.get(getterFlags)) return emptyList() + val annotations = propertyProto.getExtension(protocol.propertyGetterAnnotation).orEmpty() + return annotations.map { deserializeAnnotation(it, nameResolver) } + } + + fun loadPropertySetterAnnotations( + propertyProto: ProtoBuf.Property, + nameResolver: NameResolver, + setterFlags: Int + ): List { + if (!Flags.HAS_ANNOTATIONS.get(setterFlags)) return emptyList() + val annotations = propertyProto.getExtension(protocol.propertySetterAnnotation).orEmpty() + return annotations.map { deserializeAnnotation(it, nameResolver) } + } + fun loadConstructorAnnotations(constructorProto: ProtoBuf.Constructor, nameResolver: NameResolver): List { if (!Flags.HAS_ANNOTATIONS.get(constructorProto.flags)) return emptyList() val annotations = constructorProto.getExtension(protocol.constructorAnnotation).orEmpty() diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt index 210bf3bc716..62fd393835c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/deserialization/FirMemberDeserializer.kt @@ -20,15 +20,16 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl +import org.jetbrains.kotlin.fir.types.impl.FirImplicitUnitTypeRef import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.* import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.ProtoEnumFlags import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource import org.jetbrains.kotlin.serialization.deserialization.getName -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance class FirDeserializationContext( val nameResolver: NameResolver, @@ -172,13 +173,77 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { val symbol = FirPropertySymbol(CallableId(c.packageFqName, c.relativeClassName, callableName)) val local = c.childContext(proto.typeParameterList) - val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else flags - val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else flags + // Per documentation on Property.getter_flags in metadata.proto, if an accessor flags field is absent, its value should be computed + // by taking hasAnnotations/visibility/modality from property flags, and using false for the rest + val defaultAccessorFlags = Flags.getAccessorFlags( + Flags.HAS_ANNOTATIONS.get(flags), + Flags.VISIBILITY.get(flags), + Flags.MODALITY.get(flags), + false, false, false + ) + + val returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local) + + val getter = if (Flags.HAS_GETTER.get(flags)) { + val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else defaultAccessorFlags + val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags)) + val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(getterFlags)) + if (Flags.IS_NOT_DEFAULT.get(getterFlags)) { + buildPropertyAccessor { + session = c.session + origin = FirDeclarationOrigin.Library + this.returnTypeRef = returnTypeRef + isGetter = true + status = FirDeclarationStatusImpl(visibility, modality) + annotations += c.annotationDeserializer.loadPropertyGetterAnnotations(proto, local.nameResolver, getterFlags) + this.symbol = FirPropertyAccessorSymbol() + } + } else { + FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility) + } + } else { + null + } + + val setter = if (Flags.HAS_SETTER.get(flags)) { + val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else defaultAccessorFlags + val visibility = ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags)) + val modality = ProtoEnumFlags.modality(Flags.MODALITY.get(setterFlags)) + if (Flags.IS_NOT_DEFAULT.get(setterFlags)) { + buildPropertyAccessor { + session = c.session + origin = FirDeclarationOrigin.Library + this.returnTypeRef = FirImplicitUnitTypeRef(source) + isGetter = false + status = FirDeclarationStatusImpl(visibility, modality) + annotations += c.annotationDeserializer.loadPropertySetterAnnotations(proto, local.nameResolver, setterFlags) + this.symbol = FirPropertyAccessorSymbol() + valueParameters += proto.setterValueParameter.let { + val parameterFlags = if (it.hasFlags()) it.flags else 0 + buildValueParameter { + session = c.session + origin = FirDeclarationOrigin.Library + this.returnTypeRef = returnTypeRef + name = if (it.hasName()) c.nameResolver.getName(it.name) else Name.special("") + this.symbol = FirVariableSymbol(CallableId(FqName.ROOT, name)) + isCrossinline = Flags.IS_CROSSINLINE.get(parameterFlags) + isNoinline = Flags.IS_NOINLINE.get(parameterFlags) + isVararg = it.hasVarargElementType() + } + } + } + } else { + FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, visibility) + } + } else { + null + } + val isVar = Flags.IS_VAR.get(flags) return buildProperty { session = c.session origin = FirDeclarationOrigin.Library - returnTypeRef = proto.returnType(c.typeTable).toTypeRef(local) + this.returnTypeRef = returnTypeRef receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local) name = callableName this.isVar = isVar @@ -198,10 +263,8 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) { resolvePhase = FirResolvePhase.ANALYZED_DEPENDENCIES typeParameters += local.typeDeserializer.ownTypeParameters.map { it.fir } annotations += c.annotationDeserializer.loadPropertyAnnotations(proto, local.nameResolver) - getter = FirDefaultPropertyGetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))) - setter = if (isVar) { - FirDefaultPropertySetter(null, c.session, FirDeclarationOrigin.Library, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))) - } else null + this.getter = getter + this.setter = setter this.containerSource = c.containerSource this.initializer = if (Flags.HAS_CONSTANT.get(flags)) { proto.getExtensionOrNull(BuiltInSerializerProtocol.compileTimeValue)?.let {