From ad2b15a5bc6d48653421cbde472060e677f62f24 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 12 Jul 2011 18:39:08 +0200 Subject: [PATCH] enum constant constructors --- .../codegen/ImplementationBodyCodegen.java | 2 +- .../jet/codegen/InterfaceBodyCodegen.java | 30 +++++++++++++++---- .../jetbrains/jet/codegen/ClassGenTest.java | 10 ++++++- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index ffd7e5f1529..6cfa5fdf0d8 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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("", Type.VOID_TYPE, new Type[0]); callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.emptyList()); } diff --git a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java index a9f67f3b5da..52f31470129 100644 --- a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java @@ -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 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, "", "()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, "", "()V"); + } v.putstatic(intfClass, enumConstant.getName(), "L" + intfClass + ";"); } } diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index d23f3c67b49..8800d0aae20 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -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)); + } }