K1: add support for Enum.entries synthetic property (see KT-48872)

#KT-53270 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-07-25 11:40:32 +02:00
committed by Space
parent c0f81cbc45
commit 12e8b1d844
13 changed files with 247 additions and 62 deletions
@@ -25,4 +25,6 @@ class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVers
override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName)
override val readDeserializedContracts: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts)
override val supportEnumEntries: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.EnumEntries)
}
@@ -132,7 +132,10 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
this.scopesHolderForClass = createScopesHolderForClass(c, this.declarationProvider);
this.kind = classLikeInfo.getClassKind();
this.staticScope = kind == ClassKind.ENUM_CLASS ? new StaticScopeForKotlinEnum(storageManager, this) : MemberScope.Empty.INSTANCE;
this.staticScope = kind == ClassKind.ENUM_CLASS ?
new StaticScopeForKotlinEnum(
storageManager, this, c.getLanguageVersionSettings().supportsFeature(LanguageFeature.EnumEntries)
) : MemberScope.Empty.INSTANCE;
this.typeConstructor = new LazyClassTypeConstructor();
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.builtins.StandardNames.ENUM_ENTRIES
import org.jetbrains.kotlin.builtins.StandardNames.ENUM_VALUES
import org.jetbrains.kotlin.builtins.StandardNames.ENUM_VALUE_OF
import org.jetbrains.kotlin.ir.declarations.IrClass
@@ -26,11 +27,13 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrSyntheticBodyImpl
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.ir.util.declareSimpleFunctionWithOverrides
import org.jetbrains.kotlin.resolve.scopes.findFirstFunction
import org.jetbrains.kotlin.resolve.scopes.findFirstVariable
class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
fun generateSpecialMembers(irClass: IrClass) {
generateValues(irClass)
generateValueOf(irClass)
generateEntries(irClass)
}
private fun generateValues(irClass: IrClass) {
@@ -46,7 +49,9 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
valuesFunction
).also { irFunction ->
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null, emptyList())
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(
irFunction, null, null, emptyList()
)
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUES)
}
)
@@ -65,9 +70,35 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
valueOfFunction
).also { irFunction ->
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null, emptyList())
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(
irFunction, null, null, emptyList()
)
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUEOF)
}
)
}
private fun generateEntries(irClass: IrClass) {
val entriesProperty = irClass.descriptor.staticScope.findFirstVariable(ENUM_ENTRIES.identifier) {
it.dispatchReceiverParameter == null && it.extensionReceiverParameter == null
} ?: return
irClass.addMember(
context.symbolTable.declareProperty(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
entriesProperty
).also { irProperty ->
irProperty.getter = context.symbolTable.declareSimpleFunctionWithOverrides(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR,
entriesProperty.getter!!
).also { getter ->
getter.correspondingPropertySymbol = irProperty.symbol
getter.returnType = entriesProperty.returnType!!.toIrType()
getter.body = IrSyntheticBodyImpl(irProperty.startOffset, irProperty.endOffset, IrSyntheticBodyKind.ENUM_ENTRIES)
}
}
)
}
}
+3 -3
View File
@@ -1,7 +1,7 @@
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +EnumEntries
// TARGET_BACKEND: JVM_IR
// FULL_JDK
// WITH_STDLIB
enum class SimpleEnum {
A, B, C
@@ -0,0 +1,73 @@
FILE fqName:<root> fileName:/enumEntries.kt
CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public superTypes:[kotlin.Enum<<root>.MyEnum>]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.MyEnum
CONSTRUCTOR visibility:private <> () returnType:<root>.MyEnum [primary]
BLOCK_BODY
ENUM_CONSTRUCTOR_CALL 'public constructor <init> (name: kotlin.String, ordinal: kotlin.Int) [primary] declared in kotlin.Enum'
<E>: <root>.MyEnum
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ENUM_CLASS name:MyEnum modality:FINAL visibility:public superTypes:[kotlin.Enum<<root>.MyEnum>]'
ENUM_ENTRY name:Ok
init: EXPRESSION_BODY
ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.MyEnum'
ENUM_ENTRY name:Nope
init: EXPRESSION_BODY
ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.MyEnum'
FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<<root>.MyEnum>
SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:<root>.MyEnum
VALUE_PARAMETER name:value index:0 type:kotlin.String
SYNTHETIC_BODY kind=ENUM_VALUEOF
PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [val]
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-entries> visibility:public modality:FINAL <> () returnType:kotlin.enums.EnumEntries<<root>.MyEnum>
correspondingProperty: PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [val]
SYNTHETIC_BODY kind=ENUM_ENTRIES
FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.Any [fake_override]
overridden:
protected final fun clone (): kotlin.Any declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>, other:<root>.MyEnum) returnType:kotlin.Int [fake_override,operator]
overridden:
public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
VALUE_PARAMETER name:other index:0 type:<root>.MyEnum
FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.Int [fake_override]
overridden:
public final fun hashCode (): kotlin.Int declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val]
annotations:
IntrinsicConstEvaluation
overridden:
public final name: kotlin.String [val]
FUN FAKE_OVERRIDE name:<get-name> visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.String [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-name> (): kotlin.String declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val]
overridden:
public final ordinal: kotlin.Int [val]
FUN FAKE_OVERRIDE name:<get-ordinal> visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.Int [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-ordinal> (): kotlin.Int declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN FAKE_OVERRIDE name:getDeclaringClass visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:@[FlexibleNullability] java.lang.Class<@[FlexibleNullability] <root>.MyEnum?>? [fake_override]
overridden:
public final fun getDeclaringClass (): @[FlexibleNullability] java.lang.Class<@[FlexibleNullability] E of kotlin.Enum?>? declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.enums.EnumEntries<<root>.MyEnum>
annotations:
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalStdlibApi modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.ExperimentalStdlibApi>])
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.enums.EnumEntries<<root>.MyEnum> declared in <root>'
CALL 'public final fun <get-entries> (): kotlin.enums.EnumEntries<<root>.MyEnum> declared in <root>.MyEnum' type=kotlin.enums.EnumEntries<<root>.MyEnum> origin=GET_PROPERTY
@@ -0,0 +1,24 @@
enum class MyEnum : Enum<MyEnum> {
private constructor() /* primary */ {
super/*Enum*/<MyEnum>()
/* <init>() */
}
Ok = MyEnum()
Nope = MyEnum()
fun values(): Array<MyEnum> /* Synthetic body for ENUM_VALUES */
fun valueOf(value: String): MyEnum /* Synthetic body for ENUM_VALUEOF */
val entries: EnumEntries<MyEnum>
get
}
@OptIn(markerClass = [ExperimentalStdlibApi::class])
fun box(): EnumEntries<MyEnum> {
return <get-entries>()
}
+49 -45
View File
@@ -12,6 +12,54 @@ FILE fqName:<root> fileName:/enumEntries.kt
ENUM_ENTRY name:Nope
init: EXPRESSION_BODY
ENUM_CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.MyEnum'
PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val]
annotations:
IntrinsicConstEvaluation
overridden:
public final name: kotlin.String [val]
FUN FAKE_OVERRIDE name:<get-name> visibility:public modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:kotlin.String [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-name> (): kotlin.String declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val]
overridden:
public final ordinal: kotlin.Int [val]
FUN FAKE_OVERRIDE name:<get-ordinal> visibility:public modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:kotlin.Int [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-ordinal> (): kotlin.Int declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:kotlin.Any [fake_override]
overridden:
protected final fun clone (): kotlin.Any declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>, other:<root>.MyEnum) returnType:kotlin.Int [fake_override,operator]
overridden:
public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
VALUE_PARAMETER name:other index:0 type:<root>.MyEnum
FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:finalize visibility:protected/*protected and package*/ modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:kotlin.Unit [fake_override]
overridden:
protected/*protected and package*/ final fun finalize (): kotlin.Unit declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
FUN FAKE_OVERRIDE name:getDeclaringClass visibility:public modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:@[FlexibleNullability] java.lang.Class<@[FlexibleNullability] <root>.MyEnum?>? [fake_override]
overridden:
public final fun getDeclaringClass (): @[FlexibleNullability] java.lang.Class<@[FlexibleNullability] E of kotlin.Enum?>? declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:kotlin.Int [fake_override]
overridden:
public final fun hashCode (): kotlin.Int declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum<<root>.MyEnum>) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<<root>.MyEnum>
FUN ENUM_CLASS_SPECIAL_MEMBER name:values visibility:public modality:FINAL <> () returnType:kotlin.Array<<root>.MyEnum>
SYNTHETIC_BODY kind=ENUM_VALUES
FUN ENUM_CLASS_SPECIAL_MEMBER name:valueOf visibility:public modality:FINAL <> (value:kotlin.String) returnType:<root>.MyEnum
@@ -21,53 +69,9 @@ FILE fqName:<root> fileName:/enumEntries.kt
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-entries> visibility:public modality:FINAL <> () returnType:kotlin.enums.EnumEntries<<root>.MyEnum>
correspondingProperty: PROPERTY ENUM_CLASS_SPECIAL_MEMBER name:entries visibility:public modality:FINAL [val]
SYNTHETIC_BODY kind=ENUM_ENTRIES
FUN FAKE_OVERRIDE name:clone visibility:protected modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.Any [fake_override]
overridden:
protected final fun clone (): kotlin.Any declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN FAKE_OVERRIDE name:compareTo visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>, other:<root>.MyEnum) returnType:kotlin.Int [fake_override,operator]
overridden:
public final fun compareTo (other: E of kotlin.Enum): kotlin.Int [operator] declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
VALUE_PARAMETER name:other index:0 type:<root>.MyEnum
FUN FAKE_OVERRIDE name:equals visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public final fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.Int [fake_override]
overridden:
public final fun hashCode (): kotlin.Int declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val]
annotations:
IntrinsicConstEvaluation
overridden:
public final name: kotlin.String [val]
FUN FAKE_OVERRIDE name:<get-name> visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.String [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:name visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-name> (): kotlin.String declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val]
overridden:
public final ordinal: kotlin.Int [val]
FUN FAKE_OVERRIDE name:<get-ordinal> visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:kotlin.Int [fake_override]
correspondingProperty: PROPERTY FAKE_OVERRIDE name:ordinal visibility:public modality:FINAL [fake_override,val]
overridden:
public final fun <get-ordinal> (): kotlin.Int declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN FAKE_OVERRIDE name:getDeclaringClass visibility:public modality:FINAL <> ($this:kotlin.Enum<E of kotlin.Enum>) returnType:@[FlexibleNullability] java.lang.Class<@[FlexibleNullability] <root>.MyEnum?>? [fake_override]
overridden:
public final fun getDeclaringClass (): @[FlexibleNullability] java.lang.Class<@[FlexibleNullability] E of kotlin.Enum?>? declared in kotlin.Enum
$this: VALUE_PARAMETER name:<this> type:kotlin.Enum<E of kotlin.Enum>
FUN name:box visibility:public modality:FINAL <> () returnType:kotlin.enums.EnumEntries<<root>.MyEnum>
annotations:
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalStdlibApi modality:FINAL visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.ExperimentalStdlibApi>])
OptIn(markerClass = [CLASS_REFERENCE 'CLASS IR_EXTERNAL_DECLARATION_STUB ANNOTATION_CLASS name:ExperimentalStdlibApi modality:OPEN visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<kotlin.ExperimentalStdlibApi>])
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.enums.EnumEntries<<root>.MyEnum> declared in <root>'
CALL 'public final fun <get-entries> (): kotlin.enums.EnumEntries<<root>.MyEnum> declared in <root>.MyEnum' type=kotlin.enums.EnumEntries<<root>.MyEnum> origin=GET_PROPERTY
-1
View File
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !LANGUAGE: +EnumEntries
// TARGET_BACKEND: JVM_IR
// FULL_JDK
@@ -22,16 +22,16 @@ import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.*;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.name.StandardClassIds;
import org.jetbrains.kotlin.resolve.scopes.receivers.ContextClassReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ContextReceiver;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.Variance;
import org.jetbrains.kotlin.types.*;
import java.util.Collections;
import static org.jetbrains.kotlin.builtins.StandardNames.ENUM_VALUES;
import static org.jetbrains.kotlin.builtins.StandardNames.ENUM_VALUE_OF;
import static org.jetbrains.kotlin.builtins.StandardNames.*;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getContainingModule;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.getDefaultConstructorVisibility;
import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.getBuiltIns;
@@ -172,6 +172,36 @@ public class DescriptorFactory {
Modality.FINAL, DescriptorVisibilities.PUBLIC);
}
@Nullable
public static PropertyDescriptor createEnumEntriesProperty(@NotNull ClassDescriptor enumClass) {
ClassDescriptor enumEntriesClass = FindClassInModuleKt.findClassAcrossModuleDependencies(getContainingModule(enumClass),
StandardClassIds.INSTANCE.getEnumEntries());
if (enumEntriesClass == null) {
return null;
}
PropertyDescriptorImpl entries =
PropertyDescriptorImpl.create(enumClass, Annotations.Companion.getEMPTY(), Modality.FINAL, DescriptorVisibilities.PUBLIC,
/* isVar = */ false, ENUM_ENTRIES, CallableMemberDescriptor.Kind.SYNTHESIZED,
enumClass.getSource(), /* lateinit = */ false, /* isConst = */ false, /* isExpect = */ false,
/* isActual = */ false, /* isExternal = */ false, /* isDelegated = */ false);
PropertyGetterDescriptorImpl getter = new PropertyGetterDescriptorImpl(
entries, Annotations.Companion.getEMPTY(), Modality.FINAL, DescriptorVisibilities.PUBLIC, /* isDefault = */ false,
/* isExternal = */ false, /* isInline = */ false, CallableMemberDescriptor.Kind.SYNTHESIZED,
/* original = */ null, enumClass.getSource()
);
entries.initialize(getter, /* setter = */ null);
entries.setType(
KotlinTypeFactory.simpleType(TypeAttributes.Companion.getEmpty(),
enumEntriesClass.getTypeConstructor(),
Collections.singletonList(new TypeProjectionImpl(enumClass.getDefaultType())),
/* isNullable = */ false),
Collections.<TypeParameterDescriptor>emptyList(), null, null,
Collections.<ReceiverParameterDescriptor>emptyList())
;
getter.initialize(entries.getReturnType());
return entries;
}
public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor descriptor) {
return descriptor.getName().equals(ENUM_VALUES) && isEnumSpecialMethod(descriptor);
}
@@ -70,6 +70,9 @@ fun MemberScope.computeAllNames() = getClassifierNames()?.let { classifierNames
inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
inline fun MemberScope.findFirstVariable(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
getContributedVariables(Name.identifier(name), NoLookupLocation.FROM_BACKEND).firstOrNull(predicate)
fun Iterable<MemberScope>.flatMapClassifierNamesOrNull(): MutableSet<Name>? =
flatMapToNullable(hashSetOf(), MemberScope::getClassifierNames)
@@ -18,11 +18,11 @@ package org.jetbrains.kotlin.resolve.scopes
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorFactory.createEnumValueOfMethod
import org.jetbrains.kotlin.resolve.DescriptorFactory.createEnumValuesMethod
import org.jetbrains.kotlin.resolve.DescriptorFactory.*
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.storage.getValue
import org.jetbrains.kotlin.utils.Printer
@@ -30,8 +30,9 @@ import org.jetbrains.kotlin.utils.SmartList
// We don't need to track lookups here since this scope used only for introduce special Enum class members
class StaticScopeForKotlinEnum(
storageManager: StorageManager,
private val containingClass: ClassDescriptor
storageManager: StorageManager,
private val containingClass: ClassDescriptor,
private val supportEnumEntries: Boolean
) : MemberScopeImpl() {
init {
assert(containingClass.kind == ClassKind.ENUM_CLASS) { "Class should be an enum: $containingClass" }
@@ -43,11 +44,18 @@ class StaticScopeForKotlinEnum(
listOf(createEnumValueOfMethod(containingClass), createEnumValuesMethod(containingClass))
}
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = functions
private val properties: List<PropertyDescriptor> by storageManager.createLazyValue {
if (supportEnumEntries) listOfNotNull(createEnumEntriesProperty(containingClass)) else emptyList()
}
override fun getContributedDescriptors(kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean) = functions + properties
override fun getContributedFunctions(name: Name, location: LookupLocation) =
functions.filterTo(SmartList()) { it.name == name }
override fun getContributedVariables(name: Name, location: LookupLocation): Collection<PropertyDescriptor> =
properties.filterTo(SmartList()) { it.name == name }
override fun printScopeStructure(p: Printer) {
p.println("Static scope for $containingClass")
}
@@ -36,5 +36,8 @@ interface DeserializationConfiguration {
val preserveDeclarationsOrdering: Boolean
get() = false
val supportEnumEntries: Boolean
get() = false
object Default : DeserializationConfiguration
}
@@ -52,7 +52,12 @@ class DeserializedClassDescriptor(
VersionRequirementTable.create(classProto.versionRequirementTable), metadataVersion
)
private val staticScope = if (kind == ClassKind.ENUM_CLASS) StaticScopeForKotlinEnum(c.storageManager, this) else MemberScope.Empty
private val staticScope =
if (kind == ClassKind.ENUM_CLASS)
StaticScopeForKotlinEnum(c.storageManager, this, c.components.configuration.supportEnumEntries)
else
MemberScope.Empty
private val typeConstructor = DeserializedClassTypeConstructor()
private val memberScopeHolder =