enum constant constructors

This commit is contained in:
Dmitry Jemerov
2011-07-12 18:39:08 +02:00
parent 2d8ed0920b
commit ad2b15a5bc
3 changed files with 35 additions and 7 deletions
@@ -150,7 +150,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Method method;
CallableMethod callableMethod;
if (myClass instanceof JetObjectDeclaration || isEnum(myClass)) {
if (constructorDescriptor == null) {
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
@@ -3,10 +3,8 @@ package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
import org.jetbrains.jet.lang.psi.JetEnumEntry;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor;
@@ -103,13 +101,35 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
}
private void initializeEnumConstants(InstructionAdapter v) {
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
for (JetEnumEntry enumConstant : myEnumConstants) {
// TODO type and constructor parameters
String intfClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.INTERFACE);
String implClass = state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION);
final List<JetDelegationSpecifier> delegationSpecifiers = enumConstant.getDelegationSpecifiers();
if (delegationSpecifiers.size() > 1) {
throw new UnsupportedOperationException("multiple delegation specifiers for enum constant not supported");
}
v.anew(Type.getObjectType(implClass));
v.dup();
v.invokespecial(implClass, "<init>", "()V");
if (delegationSpecifiers.size() == 1) {
final JetDelegationSpecifier specifier = delegationSpecifiers.get(0);
if (specifier instanceof JetDelegatorToSuperCall) {
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = state.getBindingContext().resolveSuperConstructor(superCall);
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(method, superCall);
}
else {
throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
}
}
else {
v.invokespecial(implClass, "<init>", "()V");
}
v.putstatic(intfClass, enumConstant.getName(), "L" + intfClass + ";");
}
}
@@ -134,10 +134,18 @@ public class ClassGenTest extends CodegenTestCase {
public void testEnumClass() throws Exception {
loadText("enum class Direction { NORTH; SOUTH; EAST; WEST }");
System.out.println(generateToText());
final Class direction = loadAllClasses(generateClassesInFile()).get("Direction");
final Field north = direction.getField("NORTH");
assertEquals(direction, north.getType());
assertInstanceOf(north.get(null), direction);
}
public void testEnumConstantConstructors() throws Exception {
loadText("enum class Color(val rgb: Int) { RED: Color(0xFF0000); GREEN: Color(0x00FF00); }");
final Class colorClass = loadAllClasses(generateClassesInFile()).get("Color");
final Field redField = colorClass.getField("RED");
final Object redValue = redField.get(null);
final Method rgbMethod = colorClass.getMethod("getRgb");
assertEquals(0xFF0000, rgbMethod.invoke(redValue));
}
}