generate implementation / delegating implementation classes
This commit is contained in:
@@ -11,7 +11,6 @@ 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 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;
|
||||||
@@ -32,6 +31,8 @@ public class ClassCodegen {
|
|||||||
|
|
||||||
public void generate(JetClass aClass) {
|
public void generate(JetClass aClass) {
|
||||||
generateInterface(aClass);
|
generateInterface(aClass);
|
||||||
|
generateImplementation(aClass, OwnerKind.IMPLEMENTATION);
|
||||||
|
generateImplementation(aClass, OwnerKind.DELEGATING_IMPLEMENTATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateInterface(JetClass aClass) {
|
private void generateInterface(JetClass aClass) {
|
||||||
@@ -43,17 +44,74 @@ public class ClassCodegen {
|
|||||||
ClassVisitor v = factory.forClassInterface(descriptor);
|
ClassVisitor v = factory.forClassInterface(descriptor);
|
||||||
v.visit(Opcodes.V1_6,
|
v.visit(Opcodes.V1_6,
|
||||||
Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT,
|
Opcodes.ACC_PUBLIC | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT,
|
||||||
fqName.replace('.', '/'),
|
fqName,
|
||||||
null,
|
null,
|
||||||
"java/lang/Object",
|
"java/lang/Object",
|
||||||
superInterfaces.toArray(new String[superInterfaces.size()])
|
superInterfaces.toArray(new String[superInterfaces.size()])
|
||||||
);
|
);
|
||||||
|
|
||||||
generateClassBody(aClass, v);
|
generateClassBody(aClass, v, OwnerKind.INTERFACE);
|
||||||
|
|
||||||
v.visitEnd();
|
v.visitEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateImplementation(JetClass aClass, OwnerKind kind) {
|
||||||
|
ClassDescriptor descriptor = bindingContext.getClassDescriptor(aClass);
|
||||||
|
|
||||||
|
String superClass = getSuperClass(aClass, kind);
|
||||||
|
|
||||||
|
ClassVisitor v = kind == OwnerKind.IMPLEMENTATION ? factory.forClassImplementation(descriptor) : factory.forClassDelegatingImplementation(descriptor);
|
||||||
|
v.visit(Opcodes.V1_6,
|
||||||
|
Opcodes.ACC_PUBLIC,
|
||||||
|
CodeGenUtil.getInternalImplementationName(descriptor),
|
||||||
|
null,
|
||||||
|
superClass,
|
||||||
|
new String[] {CodeGenUtil.getInternalInterfaceName(descriptor)}
|
||||||
|
);
|
||||||
|
|
||||||
|
generateClassBody(aClass, v, kind);
|
||||||
|
|
||||||
|
v.visitEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getSuperClass(JetClass aClass, OwnerKind kind) {
|
||||||
|
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
|
||||||
|
String superClassName = null;
|
||||||
|
Set<ClassDescriptor> superInterfaces = new LinkedHashSet<ClassDescriptor>();
|
||||||
|
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||||
|
JetType superType = bindingContext.resolveTypeReference(specifier.getTypeReference());
|
||||||
|
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||||
|
PsiElement superPsi = bindingContext.getDeclarationPsiElement(superClassDescriptor);
|
||||||
|
|
||||||
|
if (superPsi instanceof PsiClass) {
|
||||||
|
PsiClass psiClass = (PsiClass) superPsi;
|
||||||
|
String fqn = psiClass.getQualifiedName();
|
||||||
|
if (!psiClass.isInterface()) {
|
||||||
|
if (superClassName == null) {
|
||||||
|
superClassName = fqn.replace('.', '/');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new RuntimeException("Cannot determine single class to inherit from");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
superInterfaces.add(superClassDescriptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superClassName != null) {
|
||||||
|
return superClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (superInterfaces.size() > 0) {
|
||||||
|
ClassDescriptor first = superInterfaces.iterator().next();
|
||||||
|
return kind == OwnerKind.IMPLEMENTATION ? CodeGenUtil.getInternalImplementationName(first) : CodeGenUtil.getInternalDelegatingImplementationName(first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "java/lang/Object";
|
||||||
|
}
|
||||||
|
|
||||||
private Set<String> getSuperInterfaces(JetClass aClass) {
|
private Set<String> getSuperInterfaces(JetClass aClass) {
|
||||||
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
|
List<JetDelegationSpecifier> delegationSpecifiers = aClass.getDelegationSpecifiers();
|
||||||
String superClassName = null;
|
String superClassName = null;
|
||||||
@@ -92,16 +150,16 @@ public class ClassCodegen {
|
|||||||
return superInterfaces;
|
return superInterfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateClassBody(JetClass aClass, ClassVisitor v) {
|
private void generateClassBody(JetClass aClass, ClassVisitor v, OwnerKind kind) {
|
||||||
final PropertyCodegen propertyCodegen = new PropertyCodegen(v);
|
final PropertyCodegen propertyCodegen = new PropertyCodegen(v);
|
||||||
final FunctionCodegen functionCodegen = new FunctionCodegen(v, JetStandardLibrary.getJetStandardLibrary(project), bindingContext);
|
final FunctionCodegen functionCodegen = new FunctionCodegen(v, JetStandardLibrary.getJetStandardLibrary(project), bindingContext);
|
||||||
|
|
||||||
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
for (JetDeclaration declaration : aClass.getDeclarations()) {
|
||||||
if (declaration instanceof JetProperty) {
|
if (declaration instanceof JetProperty) {
|
||||||
propertyCodegen.gen((JetProperty) declaration, OwnerKind.INTERFACE);
|
propertyCodegen.gen((JetProperty) declaration, kind);
|
||||||
}
|
}
|
||||||
else if (declaration instanceof JetFunction) {
|
else if (declaration instanceof JetFunction) {
|
||||||
functionCodegen.gen((JetFunction) declaration, OwnerKind.INTERFACE);
|
functionCodegen.gen((JetFunction) declaration, kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user