Inner class generation now performed on visiting appropriate declaration

This commit is contained in:
Mikhael Bogdanov
2013-04-22 11:07:51 +04:00
parent 5baa10df41
commit 9682b72643
4 changed files with 25 additions and 71 deletions
@@ -34,6 +34,7 @@ import java.util.List;
import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
public abstract class ClassBodyCodegen extends MemberCodegen {
protected final JetClassOrObject myClass;
@@ -85,6 +86,17 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) {
genFunctionOrProperty(context, (JetTypeParameterListOwner) declaration, v);
}
else if (declaration instanceof JetClassOrObject) {
if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(
state.getBindingContext(), (JetEnumEntry) declaration)) {
return;
}
genClassOrObject(context, (JetClassOrObject) declaration);
}
else if (declaration instanceof JetClassObject) {
genClassOrObject(context, ((JetClassObject) declaration).getObjectDeclaration());
}
}
private void generatePrimaryConstructorProperties(PropertyCodegen propertyCodegen, JetClassOrObject origin) {
@@ -121,15 +121,9 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
//noinspection SuspiciousMethodCalls
CalculatedClosure closure = bindingContext.get(CLOSURE, classDescriptor);
CodegenContext contextForInners = context.intoClass(classDescriptor, OwnerKind.IMPLEMENTATION, state);
CodegenContext objectContext = context.intoAnonymousClass(classDescriptor, this);
ImplementationBodyCodegen implementationBodyCodegen = new ImplementationBodyCodegen(objectDeclaration, objectContext, classBuilder, state);
implementationBodyCodegen.genInners(contextForInners, state, objectDeclaration);
objectContext.copyAccessors(contextForInners.getAccessors());
implementationBodyCodegen.generate();
return closure;
@@ -1508,10 +1508,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) {
if (declaration instanceof JetClassObject || declaration instanceof JetObjectDeclaration) {
// done earlier in order to have accessors
}
else if (declaration instanceof JetEnumEntry) {
if (declaration instanceof JetEnumEntry) {
String name = declaration.getName();
String desc = "L" + classAsmType.getInternalName() + ";";
v.newField(declaration, ACC_PUBLIC | ACC_ENUM | ACC_STATIC | ACC_FINAL, name, desc, null, null);
@@ -1525,9 +1522,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
}
myEnumConstants.add((JetEnumEntry) declaration);
}
else {
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
}
super.generateDeclaration(propertyCodegen, declaration, functionCodegen);
}
private final List<JetEnumEntry> myEnumConstants = new ArrayList<JetEnumEntry>();
@@ -68,48 +68,7 @@ public class MemberCodegen extends GenerationStateAware {
}
}
public static void genImplementation(
CodegenContext context,
GenerationState state,
JetClassOrObject aClass,
OwnerKind kind,
Map<DeclarationDescriptor, DeclarationDescriptor> accessors,
ClassBuilder classBuilder
) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
CodegenContext classContext = context.intoClass(descriptor, kind, state);
classContext.copyAccessors(accessors);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile());
new TraitImplBodyCodegen(aClass, context.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
.generate();
traitBuilder.done();
}
}
public void genInners(CodegenContext context, GenerationState state, JetClassOrObject aClass) {
for (JetDeclaration declaration : aClass.getDeclarations()) {
if (declaration instanceof JetClass) {
if (declaration instanceof JetEnumEntry && !enumEntryNeedSubclass(
state.getBindingContext(), (JetEnumEntry) declaration)) {
continue;
}
genClassOrObject(context, (JetClass) declaration);
}
else if (declaration instanceof JetClassObject) {
genClassOrObject(context, ((JetClassObject) declaration).getObjectDeclaration());
}
else if (declaration instanceof JetObjectDeclaration) {
genClassOrObject(context, (JetObjectDeclaration) declaration);
}
}
}
public void genClassOrObject(CodegenContext context, JetClassOrObject aClass) {
public void genClassOrObject(CodegenContext parentContext, JetClassOrObject aClass) {
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, aClass);
if (descriptor == null || ErrorUtils.isError(descriptor) || descriptor.getName().equals(JetPsiUtil.NO_NAME_PROVIDED)) {
@@ -121,22 +80,15 @@ public class MemberCodegen extends GenerationStateAware {
}
ClassBuilder classBuilder = state.getFactory().forClassImplementation(descriptor, aClass.getContainingFile());
CodegenContext contextForInners = context.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
if (state.getClassBuilderMode() == ClassBuilderMode.SIGNATURES) {
// Outer class implementation must happen prior inner classes so we get proper scoping tree in JetLightClass's delegate
// The same code is present below for the case when we genClassOrObject real bytecode. This is because the order should be
// different for the case when we compute closures
genImplementation(context, state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
genInners(contextForInners, state, aClass);
if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) {
genImplementation(context, state, aClass, OwnerKind.IMPLEMENTATION, contextForInners.getAccessors(), classBuilder);
}
CodegenContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state).generate();
classBuilder.done();
if (aClass instanceof JetClass && ((JetClass) aClass).isTrait()) {
ClassBuilder traitBuilder = state.getFactory().forTraitImplementation(descriptor, state, aClass.getContainingFile());
new TraitImplBodyCodegen(aClass, parentContext.intoClass(descriptor, OwnerKind.TRAIT_IMPL, state), traitBuilder, state)
.generate();
traitBuilder.done();
}
}
}