Drop enum class object hack

Place valueOf() and values() into the static scope of the corresponding enum
class

 #KT-5580 Fixed
 #KT-2410 Fixed
This commit is contained in:
Alexander Udalov
2014-09-05 13:39:33 +04:00
parent bb54825fac
commit b52f337f7f
43 changed files with 299 additions and 352 deletions
@@ -39,7 +39,6 @@ import org.jetbrains.jet.lang.descriptors.annotations.Annotations
import java.util.ArrayList
import org.jetbrains.jet.lang.types.checker.JetTypeChecker
import org.jetbrains.jet.lang.types.AbstractClassTypeConstructor
import org.jetbrains.jet.lang.descriptors.impl.EnumClassObjectDescriptor
class LazyJavaClassDescriptor(
private val outerC: LazyJavaResolverContextWithTypes,
@@ -88,14 +87,7 @@ class LazyJavaClassDescriptor(
override fun getUnsubstitutedPrimaryConstructor(): ConstructorDescriptor? = null
private val _classObjectDescriptor = c.storageManager.createNullableLazyValue {
if (jClass.isEnum()) {
EnumClassObjectDescriptor(c.storageManager, this)
}
else null
}
override fun getClassObjectDescriptor(): ClassDescriptor? = _classObjectDescriptor()
override fun getClassObjectDescriptor(): ClassDescriptor? = null
override fun getClassObjectType(): JetType? = getClassObjectDescriptor()?.let { d -> d.getDefaultType() }
override fun getConstructors() = _scopeForMemberLookup._constructors()
@@ -87,6 +87,8 @@ public class LazyJavaClassMemberScope(
c.errorReporter))
}
override fun computeAdditionalFunctions(name: Name) = listOf<SimpleFunctionDescriptor>()
private fun getPropertiesFromSupertypes(name: Name, descriptor: ClassDescriptor): Set<PropertyDescriptor> {
return descriptor.getTypeConstructor().getSupertypes().flatMap {
it.getMemberScope().getProperties(name).map { p -> p as PropertyDescriptor }
@@ -38,7 +38,6 @@ import org.jetbrains.jet.lang.resolve.java.lazy.hasMutableAnnotation
import org.jetbrains.jet.lang.resolve.java.lazy.hasReadOnlyAnnotation
import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter
import java.util.ArrayList
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils
import java.util.LinkedHashSet
import org.jetbrains.jet.lang.types.JetType
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPropertyDescriptor
@@ -72,23 +71,25 @@ public abstract class LazyJavaMemberScope(
protected abstract fun getExpectedThisObject(): ReceiverParameterDescriptor?
protected abstract fun computeAdditionalFunctions(name: Name): Collection<SimpleFunctionDescriptor>
private val _functions = c.storageManager.createMemoizedFunction {
(name: Name): Collection<FunctionDescriptor>
->
(name: Name): Collection<FunctionDescriptor> ->
val methods = memberIndex().findMethodsByName(name)
val functions = LinkedHashSet<SimpleFunctionDescriptor>(
methods.stream()
// values() and valueOf() are added manually, see LazyJavaClassDescriptor::getClassObjectDescriptor()
.filter{ m -> !DescriptorResolverUtils.shouldBeInEnumClassObject(m) }
.flatMap {
m ->
val function = resolveMethodToFunctionDescriptor(m, true)
val samAdapter = resolveSamAdapter(function)
if (samAdapter != null)
listOf(function, samAdapter).stream()
else
listOf(function).stream()
}.toList())
.flatMap {
m ->
val function = resolveMethodToFunctionDescriptor(m, true)
val samAdapter = resolveSamAdapter(function)
if (samAdapter != null)
listOf(function, samAdapter).stream()
else
listOf(function).stream()
}
.plus(computeAdditionalFunctions(name))
.toList()
)
computeNonDeclaredFunctions(functions, name)
@@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.java.lazy.descriptors.LazyJavaMemberScope.
import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor
import org.jetbrains.jet.lang.resolve.name.SpecialNames
import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass
import org.jetbrains.jet.lang.resolve.DescriptorFactory.*
public abstract class LazyJavaStaticScope(
c: LazyJavaResolverContext,
@@ -131,6 +132,8 @@ public class LazyPackageFragmentScopeForJavaPackage(
override fun computeMemberIndex(): MemberIndex = computeMemberIndexForSamConstructors(EMPTY_MEMBER_INDEX)
override fun computeAdditionalFunctions(name: Name) = listOf<SimpleFunctionDescriptor>()
override fun getAllClassNames(): Collection<Name> {
return jPackage.getClasses().stream()
.filter { c -> c.getOriginKind() != JavaClass.OriginKind.KOTLIN_LIGHT_CLASS }
@@ -165,6 +168,21 @@ public class LazyJavaStaticClassScope(
override fun computeMemberIndex(): MemberIndex = computeMemberIndexForSamConstructors(ClassMemberIndex(jClass, { m -> m.isStatic() }))
override fun getAllFunctionNames(): Collection<Name> {
if (jClass.isEnum()) {
return super.getAllFunctionNames() + listOf(Name.identifier("valueOf"), Name.identifier("values"))
}
return super.getAllFunctionNames()
}
override fun computeAdditionalFunctions(name: Name): Collection<SimpleFunctionDescriptor> {
if (jClass.isEnum()) {
if (name.asString() == "valueOf") return listOf(createEnumValueOfMethod(getContainingDeclaration()))
if (name.asString() == "values") return listOf(createEnumValuesMethod(getContainingDeclaration()))
}
return listOf()
}
override fun getAllClassNames(): Collection<Name> = listOf()
override fun getClassifier(name: Name): ClassifierDescriptor? = null
@@ -87,23 +87,6 @@ public final class DescriptorResolverUtils {
return null;
}
/**
* @return true if {@code method} is a static method of enum class, which is to be put into its class object (and not into the
* corresponding package). This applies to values() and valueOf(String) methods
*/
public static boolean shouldBeInEnumClassObject(@NotNull JavaMethod method) {
if (!method.getContainingClass().isEnum()) return false;
String name = method.getName().asString();
if (name.equals("values")) {
return method.getValueParameters().isEmpty();
}
else if (name.equals("valueOf")) {
return isMethodWithOneParameterWithFqName(method, "java.lang.String");
}
return false;
}
public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
return member.getContainingClass().isInterface() && member instanceof JavaMethod && isObjectMethod((JavaMethod) member);
}