Move generation of non-local interface DefaultImpls

`DefaultImpls` should be inner class of it's interface,
so for proper light classes building it should be built
before original interface has been done, i.e. `done` method called.

Everything is complicated with local interfaces, so they are just left untouched
This commit is contained in:
Denis Zharkov
2015-09-28 11:06:21 +03:00
parent a101fffd9a
commit c1bed7efc7
3 changed files with 24 additions and 12 deletions
@@ -211,8 +211,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION); ClassContext objectContext = context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION);
MemberCodegen literalCodegen = new ImplementationBodyCodegen( MemberCodegen literalCodegen = new ImplementationBodyCodegen(
objectDeclaration, objectContext, classBuilder, state, getParentCodegen() objectDeclaration, objectContext, classBuilder, state, getParentCodegen(),
); /* isLocal = */ true);
literalCodegen.generate(); literalCodegen.generate();
addReifiedParametersFromSignature(literalCodegen, classDescriptor); addReifiedParametersFromSignature(literalCodegen, classDescriptor);
@@ -330,7 +330,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
ClassBuilder classBuilder = state.getFactory().newVisitor(OtherOrigin(declaration, descriptor), asmType, declaration.getContainingFile()); ClassBuilder classBuilder = state.getFactory().newVisitor(OtherOrigin(declaration, descriptor), asmType, declaration.getContainingFile());
ClassContext objectContext = context.intoAnonymousClass(descriptor, this, OwnerKind.IMPLEMENTATION); ClassContext objectContext = context.intoAnonymousClass(descriptor, this, OwnerKind.IMPLEMENTATION);
new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, getParentCodegen()).generate(); new ImplementationBodyCodegen(declaration, objectContext, classBuilder, state, getParentCodegen(), /* isLocal = */ true).generate();
if (declaration instanceof JetClass && ((JetClass) declaration).isInterface()) { if (declaration instanceof JetClass && ((JetClass) declaration).isInterface()) {
Type traitImplType = state.getTypeMapper().mapDefaultImpls(descriptor); Type traitImplType = state.getTypeMapper().mapDefaultImpls(descriptor);
@@ -100,6 +100,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@Nullable // null means java/lang/Object @Nullable // null means java/lang/Object
private JetType superClassType; private JetType superClassType;
private final Type classAsmType; private final Type classAsmType;
private final boolean isLocal;
private List<PropertyAndDefaultValue> companionObjectPropertiesToCopy; private List<PropertyAndDefaultValue> companionObjectPropertiesToCopy;
@@ -111,10 +112,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
@NotNull ClassContext context, @NotNull ClassContext context,
@NotNull ClassBuilder v, @NotNull ClassBuilder v,
@NotNull GenerationState state, @NotNull GenerationState state,
@Nullable MemberCodegen<?> parentCodegen @Nullable MemberCodegen<?> parentCodegen,
boolean isLocal
) { ) {
super(aClass, context, v, state, parentCodegen); super(aClass, context, v, state, parentCodegen);
this.classAsmType = typeMapper.mapClass(descriptor); this.classAsmType = typeMapper.mapClass(descriptor);
this.isLocal = isLocal;
} }
@Override @Override
@@ -231,6 +234,22 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
generateEnumEntries(); generateEnumEntries();
} }
@Override
protected void generateBody() {
super.generateBody();
if (isInterface(descriptor) && !isLocal) {
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
ClassBuilder defaultImplsBuilder =
state.getFactory().newVisitor(TraitImpl(myClass, descriptor), defaultImplsType, myClass.getContainingFile());
CodegenContext parentContext = context.getParentContext();
assert parentContext != null : "Parent context of interface declaration should not be null";
ClassContext defaultImplsContext = parentContext.intoClass(descriptor, OwnerKind.DEFAULT_IMPLS, state);
new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
}
}
@Override @Override
protected void generateKotlinAnnotation() { protected void generateKotlinAnnotation() {
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
@@ -205,14 +205,7 @@ public abstract class MemberCodegen<T extends JetElement/* TODO: & JetDeclaratio
Type classType = state.getTypeMapper().mapClass(descriptor); Type classType = state.getTypeMapper().mapClass(descriptor);
ClassBuilder classBuilder = state.getFactory().newVisitor(OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile()); ClassBuilder classBuilder = state.getFactory().newVisitor(OtherOrigin(aClass, descriptor), classType, aClass.getContainingFile());
ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state); ClassContext classContext = parentContext.intoClass(descriptor, OwnerKind.IMPLEMENTATION, state);
new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen).generate(); new ImplementationBodyCodegen(aClass, classContext, classBuilder, state, parentCodegen, false).generate();
if (aClass instanceof JetClass && ((JetClass) aClass).isInterface()) {
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
ClassBuilder defaultImplsBuilder = state.getFactory().newVisitor(TraitImpl(aClass, descriptor), defaultImplsType, aClass.getContainingFile());
ClassContext defaultImplsContext = parentContext.intoClass(descriptor, OwnerKind.DEFAULT_IMPLS, state);
new InterfaceImplBodyCodegen(aClass, defaultImplsContext, defaultImplsBuilder, state, parentCodegen).generate();
}
} }
private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) { private static void badDescriptor(ClassDescriptor descriptor, ClassBuilderMode mode) {