Extract "values" and "valueOf" names as static constants

This commit is contained in:
Alexander Udalov
2014-09-09 11:29:07 +04:00
parent 4bd603818a
commit 2f12875515
8 changed files with 42 additions and 36 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
@@ -176,14 +177,14 @@ public class CodegenUtil {
public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) { public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType()); JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType());
return "valueOf".equals(functionDescriptor.getName().asString()) return DescriptorUtils.ENUM_VALUE_OF.equals(functionDescriptor.getName())
&& methodTypeParameters.size() == 1 && methodTypeParameters.size() == 1
&& JetTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString); && JetTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString);
} }
public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) { public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
return "values".equals(functionDescriptor.getName().asString()) return DescriptorUtils.ENUM_VALUES.equals(functionDescriptor.getName())
&& methodTypeParameters.isEmpty(); && methodTypeParameters.isEmpty();
} }
} }
@@ -83,7 +83,7 @@ import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrig
import static org.jetbrains.org.objectweb.asm.Opcodes.*; import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ImplementationBodyCodegen extends ClassBodyCodegen { public class ImplementationBodyCodegen extends ClassBodyCodegen {
private static final String VALUES = "$VALUES"; private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
private JetDelegatorToSuperCall superCall; private JetDelegatorToSuperCall superCall;
private Type superClassAsmType; private Type superClassAsmType;
@Nullable // null means java/lang/Object @Nullable // null means java/lang/Object
@@ -925,17 +925,19 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateEnumValuesMethod() { private void generateEnumValuesMethod() {
Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType())); Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
FunctionDescriptor valuesFunction = findEnumFunction("values", new Function1<FunctionDescriptor, Boolean>() { FunctionDescriptor valuesFunction =
@Override KotlinPackage.single(descriptor.getStaticScope().getFunctions(ENUM_VALUES), new Function1<FunctionDescriptor, Boolean>() {
public Boolean invoke(FunctionDescriptor descriptor) { @Override
return CodegenUtil.isEnumValuesMethod(descriptor); public Boolean invoke(FunctionDescriptor descriptor) {
} return CodegenUtil.isEnumValuesMethod(descriptor);
}); }
MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, "values", "()" + type.getDescriptor(), null, null); });
MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(),
"()" + type.getDescriptor(), null, null);
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
mv.visitCode(); mv.visitCode();
mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), VALUES, type.getDescriptor()); mv.visitFieldInsn(GETSTATIC, classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, type.getDescriptor());
mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false); mv.visitMethodInsn(INVOKEVIRTUAL, type.getInternalName(), "clone", "()Ljava/lang/Object;", false);
mv.visitTypeInsn(CHECKCAST, type.getInternalName()); mv.visitTypeInsn(CHECKCAST, type.getInternalName());
mv.visitInsn(ARETURN); mv.visitInsn(ARETURN);
@@ -943,14 +945,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
private void generateEnumValueOfMethod() { private void generateEnumValueOfMethod() {
FunctionDescriptor valueOfFunction = findEnumFunction("valueOf", new Function1<FunctionDescriptor, Boolean>() { FunctionDescriptor valueOfFunction =
@Override KotlinPackage.single(descriptor.getStaticScope().getFunctions(ENUM_VALUE_OF), new Function1<FunctionDescriptor, Boolean>() {
public Boolean invoke(FunctionDescriptor descriptor) { @Override
return CodegenUtil.isEnumValueOfMethod(descriptor); public Boolean invoke(FunctionDescriptor descriptor) {
} return CodegenUtil.isEnumValueOfMethod(descriptor);
}); }
MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valueOfFunction), });
ACC_PUBLIC | ACC_STATIC, "valueOf", "(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null); MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valueOfFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUE_OF.asString(),
"(Ljava/lang/String;)" + classAsmType.getDescriptor(), null, null);
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
mv.visitCode(); mv.visitCode();
@@ -962,14 +965,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
FunctionCodegen.endVisit(mv, "valueOf()", myClass); FunctionCodegen.endVisit(mv, "valueOf()", myClass);
} }
@NotNull
private FunctionDescriptor findEnumFunction(@NotNull String name, @NotNull Function1<FunctionDescriptor, Boolean> predicate) {
Collection<FunctionDescriptor> functions = descriptor.getStaticScope().getFunctions(Name.identifier(name));
FunctionDescriptor function = KotlinPackage.firstOrNull(functions, predicate);
assert function != null : "No " + name + "() function found for " + descriptor;
return function;
}
protected void generateSyntheticAccessors() { protected void generateSyntheticAccessors() {
Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors(); Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors();
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) { for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
@@ -1633,7 +1628,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter iv = codegen.v; InstructionAdapter iv = codegen.v;
Type arrayAsmType = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType())); Type arrayAsmType = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
v.newField(OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, VALUES, arrayAsmType.getDescriptor(), null, null); v.newField(OtherOrigin(myClass), ACC_PRIVATE | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, ENUM_VALUES_FIELD_NAME,
arrayAsmType.getDescriptor(), null, null);
iv.iconst(myEnumConstants.size()); iv.iconst(myEnumConstants.size());
iv.newarray(classAsmType); iv.newarray(classAsmType);
@@ -1645,7 +1641,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
iv.putstatic(classAsmType.getInternalName(), VALUES, arrayAsmType.getDescriptor()); iv.putstatic(classAsmType.getInternalName(), ENUM_VALUES_FIELD_NAME, arrayAsmType.getDescriptor());
} }
private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) { private void initializeEnumConstant(@NotNull ExpressionCodegen codegen, int ordinal) {
@@ -27,6 +27,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.ENUM_VALUE_OF;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
public class EnumValueOf extends IntrinsicMethod { public class EnumValueOf extends IntrinsicMethod {
@@ -42,7 +43,7 @@ public class EnumValueOf extends IntrinsicMethod {
) { ) {
assert arguments != null; assert arguments != null;
codegen.gen(arguments.get(0), JAVA_STRING_TYPE); codegen.gen(arguments.get(0), JAVA_STRING_TYPE);
v.invokestatic(returnType.getInternalName(), "valueOf", "(Ljava/lang/String;)" + returnType.getDescriptor(), false); v.invokestatic(returnType.getInternalName(), ENUM_VALUE_OF.asString(), "(Ljava/lang/String;)" + returnType.getDescriptor(), false);
return returnType; return returnType;
} }
} }
@@ -27,6 +27,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List; import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.ENUM_VALUES;
public class EnumValues extends IntrinsicMethod { public class EnumValues extends IntrinsicMethod {
@NotNull @NotNull
@Override @Override
@@ -38,7 +40,7 @@ public class EnumValues extends IntrinsicMethod {
@Nullable List<JetExpression> arguments, @Nullable List<JetExpression> arguments,
StackValue receiver StackValue receiver
) { ) {
v.invokestatic(returnType.getElementType().getInternalName(), "values", "()" + returnType, false); v.invokestatic(returnType.getElementType().getInternalName(), ENUM_VALUES.asString(), "()" + returnType, false);
return returnType; return returnType;
} }
} }
@@ -22,6 +22,7 @@ import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.jet.codegen.ClassBuilder; import org.jetbrains.jet.codegen.ClassBuilder;
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.constants.EnumValue; import org.jetbrains.jet.lang.resolve.constants.EnumValue;
import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin; import org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.MethodVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -170,15 +170,17 @@ public class LazyJavaStaticClassScope(
override fun getAllFunctionNames(): Collection<Name> { override fun getAllFunctionNames(): Collection<Name> {
if (jClass.isEnum()) { if (jClass.isEnum()) {
return super.getAllFunctionNames() + listOf(Name.identifier("valueOf"), Name.identifier("values")) return super.getAllFunctionNames() + listOf(DescriptorUtils.ENUM_VALUE_OF, DescriptorUtils.ENUM_VALUES)
} }
return super.getAllFunctionNames() return super.getAllFunctionNames()
} }
override fun computeAdditionalFunctions(name: Name): Collection<SimpleFunctionDescriptor> { override fun computeAdditionalFunctions(name: Name): Collection<SimpleFunctionDescriptor> {
if (jClass.isEnum()) { if (jClass.isEnum()) {
if (name.asString() == "valueOf") return listOf(createEnumValueOfMethod(getContainingDeclaration())) when (name) {
if (name.asString() == "values") return listOf(createEnumValuesMethod(getContainingDeclaration())) DescriptorUtils.ENUM_VALUE_OF -> return listOf(createEnumValueOfMethod(getContainingDeclaration()))
DescriptorUtils.ENUM_VALUES -> return listOf(createEnumValuesMethod(getContainingDeclaration()))
}
} }
return listOf() return listOf()
} }
@@ -85,7 +85,7 @@ public class DescriptorFactory {
@NotNull @NotNull
public static SimpleFunctionDescriptor createEnumValuesMethod(@NotNull ClassDescriptor enumClass) { public static SimpleFunctionDescriptor createEnumValuesMethod(@NotNull ClassDescriptor enumClass) {
SimpleFunctionDescriptorImpl values = SimpleFunctionDescriptorImpl values =
SimpleFunctionDescriptorImpl.create(enumClass, Annotations.EMPTY, Name.identifier("values"), SimpleFunctionDescriptorImpl.create(enumClass, Annotations.EMPTY, DescriptorUtils.ENUM_VALUES,
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE); CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE);
return values.initialize(null, NO_RECEIVER_PARAMETER, Collections.<TypeParameterDescriptor>emptyList(), return values.initialize(null, NO_RECEIVER_PARAMETER, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(),
@@ -96,7 +96,7 @@ public class DescriptorFactory {
@NotNull @NotNull
public static SimpleFunctionDescriptor createEnumValueOfMethod(@NotNull ClassDescriptor enumClass) { public static SimpleFunctionDescriptor createEnumValueOfMethod(@NotNull ClassDescriptor enumClass) {
SimpleFunctionDescriptorImpl valueOf = SimpleFunctionDescriptorImpl valueOf =
SimpleFunctionDescriptorImpl.create(enumClass, Annotations.EMPTY, Name.identifier("valueOf"), SimpleFunctionDescriptorImpl.create(enumClass, Annotations.EMPTY, DescriptorUtils.ENUM_VALUE_OF,
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE); CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE);
ValueParameterDescriptor parameterDescriptor = new ValueParameterDescriptorImpl( ValueParameterDescriptor parameterDescriptor = new ValueParameterDescriptorImpl(
valueOf, null, 0, Annotations.EMPTY, Name.identifier("value"), KotlinBuiltIns.getInstance().getStringType(), false, null, valueOf, null, 0, Annotations.EMPTY, Name.identifier("value"), KotlinBuiltIns.getInstance().getStringType(), false, null,
@@ -41,6 +41,9 @@ import java.util.Set;
import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER; import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
public class DescriptorUtils { public class DescriptorUtils {
public static final Name ENUM_VALUES = Name.identifier("values");
public static final Name ENUM_VALUE_OF = Name.identifier("valueOf");
private DescriptorUtils() { private DescriptorUtils() {
} }