Write proper enclosingMethod/enclosingClass information to bytecode
This commit is contained in:
@@ -39,12 +39,14 @@ import org.jetbrains.jet.codegen.state.JetTypeMapperMode;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.OverridingUtil;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
@@ -184,9 +186,50 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void writeOuterClass() {
|
||||
ClassDescriptor container = getContainingClassDescriptor(descriptor);
|
||||
//JVMS7: A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
|
||||
DeclarationDescriptor parentDescriptor = descriptor.getContainingDeclaration();
|
||||
|
||||
boolean isObjectLiteral = descriptor.getName().isSpecial() && descriptor.getKind() == ClassKind.OBJECT;
|
||||
|
||||
boolean isLocalOrAnonymousClass = isObjectLiteral ||
|
||||
!(parentDescriptor instanceof NamespaceDescriptor || parentDescriptor instanceof ClassDescriptor);
|
||||
if (isLocalOrAnonymousClass) {
|
||||
String outerClassName = getOuterClassName(descriptor, typeMapper, bindingContext, state);
|
||||
FunctionDescriptor function = DescriptorUtils.getParentOfType(descriptor, FunctionDescriptor.class);
|
||||
|
||||
//Function descriptor could be null only for object literal in package namespace
|
||||
assert (!isObjectLiteral && function != null) || isObjectLiteral:
|
||||
"Function descriptor should be present: " + descriptor.getName();
|
||||
|
||||
Name functionName = function != null ? function.getName() : null;
|
||||
|
||||
v.visitOuterClass(outerClassName,
|
||||
functionName != null ? functionName.getName() : null,
|
||||
functionName != null ? typeMapper.mapSignature(functionName, function).getAsmMethod().getDescriptor() : null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getOuterClassName(
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull JetTypeMapper typeMapper,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull GenerationState state
|
||||
) {
|
||||
ClassDescriptor container = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class);
|
||||
if (container != null) {
|
||||
v.visitOuterClass(typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName(), null, null);
|
||||
return typeMapper.mapType(container.getDefaultType(), JetTypeMapperMode.IMPL).getInternalName();
|
||||
}
|
||||
else {
|
||||
NamespaceDescriptor namespaceDescriptor = DescriptorUtils.getParentOfType(classDescriptor, NamespaceDescriptor.class);
|
||||
assert namespaceDescriptor != null : "Namespace descriptor should be present: " + classDescriptor.getName();
|
||||
FqName namespaceQN = namespaceDescriptor.getQualifiedName();
|
||||
boolean isMultiFile = CodegenBinding.isMultiFileNamespace(state.getBindingContext(), namespaceQN);
|
||||
return isMultiFile
|
||||
? NamespaceCodegen.getNamespacePartInternalName(
|
||||
BindingContextUtils.getContainingFile(bindingContext, classDescriptor))
|
||||
: NamespaceCodegen.getJVMClassNameForKotlinNs(namespaceQN).getInternalName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,16 +285,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
annotationVisitor.visitEnd();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ClassDescriptor getContainingClassDescriptor(ClassDescriptor decl) {
|
||||
DeclarationDescriptor container = decl.getContainingDeclaration();
|
||||
while (container != null && !(container instanceof NamespaceDescriptor)) {
|
||||
if (container instanceof ClassDescriptor) return (ClassDescriptor) container;
|
||||
container = container.getContainingDeclaration();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private JvmClassSignature signature() {
|
||||
List<String> superInterfaces;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user