simplest case of enum classes
This commit is contained in:
@@ -25,13 +25,15 @@ public class ClassCodegen {
|
|||||||
else {
|
else {
|
||||||
generateInterface(parentContext, aClass);
|
generateInterface(parentContext, aClass);
|
||||||
generateImplementation(parentContext, aClass, OwnerKind.IMPLEMENTATION);
|
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);
|
ClassDescriptor descriptor = state.getBindingContext().getClassDescriptor(aClass);
|
||||||
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
|
final ClassContext contextForInners = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION);
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetClass) {
|
if (declaration instanceof JetClass && !(declaration instanceof JetEnumEntry)) {
|
||||||
generate(contextForInners, (JetClass) declaration);
|
generate(contextForInners, (JetClass) declaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,11 +146,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
protected void generatePrimaryConstructor() {
|
protected void generatePrimaryConstructor() {
|
||||||
ConstructorDescriptor constructorDescriptor = state.getBindingContext().getConstructorDescriptor((JetElement) myClass);
|
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;
|
Method method;
|
||||||
CallableMethod callableMethod;
|
CallableMethod callableMethod;
|
||||||
if (myClass instanceof JetObjectDeclaration) {
|
if (myClass instanceof JetObjectDeclaration || isEnum(myClass)) {
|
||||||
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
method = new Method("<init>", Type.VOID_TYPE, new Type[0]);
|
||||||
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
|
callableMethod = new CallableMethod("", method, Opcodes.INVOKESPECIAL, Collections.<Type>emptyList());
|
||||||
}
|
}
|
||||||
@@ -278,6 +278,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
mv.visitEnd();
|
mv.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static boolean isEnum(JetClassOrObject myClass) {
|
||||||
|
final JetModifierList modifierList = myClass.getModifierList();
|
||||||
|
return modifierList != null && modifierList.hasModifier(JetTokens.ENUM_KEYWORD);
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private ClassDescriptor getOuterClassDescriptor() {
|
private ClassDescriptor getOuterClassDescriptor() {
|
||||||
if (myClass.getParent() instanceof JetClassObject) {
|
if (myClass.getParent() instanceof JetClassObject) {
|
||||||
|
|||||||
@@ -4,12 +4,17 @@ import com.intellij.psi.PsiClass;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
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.JetDelegationSpecifier;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetEnumEntry;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.objectweb.asm.ClassVisitor;
|
import org.objectweb.asm.ClassVisitor;
|
||||||
import org.objectweb.asm.Opcodes;
|
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.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -18,6 +23,8 @@ import java.util.Set;
|
|||||||
* @author yole
|
* @author yole
|
||||||
*/
|
*/
|
||||||
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
||||||
|
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
|
||||||
|
|
||||||
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
public InterfaceBodyCodegen(JetClassOrObject aClass, ClassContext context, ClassVisitor v, GenerationState state) {
|
||||||
super(aClass, context, v, state);
|
super(aClass, context, v, state);
|
||||||
assert context.getContextKind() == OwnerKind.INTERFACE;
|
assert context.getContextKind() == OwnerKind.INTERFACE;
|
||||||
@@ -73,4 +80,37 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
return superInterfaces;
|
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;
|
package org.jetbrains.jet.codegen;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -130,4 +131,13 @@ public class ClassGenTest extends CodegenTestCase {
|
|||||||
Object result = method.invoke(null);
|
Object result = method.invoke(null);
|
||||||
assertInstanceOf(result, Runnable.class);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user