Parcelable: Use the Parcelable implementation class as a containing declaration for Creator (KT-19899)
This commit is contained in:
committed by
Yan Zhulanow
parent
f8ca714c45
commit
e645da64da
+1
-1
@@ -230,7 +230,7 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
|
|||||||
codegen.typeMapper.typeMappingConfiguration.innerClassNameFactory(containerAsmType.internalName, "Creator"))
|
codegen.typeMapper.typeMappingConfiguration.innerClassNameFactory(containerAsmType.internalName, "Creator"))
|
||||||
|
|
||||||
val creatorClass = ClassDescriptorImpl(
|
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)
|
parcelableClass.source, false)
|
||||||
|
|
||||||
creatorClass.initialize(
|
creatorClass.initialize(
|
||||||
|
|||||||
+1
@@ -1,4 +1,5 @@
|
|||||||
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>, describeContents
|
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>, describeContents
|
||||||
|
// LOCAL_VARIABLES_TABLE
|
||||||
|
|
||||||
import kotlinx.android.parcel.*
|
import kotlinx.android.parcel.*
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
|||||||
+12
@@ -19,6 +19,10 @@ public static class User$Creator : java/lang/Object, android/os/Parcelable$Creat
|
|||||||
INVOKESPECIAL (User, <init>, (Ljava/lang/String;Ljava/lang/String;IZ)V)
|
INVOKESPECIAL (User, <init>, (Ljava/lang/String;Ljava/lang/String;IZ)V)
|
||||||
ARETURN
|
ARETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
|
|
||||||
|
Local variables:
|
||||||
|
this: LUser$Creator;
|
||||||
|
in: Landroid/os/Parcel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final User[] newArray(int p0)
|
public final User[] newArray(int p0)
|
||||||
@@ -50,6 +54,9 @@ public final class User : java/lang/Object, android/os/Parcelable {
|
|||||||
LDC (0)
|
LDC (0)
|
||||||
IRETURN
|
IRETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
|
|
||||||
|
Local variables:
|
||||||
|
this: LUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final int getAge()
|
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)
|
INVOKEVIRTUAL (android/os/Parcel, writeInt, (I)V)
|
||||||
RETURN
|
RETURN
|
||||||
LABEL (L1)
|
LABEL (L1)
|
||||||
|
|
||||||
|
Local variables:
|
||||||
|
this: LUser;
|
||||||
|
parcel: Landroid/os/Parcel;
|
||||||
|
flags: I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+29
-5
@@ -32,6 +32,7 @@ private val LINE_SEPARATOR = System.getProperty("line.separator")
|
|||||||
abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
||||||
private companion object {
|
private companion object {
|
||||||
val CURIOUS_ABOUT_DIRECTIVE = "// CURIOUS_ABOUT "
|
val CURIOUS_ABOUT_DIRECTIVE = "// CURIOUS_ABOUT "
|
||||||
|
val LOCAL_VARIABLES_TABLE_DIRECTIVE = "// LOCAL_VARIABLES_TABLE"
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
|
override fun doMultiFileTest(wholeFile: File, files: List<TestFile>, javaFilesDir: File?) {
|
||||||
@@ -43,17 +44,21 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
|||||||
.sortedBy { it.relativePath }
|
.sortedBy { it.relativePath }
|
||||||
.map { file -> ClassNode().also { ClassReader(file.asByteArray()).accept(it, ClassReader.EXPAND_FRAMES) } }
|
.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) }
|
.filter { it.startsWith(CURIOUS_ABOUT_DIRECTIVE) }
|
||||||
.map { it.substring(CURIOUS_ABOUT_DIRECTIVE.length) }
|
.map { it.substring(CURIOUS_ABOUT_DIRECTIVE.length) }
|
||||||
.flatMap { it.split(',').map { it.trim() } }
|
.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)) {
|
KotlinTestUtils.assertEqualsToFile(txtFile, classes.joinToString(LINE_SEPARATOR.repeat(2)) {
|
||||||
renderClassNode(it, printBytecodeForTheseMethods)
|
renderClassNode(it, printBytecodeForTheseMethods, showLocalVariables)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderClassNode(clazz: ClassNode, printBytecodeForTheseMethods: List<String>): String {
|
private fun renderClassNode(clazz: ClassNode, printBytecodeForTheseMethods: List<String>, showLocalVariables: Boolean): String {
|
||||||
val fields = (clazz.fields ?: emptyList()).sortedBy { it.name }
|
val fields = (clazz.fields ?: emptyList()).sortedBy { it.name }
|
||||||
val methods = (clazz.methods ?: 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)) {
|
methods.joinTo(this, LINE_SEPARATOR.repeat(2)) {
|
||||||
val printBytecode = printBytecodeForTheseMethods.contains(it.name)
|
val printBytecode = printBytecodeForTheseMethods.contains(it.name)
|
||||||
renderMethod(it, printBytecode).withMargin()
|
renderMethod(it, printBytecode, showLocalVariables).withMargin()
|
||||||
}
|
}
|
||||||
|
|
||||||
appendln().append("}")
|
appendln().append("}")
|
||||||
@@ -93,7 +98,7 @@ abstract class AbstractAsmLikeInstructionListingTest : CodegenTestCase() {
|
|||||||
append(field.name)
|
append(field.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun renderMethod(method: MethodNode, printBytecode: Boolean) = buildString {
|
private fun renderMethod(method: MethodNode, printBytecode: Boolean, showLocalVariables: Boolean) = buildString {
|
||||||
renderVisibilityModifiers(method.access)
|
renderVisibilityModifiers(method.access)
|
||||||
renderModalityModifiers(method.access)
|
renderModalityModifiers(method.access)
|
||||||
val (returnType, parameterTypes) = with(Type.getMethodType(method.desc)) { returnType to argumentTypes }
|
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) {
|
if (printBytecode && (method.access and ACC_ABSTRACT) == 0) {
|
||||||
appendln(" {")
|
appendln(" {")
|
||||||
append(renderBytecodeInstructions(method.instructions).trimEnd().withMargin())
|
append(renderBytecodeInstructions(method.instructions).trimEnd().withMargin())
|
||||||
|
|
||||||
|
if (showLocalVariables) {
|
||||||
|
val localVariableTable = buildLocalVariableTable(method)
|
||||||
|
if (localVariableTable.isNotEmpty()) {
|
||||||
|
appendln().appendln()
|
||||||
|
append(localVariableTable.withMargin())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
appendln().append("}")
|
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 {
|
private fun renderBytecodeInstructions(instructions: InsnList) = buildString {
|
||||||
val labelMappings = LabelMappings()
|
val labelMappings = LabelMappings()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user