From e645da64da114ebf6e9b51d8de3f72dcb6857eea Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Thu, 24 Aug 2017 18:40:24 +0300 Subject: [PATCH] Parcelable: Use the Parcelable implementation class as a containing declaration for Creator (KT-19899) --- .../parcel/ParcelableCodegenExtension.kt | 2 +- .../testData/parcel/codegen/simple.kt | 1 + .../testData/parcel/codegen/simple.txt | 12 +++++++ .../AbstractAsmLikeInstructionListingTest.kt | 34 ++++++++++++++++--- 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt index 91c0bdcd26d..11f5ccd6104 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableCodegenExtension.kt @@ -230,7 +230,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension { codegen.typeMapper.typeMappingConfiguration.innerClassNameFactory(containerAsmType.internalName, "Creator")) val creatorClass = ClassDescriptorImpl( - parcelableClass.containingDeclaration, Name.identifier("Creator"), Modality.FINAL, ClassKind.CLASS, emptyList(), + parcelableClass, Name.identifier("Creator"), Modality.FINAL, ClassKind.CLASS, emptyList(), parcelableClass.source, false) creatorClass.initialize( diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.kt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.kt index 06836514910..ab426614a1a 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.kt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.kt @@ -1,4 +1,5 @@ // CURIOUS_ABOUT writeToParcel, createFromParcel, , describeContents +// LOCAL_VARIABLES_TABLE import kotlinx.android.parcel.* import android.os.Parcelable diff --git a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.txt b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.txt index 5a31f8335a8..469b6ba2919 100644 --- a/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.txt +++ b/plugins/android-extensions/android-extensions-compiler/testData/parcel/codegen/simple.txt @@ -19,6 +19,10 @@ public static class User$Creator : java/lang/Object, android/os/Parcelable$Creat INVOKESPECIAL (User, , (Ljava/lang/String;Ljava/lang/String;IZ)V) ARETURN LABEL (L1) + + Local variables: + this: LUser$Creator; + in: Landroid/os/Parcel; } public final User[] newArray(int p0) @@ -50,6 +54,9 @@ public final class User : java/lang/Object, android/os/Parcelable { LDC (0) IRETURN LABEL (L1) + + Local variables: + this: LUser; } public final int getAge() @@ -83,5 +90,10 @@ public final class User : java/lang/Object, android/os/Parcelable { INVOKEVIRTUAL (android/os/Parcel, writeInt, (I)V) RETURN LABEL (L1) + + Local variables: + this: LUser; + parcel: Landroid/os/Parcel; + flags: I } } diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractAsmLikeInstructionListingTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractAsmLikeInstructionListingTest.kt index c038943f14e..f9d1caac46f 100644 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractAsmLikeInstructionListingTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/android/parcel/AbstractAsmLikeInstructionListingTest.kt @@ -32,6 +32,7 @@ private val LINE_SEPARATOR = System.getProperty("line.separator") abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { private companion object { val CURIOUS_ABOUT_DIRECTIVE = "// CURIOUS_ABOUT " + val LOCAL_VARIABLES_TABLE_DIRECTIVE = "// LOCAL_VARIABLES_TABLE" } override fun doMultiFileTest(wholeFile: File, files: List, javaFilesDir: File?) { @@ -43,17 +44,21 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { .sortedBy { it.relativePath } .map { file -> ClassNode().also { ClassReader(file.asByteArray()).accept(it, ClassReader.EXPAND_FRAMES) } } - val printBytecodeForTheseMethods = wholeFile.readLines() + val testFileLines = wholeFile.readLines() + + val printBytecodeForTheseMethods = testFileLines .filter { it.startsWith(CURIOUS_ABOUT_DIRECTIVE) } .map { it.substring(CURIOUS_ABOUT_DIRECTIVE.length) } .flatMap { it.split(',').map { it.trim() } } + val showLocalVariables = testFileLines.any { it.trim() == LOCAL_VARIABLES_TABLE_DIRECTIVE } + KotlinTestUtils.assertEqualsToFile(txtFile, classes.joinToString(LINE_SEPARATOR.repeat(2)) { - renderClassNode(it, printBytecodeForTheseMethods) + renderClassNode(it, printBytecodeForTheseMethods, showLocalVariables) }) } - private fun renderClassNode(clazz: ClassNode, printBytecodeForTheseMethods: List): String { + private fun renderClassNode(clazz: ClassNode, printBytecodeForTheseMethods: List, showLocalVariables: Boolean): String { val fields = (clazz.fields ?: emptyList()).sortedBy { it.name } val methods = (clazz.methods ?: emptyList()).sortedBy { it.name } @@ -79,7 +84,7 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { methods.joinTo(this, LINE_SEPARATOR.repeat(2)) { val printBytecode = printBytecodeForTheseMethods.contains(it.name) - renderMethod(it, printBytecode).withMargin() + renderMethod(it, printBytecode, showLocalVariables).withMargin() } appendln().append("}") @@ -93,7 +98,7 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { append(field.name) } - private fun renderMethod(method: MethodNode, printBytecode: Boolean) = buildString { + private fun renderMethod(method: MethodNode, printBytecode: Boolean, showLocalVariables: Boolean) = buildString { renderVisibilityModifiers(method.access) renderModalityModifiers(method.access) val (returnType, parameterTypes) = with(Type.getMethodType(method.desc)) { returnType to argumentTypes } @@ -104,10 +109,29 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() { if (printBytecode && (method.access and ACC_ABSTRACT) == 0) { appendln(" {") append(renderBytecodeInstructions(method.instructions).trimEnd().withMargin()) + + if (showLocalVariables) { + val localVariableTable = buildLocalVariableTable(method) + if (localVariableTable.isNotEmpty()) { + appendln().appendln() + append(localVariableTable.withMargin()) + } + } + appendln().append("}") } } + private fun buildLocalVariableTable(method: MethodNode): String { + val localVariables = method.localVariables?.takeIf { it.isNotEmpty() } ?: return "" + return buildString { + append("Local variables:") + for (variable in localVariables) { + appendln().append((variable.name + ": " + variable.desc).withMargin()) + } + } + } + private fun renderBytecodeInstructions(instructions: InsnList) = buildString { val labelMappings = LabelMappings()