From 8f71c188e9c52de05035076227e3645f8d0ce183 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Fri, 8 Jul 2011 16:45:09 +0200 Subject: [PATCH] correctly generate supertypes of class objects and object literals --- .../jet/codegen/ImplementationBodyCodegen.java | 7 +++++++ .../jetbrains/jet/codegen/InterfaceBodyCodegen.java | 13 +++++++------ .../codegen/classes/classObjectInterface.jet | 9 +++++++++ .../org/jetbrains/jet/codegen/ClassGenTest.java | 7 +++++++ 4 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 idea/testData/codegen/classes/classObjectInterface.jet diff --git a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index fc5da7d85d3..f013f20e2d9 100644 --- a/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -34,6 +34,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (!(myClass instanceof JetObjectDeclaration)) { interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor)); } + else { + interfaces.addAll(InterfaceBodyCodegen.getSuperInterfaces(myClass, state.getBindingContext())); + } boolean isAbstract = myClass instanceof JetClass && ((JetClass) myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD); @@ -59,6 +62,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (first instanceof JetDelegatorToSuperClass || first instanceof JetDelegatorToSuperCall) { JetType superType = state.getBindingContext().resolveTypeReference(first.getTypeReference()); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); + final PsiElement declaration = state.getBindingContext().getDeclarationPsiElement(superClassDescriptor); + if (declaration instanceof PsiClass && ((PsiClass) declaration).isInterface()) { + return "java/lang/Object"; + } return state.getTypeMapper().jvmName(superClassDescriptor, kind); } diff --git a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java index e14303bcf89..2c7fb25aa0b 100644 --- a/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java +++ b/idea/src/org/jetbrains/jet/codegen/InterfaceBodyCodegen.java @@ -5,6 +5,7 @@ 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.JetDelegationSpecifier; +import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.types.JetType; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.Opcodes; @@ -23,7 +24,7 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen { } protected void generateDeclaration() { - Set superInterfaces = getSuperInterfaces(); + Set superInterfaces = getSuperInterfaces(myClass, state.getBindingContext()); String fqName = JetTypeMapper.jvmNameForInterface(descriptor); v.visit(Opcodes.V1_6, @@ -35,20 +36,20 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen { ); } - private Set getSuperInterfaces() { - List delegationSpecifiers = myClass.getDelegationSpecifiers(); + static Set getSuperInterfaces(JetClassOrObject aClass, final BindingContext bindingContext) { + List delegationSpecifiers = aClass.getDelegationSpecifiers(); String superClassName = null; Set superInterfaces = new LinkedHashSet(); for (JetDelegationSpecifier specifier : delegationSpecifiers) { - JetType superType = state.getBindingContext().resolveTypeReference(specifier.getTypeReference()); + JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference()); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); - PsiElement superPsi = state.getBindingContext().getDeclarationPsiElement(superClassDescriptor); + PsiElement superPsi = bindingContext.getDeclarationPsiElement(superClassDescriptor); if (superPsi instanceof PsiClass) { PsiClass psiClass = (PsiClass) superPsi; String fqn = psiClass.getQualifiedName(); if (psiClass.isInterface()) { - superInterfaces.add(fqn); + superInterfaces.add(fqn.replace('.', '/')); } else { if (superClassName == null) { diff --git a/idea/testData/codegen/classes/classObjectInterface.jet b/idea/testData/codegen/classes/classObjectInterface.jet new file mode 100644 index 00000000000..8c0cb8210c4 --- /dev/null +++ b/idea/testData/codegen/classes/classObjectInterface.jet @@ -0,0 +1,9 @@ +class C() { + fun getInstance(): Runnable = C + + class object: Runnable { + fun run(): Unit { } + } +} + +fun foo() = C().getInstance() diff --git a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java index 5c361782df3..b051e854244 100644 --- a/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java +++ b/idea/tests/org/jetbrains/jet/codegen/ClassGenTest.java @@ -123,4 +123,11 @@ public class ClassGenTest extends CodegenTestCase { public void testClassObjectMethod() throws Exception { blackBoxFile("classes/classObjectMethod.jet"); } + + public void testClassObjectInterface() throws Exception { + loadFile("classes/classObjectInterface.jet"); + final Method method = generateFunction(); + Object result = method.invoke(null); + assertInstanceOf(result, Runnable.class); + } }