Write inner class attributes

This commit is contained in:
Michael Bogdanov
2016-09-30 15:00:46 +03:00
committed by Dmitry Petrov
parent 0b45655b7b
commit e40c434c57
3 changed files with 40 additions and 7 deletions
@@ -315,6 +315,10 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
} }
private void writeInnerClass(@NotNull ClassDescriptor innerClass) { private void writeInnerClass(@NotNull ClassDescriptor innerClass) {
writeInnerClass(innerClass, typeMapper, v);
}
public static void writeInnerClass(@NotNull ClassDescriptor innerClass, @NotNull KotlinTypeMapper typeMapper, @NotNull ClassBuilder v) {
DeclarationDescriptor containing = innerClass.getContainingDeclaration(); DeclarationDescriptor containing = innerClass.getContainingDeclaration();
String outerClassInternalName = null; String outerClassInternalName = null;
if (containing instanceof ClassDescriptor) { if (containing instanceof ClassDescriptor) {
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSpecialDescriptor import org.jetbrains.kotlin.backend.jvm.descriptors.JvmSpecialDescriptor
import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor import org.jetbrains.kotlin.backend.jvm.lower.FileClassDescriptor
import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor import org.jetbrains.kotlin.codegen.MemberCodegen.badDescriptor
import org.jetbrains.kotlin.codegen.binding.CodegenBinding import org.jetbrains.kotlin.codegen.binding.CodegenBinding
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -37,7 +38,9 @@ import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type import org.jetbrains.org.objectweb.asm.Type
import java.lang.RuntimeException import java.lang.RuntimeException
class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBackendContext) { class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBackendContext, val parentClassCodegen: ClassCodegen? = null) {
private val innerClasses = mutableListOf<ClassDescriptor>()
val state = context.state val state = context.state
@@ -71,6 +74,8 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
generateDeclaration(it) generateDeclaration(it)
} }
writeInnerClasses()
visitor.done() visitor.done()
} }
@@ -90,10 +95,6 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
ClassCodegen(irClass, context).generate() ClassCodegen(irClass, context).generate()
} }
fun generateAnonymous(irClass: IrClass, context: JvmBackendContext) {
ClassCodegen(irClass, context).generate()
}
} }
fun generateDeclaration(declaration: IrDeclaration) { fun generateDeclaration(declaration: IrDeclaration) {
@@ -110,7 +111,7 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
// skip // skip
} }
is IrClass -> { is IrClass -> {
ClassCodegen(declaration, context).generate() ClassCodegen(declaration, context, this).generate()
} }
else -> throw RuntimeException("Unsupported declaration $declaration") else -> throw RuntimeException("Unsupported declaration $declaration")
} }
@@ -128,6 +129,34 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac
FunctionCodegen(method, this).generate() FunctionCodegen(method, this).generate()
} }
private fun writeInnerClasses() {
// JVMS7 (4.7.6): a nested class or interface member will have InnerClasses information
// for each enclosing class and for each immediate member
val classDescriptor = classForInnerClassRecord()
if (classDescriptor != null) {
if (parentClassCodegen != null) {
parentClassCodegen.innerClasses.add(classDescriptor)
}
var codegen: ClassCodegen? = this
while (codegen != null) {
val outerClass = codegen.classForInnerClassRecord()
if (outerClass != null) {
innerClasses.add(outerClass)
}
codegen = codegen.parentClassCodegen
}
}
for (innerClass in innerClasses) {
MemberCodegen.writeInnerClass(innerClass, typeMapper, visitor)
}
}
private fun classForInnerClassRecord(): ClassDescriptor? {
return if (parentClassCodegen != null) descriptor else null
}
} }
fun ClassDescriptor.calculateClassFlags(): Int { fun ClassDescriptor.calculateClassFlags(): Int {
@@ -296,7 +296,7 @@ class ExpressionCodegen(
} }
override fun visitClass(declaration: IrClass, data: BlockInfo): StackValue { override fun visitClass(declaration: IrClass, data: BlockInfo): StackValue {
ClassCodegen.generateAnonymous(declaration, classCodegen.context) classCodegen.generateDeclaration(declaration)
return none() return none()
} }