Fix broken isEnumClassObject methods

Out of three methods, two were incorrect
This commit is contained in:
Alexander Udalov
2013-03-14 18:19:43 +04:00
parent c3a2f16624
commit 68844131b0
8 changed files with 49 additions and 48 deletions
@@ -19,7 +19,9 @@ package org.jetbrains.jet.codegen.intrinsics;
import com.google.common.collect.ImmutableList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType;
import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -35,7 +37,7 @@ import java.util.List;
import java.util.Map;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
public class IntrinsicMethods {
private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus();
@@ -229,10 +231,11 @@ public class IntrinsicMethods {
SimpleFunctionDescriptor functionDescriptor = (SimpleFunctionDescriptor) descriptor;
if (isEnumClassObject(functionDescriptor.getContainingDeclaration())) {
if ("values".equals(functionDescriptor.getName().getName())) {
if (isEnumValuesMethod(functionDescriptor)) {
return ENUM_VALUES;
}
if ("valueOf".equals(functionDescriptor.getName().getName())) {
if (isEnumValueOfMethod(functionDescriptor)) {
return ENUM_VALUE_OF;
}
}
@@ -254,20 +257,4 @@ public class IntrinsicMethods {
}
return intrinsicMethod;
}
private static boolean isEnumClassObject(DeclarationDescriptor declaration) {
if (declaration instanceof ClassDescriptor) {
ClassDescriptor descriptor = (ClassDescriptor) declaration;
if (descriptor.getContainingDeclaration() instanceof ClassDescriptor) {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
//noinspection ConstantConditions
if (containingDeclaration != null &&
containingDeclaration.getClassObjectDescriptor() != null &&
containingDeclaration.getClassObjectDescriptor().equals(descriptor)) {
return true;
}
}
}
return false;
}
}
@@ -40,7 +40,6 @@ import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.Collections;
@@ -48,6 +47,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
import static org.jetbrains.jet.lang.resolve.OverridingUtil.*;
import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.JAVA;
import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.KOTLIN;
@@ -296,9 +296,9 @@ public final class JavaFunctionResolver {
OverrideResolver.resolveUnknownVisibilities(functions, trace);
functions.addAll(functionsFromCurrent);
if (DescriptorUtils.isEnumClassObject(owner)) {
if (isEnumClassObject(owner)) {
for (FunctionDescriptor functionDescriptor : Lists.newArrayList(functions)) {
if (isEnumSpecialMethod(functionDescriptor)) {
if (isEnumValueOfMethod(functionDescriptor) || isEnumValuesMethod(functionDescriptor)) {
functions.remove(functionDescriptor);
}
}
@@ -361,17 +361,6 @@ public final class JavaFunctionResolver {
return r;
}
private static boolean isEnumSpecialMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
String methodName = functionDescriptor.getName().getName();
JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType());
if (methodName.equals("valueOf") && methodTypeParameters.size() == 1
&& JetTypeChecker.INSTANCE.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString)) {
return true;
}
return (methodName.equals("values") && methodTypeParameters.isEmpty());
}
private static boolean containsErrorType(@NotNull List<FunctionDescriptor> superFunctions, @NotNull FunctionDescriptor function) {
if (containsErrorType(function)) {
return true;
@@ -354,10 +354,14 @@ public class DescriptorUtils {
return Name.special("<class-object-for-" + className + ">");
}
public static boolean isEnumClassObject(@NotNull DeclarationDescriptor classObjectDescriptor) {
DeclarationDescriptor containingDeclaration = classObjectDescriptor.getContainingDeclaration();
return ((containingDeclaration instanceof ClassDescriptor) &&
((ClassDescriptor) containingDeclaration).getKind() == ClassKind.ENUM_CLASS);
public static boolean isEnumClassObject(@NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getKind() == ClassKind.CLASS_OBJECT) {
DeclarationDescriptor containing = descriptor.getContainingDeclaration();
if ((containing instanceof ClassDescriptor) && ((ClassDescriptor) containing).getKind() == ClassKind.ENUM_CLASS) {
return true;
}
}
return false;
}
@NotNull
@@ -512,4 +516,17 @@ public class DescriptorUtils {
return null;
}
public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType());
return "valueOf".equals(functionDescriptor.getName().getName())
&& methodTypeParameters.size() == 1
&& JetTypeChecker.INSTANCE.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString);
}
public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
return "values".equals(functionDescriptor.getName().getName())
&& methodTypeParameters.isEmpty();
}
}
@@ -189,7 +189,7 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
}
private void generateEnumClassObjectMethods(@NotNull Collection<? super FunctionDescriptor> result, @NotNull Name name) {
if (!isEnumClassObject()) return;
if (!DescriptorUtils.isEnumClassObject(thisDescriptor)) return;
if (name.equals(DescriptorResolver.VALUES_METHOD_NAME)) {
SimpleFunctionDescriptor valuesMethod = DescriptorResolver
@@ -203,15 +203,6 @@ public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescr
}
}
private boolean isEnumClassObject() {
DeclarationDescriptor containingDeclaration = thisDescriptor.getContainingDeclaration();
if (!(containingDeclaration instanceof ClassDescriptor)) return false;
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
if (classDescriptor.getKind() != ClassKind.ENUM_CLASS) return false;
if (classDescriptor.getClassObjectDescriptor() != thisDescriptor) return false;
return true;
}
@NotNull
@Override
public Set<VariableDescriptor> getProperties(@NotNull Name name) {
@@ -0,0 +1,8 @@
class A {
class object {
fun values() = "O"
fun valueOf() = "K"
}
}
fun box() = A.values() + A.valueOf()
@@ -7,9 +7,11 @@ public enum Enum {
public static class Nested {
void foo() {}
void values() {}
}
public class Inner {
void bar() {}
void valueOf(String s) {}
}
}
@@ -17,10 +17,12 @@ public final enum class Enum : jet.Enum<test.Enum> {
public open inner class Inner : java.lang.Object {
public constructor Inner()
public/*package*/ open fun bar() : Unit
public/*package*/ open fun valueOf(/*0*/ p0 : jet.String?) : Unit
}
public open class Nested : java.lang.Object {
public constructor Nested()
public/*package*/ open fun foo() : Unit
public/*package*/ open fun values() : Unit
}
}
@@ -477,6 +477,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest("compiler/testData/codegen/box/classes/classObjectInTrait.kt");
}
@TestMetadata("classObjectNotOfEnum.kt")
public void testClassObjectNotOfEnum() throws Exception {
doTest("compiler/testData/codegen/box/classes/classObjectNotOfEnum.kt");
}
@TestMetadata("delegation2.kt")
public void testDelegation2() throws Exception {
doTest("compiler/testData/codegen/box/classes/delegation2.kt");