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.JetSimpleNameExpression;
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.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
@@ -176,14 +177,14 @@ public class CodegenUtil {
public static boolean isEnumValueOfMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
JetType nullableString = TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getStringType());
return "valueOf".equals(functionDescriptor.getName().asString())
return DescriptorUtils.ENUM_VALUE_OF.equals(functionDescriptor.getName())
&& methodTypeParameters.size() == 1
&& JetTypeChecker.DEFAULT.isSubtypeOf(methodTypeParameters.get(0).getType(), nullableString);
}
public static boolean isEnumValuesMethod(@NotNull FunctionDescriptor functionDescriptor) {
List<ValueParameterDescriptor> methodTypeParameters = functionDescriptor.getValueParameters();
return "values".equals(functionDescriptor.getName().asString())
return DescriptorUtils.ENUM_VALUES.equals(functionDescriptor.getName())
&& methodTypeParameters.isEmpty();
}
}
@@ -83,7 +83,7 @@ import static org.jetbrains.jet.lang.resolve.java.diagnostics.JvmDeclarationOrig
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
public class ImplementationBodyCodegen extends ClassBodyCodegen {
private static final String VALUES = "$VALUES";
private static final String ENUM_VALUES_FIELD_NAME = "$VALUES";
private JetDelegatorToSuperCall superCall;
private Type superClassAsmType;
@Nullable // null means java/lang/Object
@@ -925,17 +925,19 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
private void generateEnumValuesMethod() {
Type type = typeMapper.mapType(KotlinBuiltIns.getInstance().getArrayType(descriptor.getDefaultType()));
FunctionDescriptor valuesFunction = findEnumFunction("values", new Function1<FunctionDescriptor, Boolean>() {
@Override
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);
FunctionDescriptor valuesFunction =
KotlinPackage.single(descriptor.getStaticScope().getFunctions(ENUM_VALUES), new Function1<FunctionDescriptor, Boolean>() {
@Override
public Boolean invoke(FunctionDescriptor descriptor) {
return CodegenUtil.isEnumValuesMethod(descriptor);
}
});
MethodVisitor mv = v.newMethod(OtherOrigin(myClass, valuesFunction), ACC_PUBLIC | ACC_STATIC, ENUM_VALUES.asString(),
"()" + type.getDescriptor(), null, null);
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
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.visitTypeInsn(CHECKCAST, type.getInternalName());
mv.visitInsn(ARETURN);
@@ -943,14 +945,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
private void generateEnumValueOfMethod() {
FunctionDescriptor valueOfFunction = findEnumFunction("valueOf", new Function1<FunctionDescriptor, Boolean>() {
@Override
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);
FunctionDescriptor valueOfFunction =
KotlinPackage.single(descriptor.getStaticScope().getFunctions(ENUM_VALUE_OF), new Function1<FunctionDescriptor, Boolean>() {
@Override
public Boolean invoke(FunctionDescriptor descriptor) {
return CodegenUtil.isEnumValueOfMethod(descriptor);
}
});
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;
mv.visitCode();
@@ -962,14 +965,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
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() {
Map<DeclarationDescriptor, DeclarationDescriptor> accessors = context.getAccessors();
for (Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry : accessors.entrySet()) {
@@ -1633,7 +1628,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
InstructionAdapter iv = codegen.v;
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.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) {
@@ -27,6 +27,7 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
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;
public class EnumValueOf extends IntrinsicMethod {
@@ -42,7 +43,7 @@ public class EnumValueOf extends IntrinsicMethod {
) {
assert arguments != null;
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;
}
}
@@ -27,6 +27,8 @@ import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.ENUM_VALUES;
public class EnumValues extends IntrinsicMethod {
@NotNull
@Override
@@ -38,7 +40,7 @@ public class EnumValues extends IntrinsicMethod {
@Nullable List<JetExpression> arguments,
StackValue receiver
) {
v.invokestatic(returnType.getElementType().getInternalName(), "values", "()" + returnType, false);
v.invokestatic(returnType.getElementType().getInternalName(), ENUM_VALUES.asString(), "()" + returnType, false);
return returnType;
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.jet.codegen.AsmUtil;
import org.jetbrains.jet.codegen.ClassBuilder;
import org.jetbrains.jet.codegen.state.GenerationState;
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.java.diagnostics.JvmDeclarationOrigin;
import org.jetbrains.org.objectweb.asm.MethodVisitor;
@@ -170,15 +170,17 @@ public class LazyJavaStaticClassScope(
override fun getAllFunctionNames(): Collection<Name> {
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()
}
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()))
when (name) {
DescriptorUtils.ENUM_VALUE_OF -> return listOf(createEnumValueOfMethod(getContainingDeclaration()))
DescriptorUtils.ENUM_VALUES -> return listOf(createEnumValuesMethod(getContainingDeclaration()))
}
}
return listOf()
}
@@ -85,7 +85,7 @@ public class DescriptorFactory {
@NotNull
public static SimpleFunctionDescriptor createEnumValuesMethod(@NotNull ClassDescriptor enumClass) {
SimpleFunctionDescriptorImpl values =
SimpleFunctionDescriptorImpl.create(enumClass, Annotations.EMPTY, Name.identifier("values"),
SimpleFunctionDescriptorImpl.create(enumClass, Annotations.EMPTY, DescriptorUtils.ENUM_VALUES,
CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE);
return values.initialize(null, NO_RECEIVER_PARAMETER, Collections.<TypeParameterDescriptor>emptyList(),
Collections.<ValueParameterDescriptor>emptyList(),
@@ -96,7 +96,7 @@ public class DescriptorFactory {
@NotNull
public static SimpleFunctionDescriptor createEnumValueOfMethod(@NotNull ClassDescriptor enumClass) {
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);
ValueParameterDescriptor parameterDescriptor = new ValueParameterDescriptorImpl(
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;
public class DescriptorUtils {
public static final Name ENUM_VALUES = Name.identifier("values");
public static final Name ENUM_VALUE_OF = Name.identifier("valueOf");
private DescriptorUtils() {
}