simplest case of enum classes

This commit is contained in:
Dmitry Jemerov
2011-07-12 18:18:08 +02:00
parent 57f4f664ba
commit f44ac29cde
4 changed files with 61 additions and 4 deletions
@@ -25,13 +25,15 @@ public class ClassCodegen {
else {
generateInterface(parentContext, aClass);
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
generateImplementation(parentContext, aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
if (!ImplementationBodyCodegen.isEnum(aClass)) {
generateImplementation(parentContext, aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
}
}
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) {
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
generate(contextForInners, (JetClass) declaration);
}
}
@@ -146,11 +146,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void generatePrimaryConstructor() {
ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor((JetElement) myClass);
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration)) return;
if (constructorDescriptor == null && !(myClass instanceof JetObjectDeclaration) && !isEnum(myClass)) return;
Method method;
CallableMethod callableMethod;
if (myClass instanceof JetObjectDeclaration) {
if (myClass instanceof JetObjectDeclaration || isEnum(myClass)) {
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
}
@@ -278,6 +278,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
mv.visitEnd();
}
static boolean isEnum(JetClassOrObject myClass) {
final JetModifierList modifierList = myClass.getModifierList();
return modifierList != null && modifierList.hasModifier(JetTokens.ENUM_KEYWORD);
}
@Nullable
private ClassDescriptor getOuterClassDescriptor() {
if (myClass.getParent() instanceof JetClassObject) {
@@ -4,12 +4,17 @@ 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.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -18,6 +23,8 @@ import java.util.Set;
* @author yole
*/
public class InterfaceBodyCodegen extends ClassBodyCodegen {
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
super(aClass, context, v, state);
assert context.getContextKind() == OwnerKind.INTERFACE;
@@ -73,4 +80,37 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
}
return superInterfaces;
}
@Override
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
if (declaration instanceof JetEnumEntry && !((JetEnumEntry) declaration).hasPrimaryConstructor()) {
String name = declaration.getName();
final String desc = "L" + state.getTypeMapper().jvmName(descriptor, OwnerKind.INTERFACE) + ";";
v.visitField(Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, name, desc, null, null);
if (myEnumConstants.isEmpty()) {
staticInitializerChunks.add(new CodeChunk() {
@Override
public void generate(InstructionAdapter v) {
initializeEnumConstants(v);
}
});
}
myEnumConstants.add((JetEnumEntry) declaration);
}
else {
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
}
}
private void initializeEnumConstants(InstructionAdapter v) {
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);
v.anew(Type.getObjectType(implClass));
v.dup();
v.invokespecial(implClass, "<init>", "()V");
v.putstatic(intfClass, enumConstant.getName(), "L" + intfClass + ";");
}
}
}
@@ -1,5 +1,6 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
@@ -130,4 +131,13 @@ public class ClassGenTest extends CodegenTestCase {
Object result = method.invoke(null);
assertInstanceOf(result, Runnable.class);
}
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);
}
}