correctly generate supertypes of class objects and object literals

This commit is contained in:
Dmitry Jemerov
2011-07-08 16:45:09 +02:00
parent d4020a422b
commit 8f71c188e9
4 changed files with 30 additions and 6 deletions
@@ -34,6 +34,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (!(myClass instanceof JetObjectDeclaration)) { if (!(myClass instanceof JetObjectDeclaration)) {
interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor)); interfaces.add(JetTypeMapper.jvmNameForInterface(descriptor));
} }
else {
interfaces.addAll(InterfaceBodyCodegen.getSuperInterfaces(myClass, state.getBindingContext()));
}
boolean isAbstract = myClass instanceof JetClass && ((JetClass) myClass).hasModifier(JetTokens.ABSTRACT_KEYWORD); 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) { if (first instanceof JetDelegatorToSuperClass || first instanceof JetDelegatorToSuperCall) {
JetType superType = state.getBindingContext().resolveTypeReference(first.getTypeReference()); JetType superType = state.getBindingContext().resolveTypeReference(first.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); 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); return state.getTypeMapper().jvmName(superClassDescriptor, kind);
} }
@@ -5,6 +5,7 @@ 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.JetDelegationSpecifier; import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
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;
@@ -23,7 +24,7 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
} }
protected void generateDeclaration() { protected void generateDeclaration() {
Set<String> superInterfaces = getSuperInterfaces(); Set<String> superInterfaces = getSuperInterfaces(myClass, state.getBindingContext());
String fqName = JetTypeMapper.jvmNameForInterface(descriptor); String fqName = JetTypeMapper.jvmNameForInterface(descriptor);
v.visit(Opcodes.V1_6, v.visit(Opcodes.V1_6,
@@ -35,20 +36,20 @@ public class InterfaceBodyCodegen extends ClassBodyCodegen {
); );
} }
private Set<String> getSuperInterfaces() { static Set<String> getSuperInterfaces(JetClassOrObject aClass, final BindingContext bindingContext) {
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers(); List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
String superClassName = null; String superClassName = null;
Set<String> superInterfaces = new LinkedHashSet<String>(); Set<String> superInterfaces = new LinkedHashSet<String>();
for (JetDelegationSpecifier specifier : delegationSpecifiers) { for (JetDelegationSpecifier specifier : delegationSpecifiers) {
JetType superType = state.getBindingContext().resolveTypeReference(specifier.getTypeReference()); JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference());
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor(); ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
PsiElement superPsi = state.getBindingContext().getDeclarationPsiElement(superClassDescriptor); PsiElement superPsi = bindingContext.getDeclarationPsiElement(superClassDescriptor);
if (superPsi instanceof PsiClass) { if (superPsi instanceof PsiClass) {
PsiClass psiClass = (PsiClass) superPsi; PsiClass psiClass = (PsiClass) superPsi;
String fqn = psiClass.getQualifiedName(); String fqn = psiClass.getQualifiedName();
if (psiClass.isInterface()) { if (psiClass.isInterface()) {
superInterfaces.add(fqn); superInterfaces.add(fqn.replace('.', '/'));
} }
else { else {
if (superClassName == null) { if (superClassName == null) {
@@ -0,0 +1,9 @@
class C() {
fun getInstance(): Runnable = C
class object: Runnable {
fun run(): Unit { }
}
}
fun foo() = C().getInstance()
@@ -123,4 +123,11 @@ public class ClassGenTest extends CodegenTestCase {
public void testClassObjectMethod() throws Exception { public void testClassObjectMethod() throws Exception {
blackBoxFile("classes/classObjectMethod.jet"); 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);
}
} }