K1: add support for Enum.entries synthetic property (see KT-48872)
#KT-53270 Fixed
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
+13
-5
@@ -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")
|
||||
}
|
||||
|
||||
+3
@@ -36,5 +36,8 @@ interface DeserializationConfiguration {
|
||||
val preserveDeclarationsOrdering: Boolean
|
||||
get() = false
|
||||
|
||||
val supportEnumEntries: Boolean
|
||||
get() = false
|
||||
|
||||
object Default : DeserializationConfiguration
|
||||
}
|
||||
|
||||
+6
-1
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user