Parcelable: Add CREATOR field (and other generated declarations) in light classes (KT-19300, KT-19853)

This commit is contained in:
Yan Zhulanow
2017-12-16 01:45:54 +09:00
parent 90dff281ba
commit 145ddf3b1f
29 changed files with 129 additions and 66 deletions
@@ -392,10 +392,12 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if (context.closure != null) if (context.closure != null)
genClosureFields(context.closure, v, typeMapper); genClosureFields(context.closure, v, typeMapper);
if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return;
for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) { for (ExpressionCodegenExtension extension : ExpressionCodegenExtension.Companion.getInstances(state.getProject())) {
extension.generateClassSyntheticParts(this); if (state.getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES
|| extension.getShouldGenerateClassSyntheticPartsInLightClassesMode()
) {
extension.generateClassSyntheticParts(this);
}
} }
} }
@@ -47,4 +47,7 @@ interface ExpressionCodegenExtension {
fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null fun applyFunction(receiver: StackValue, resolvedCall: ResolvedCall<*>, c: Context): StackValue? = null
fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {} fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {}
val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean
get() = false
} }
@@ -113,7 +113,7 @@ sealed class KtLightFieldImpl<D : PsiField>(
fun lazy( fun lazy(
dummyDelegate: PsiField, dummyDelegate: PsiField,
origin: LightMemberOriginForDeclaration, origin: LightMemberOriginForDeclaration?,
containingClass: KtLightClass, containingClass: KtLightClass,
computeRealDelegate: () -> PsiField computeRealDelegate: () -> PsiField
): KtLightField { ): KtLightField {
@@ -327,8 +327,11 @@ object IDELightClassContexts {
private val annotationsThatAffectCodegen = listOf( private val annotationsThatAffectCodegen = listOf(
"JvmField", "JvmOverloads", "JvmName", "JvmStatic", "JvmField", "JvmOverloads", "JvmName", "JvmStatic",
"Synchronized", "Transient", "Volatile", "Strictfp" "Synchronized", "Transient", "Volatile", "Strictfp"
).map { FqName("kotlin.jvm").child(Name.identifier(it)) } + FqName("kotlin.PublishedApi") + FqName("kotlin.Deprecated") + FqName("kotlin.internal.InlineOnly") ).map { FqName("kotlin.jvm").child(Name.identifier(it)) } +
FqName("kotlin.PublishedApi") +
FqName("kotlin.Deprecated") +
FqName("kotlin.internal.InlineOnly") +
FqName("kotlinx.android.parcel.Parcelize")
} }
class AdHocAnnotationResolver( class AdHocAnnotationResolver(
@@ -95,7 +95,7 @@ sealed class LazyLightClassDataHolder(
if (dummyDelegate == null) return KtLightFieldImpl.fromClsFields(clsDelegate, containingClass) if (dummyDelegate == null) return KtLightFieldImpl.fromClsFields(clsDelegate, containingClass)
return dummyDelegate!!.fields.map { dummyField -> return dummyDelegate!!.fields.map { dummyField ->
val fieldOrigin = KtLightFieldImpl.getOrigin(dummyField)!! val fieldOrigin = KtLightFieldImpl.getOrigin(dummyField)
val fieldName = dummyField.name!! val fieldName = dummyField.name!!
KtLightFieldImpl.lazy(dummyField, fieldOrigin, containingClass) { KtLightFieldImpl.lazy(dummyField, fieldOrigin, containingClass) {
@@ -33,10 +33,12 @@ abstract class AbstractKotlinLintTest : KotlinAndroidTestCase() {
AndroidLintInspectionBase.invalidateInspectionShortName2IssueMap() AndroidLintInspectionBase.invalidateInspectionShortName2IssueMap()
(myFixture as CodeInsightTestFixtureImpl).setVirtualFileFilter { false } // Allow access to tree elements. (myFixture as CodeInsightTestFixtureImpl).setVirtualFileFilter { false } // Allow access to tree elements.
ConfigLibraryUtil.configureKotlinRuntime(myModule) ConfigLibraryUtil.configureKotlinRuntime(myModule)
ConfigLibraryUtil.addLibrary(myModule, "androidExtensionsRuntime", "dist/kotlinc/lib", arrayOf("android-extensions-runtime.jar"))
} }
override fun tearDown() { override fun tearDown() {
ConfigLibraryUtil.unConfigureKotlinRuntime(myModule) ConfigLibraryUtil.unConfigureKotlinRuntime(myModule)
ConfigLibraryUtil.removeLibrary(myModule, "androidExtensionsRuntime")
super.tearDown() super.tearDown()
} }
+4
View File
@@ -3,6 +3,7 @@
@file:Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION") @file:Suppress("UsePropertyAccessSyntax", "UNUSED_VARIABLE", "unused", "UNUSED_PARAMETER", "DEPRECATION")
import android.os.Parcel import android.os.Parcel
import android.os.Parcelable import android.os.Parcelable
import kotlinx.android.parcel.Parcelize
class <error descr="This class implements `Parcelable` but does not provide a `CREATOR` field">MyParcelable1</error> : Parcelable { class <error descr="This class implements `Parcelable` but does not provide a `CREATOR` field">MyParcelable1</error> : Parcelable {
override fun describeContents() = 0 override fun describeContents() = 0
@@ -98,3 +99,6 @@ internal abstract class MyParcelable4 : Parcelable {
override fun describeContents() = 0 override fun describeContents() = 0
override fun writeToParcel(arg0: Parcel, arg1: Int) {} override fun writeToParcel(arg0: Parcel, arg1: Int) {}
} }
@Parcelize
class ParcelizeUser(val firstName: String, val lastName: String) : Parcelable
@@ -144,7 +144,7 @@ class ParcelableClinitClassBuilderInterceptorExtension : ClassBuilderInterceptor
iv.anew(creatorType) iv.anew(creatorType)
iv.dup() iv.dup()
iv.invokespecial(creatorName, "<init>", "()V", false) iv.invokespecial(creatorName, "<init>", "()V", false)
iv.putstatic(parcelableName, "CREATOR", creatorType.descriptor) iv.putstatic(parcelableName, "CREATOR", "Landroid/os/Parcelable\$Creator;")
} }
super.visitInsn(opcode) super.visitInsn(opcode)
@@ -1,3 +1,5 @@
package org.jetbrains.kotlin.android.parcel
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * Copyright 2010-2017 JetBrains s.r.o.
* *
@@ -14,10 +16,9 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.android.parcel
import kotlinx.android.parcel.TypeParceler import kotlinx.android.parcel.TypeParceler
import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod import org.jetbrains.kotlin.android.parcel.ParcelableResolveExtension.Companion.createMethod
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.*
import org.jetbrains.kotlin.android.parcel.serializers.* import org.jetbrains.kotlin.android.parcel.serializers.*
import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.* import org.jetbrains.kotlin.android.parcel.ParcelableSyntheticComponent.ComponentKind.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
@@ -57,10 +58,14 @@ import java.io.FileDescriptor
open class ParcelableCodegenExtension : ExpressionCodegenExtension { open class ParcelableCodegenExtension : ExpressionCodegenExtension {
private companion object { private companion object {
private val FILE_DESCRIPTOR_FQNAME = FqName(FileDescriptor::class.java.canonicalName) private val FILE_DESCRIPTOR_FQNAME = FqName(FileDescriptor::class.java.canonicalName)
private val CREATOR_NAME = Name.identifier("CREATOR")
} }
protected open fun isExperimental(element: KtElement) = true protected open fun isExperimental(element: KtElement) = true
override val shouldGenerateClassSyntheticPartsInLightClassesMode: Boolean
get() = true
override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) { override fun generateClassSyntheticParts(codegen: ImplementationBodyCodegen) {
val parcelableClass = codegen.descriptor val parcelableClass = codegen.descriptor
if (!parcelableClass.isParcelize) return if (!parcelableClass.isParcelize) return
@@ -68,24 +73,60 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
val sourceElement = (codegen.myClass as? KtClassOrObject) ?: return val sourceElement = (codegen.myClass as? KtClassOrObject) ?: return
if (!isExperimental(sourceElement)) return if (!isExperimental(sourceElement)) return
assert(parcelableClass.kind == ClassKind.CLASS || parcelableClass.kind == ClassKind.OBJECT) if (parcelableClass.kind != ClassKind.CLASS && parcelableClass.kind != ClassKind.OBJECT) return
val propertiesToSerialize = getPropertiesToSerialize(codegen, parcelableClass) val propertiesToSerialize = getPropertiesToSerialize(codegen, parcelableClass)
val parcelClassType = ParcelableResolveExtension.resolveParcelClassType(parcelableClass.module)
val parcelAsmType = codegen.typeMapper.mapType(parcelClassType)
val parcelerObject = parcelableClass.companionObjectDescriptor?.takeIf { val parcelerObject = parcelableClass.companionObjectDescriptor?.takeIf {
TypeUtils.getAllSupertypes(it.defaultType).any { it.isParceler } TypeUtils.getAllSupertypes(it.defaultType).any { it.isParceler }
} }
with (parcelableClass) { with (parcelableClass) {
writeDescribeContentsFunction(codegen, propertiesToSerialize) if (hasSyntheticDescribeContents()) {
writeWriteToParcel(codegen, propertiesToSerialize, parcelAsmType, parcelerObject) writeDescribeContentsFunction(codegen, propertiesToSerialize)
}
if (hasSyntheticWriteToParcel()) {
writeWriteToParcel(codegen, propertiesToSerialize, PARCEL_TYPE, parcelerObject)
}
if (!hasCreatorField()) {
writeCreatorAccessField(codegen)
}
} }
writeCreatorAccessField(codegen, parcelableClass) if (codegen.state.classBuilderMode != ClassBuilderMode.LIGHT_CLASSES) {
writeCreatorClass(codegen, parcelableClass, parcelClassType, parcelAsmType, parcelerObject, propertiesToSerialize) val parcelClassType = ParcelableResolveExtension.resolveParcelClassType(parcelableClass.module)
?: error("Can't resolve 'android.os.Parcel' class")
writeCreatorClass(codegen, parcelableClass, parcelClassType, PARCEL_TYPE, parcelerObject, propertiesToSerialize)
}
}
private fun ClassDescriptor.hasCreatorField(): Boolean {
val companionObject = companionObjectDescriptor ?: return false
if (companionObject.name == CREATOR_NAME) {
return true
}
return companionObject.unsubstitutedMemberScope
.getContributedVariables(CREATOR_NAME, NoLookupLocation.FROM_BACKEND)
.isNotEmpty()
}
private fun ClassDescriptor.hasSyntheticDescribeContents() = hasParcelizeSyntheticMethod(ComponentKind.DESCRIBE_CONTENTS)
private fun ClassDescriptor.hasSyntheticWriteToParcel() = hasParcelizeSyntheticMethod(ComponentKind.WRITE_TO_PARCEL)
private fun ClassDescriptor.hasParcelizeSyntheticMethod(componentKind: ParcelableSyntheticComponent.ComponentKind): Boolean {
val methodName = Name.identifier(componentKind.methodName)
val writeToParcelMethods = unsubstitutedMemberScope
.getContributedFunctions(methodName, NoLookupLocation.FROM_BACKEND)
.filter { it is ParcelableSyntheticComponent && it.componentKind == componentKind }
return writeToParcelMethods.size == 1
} }
private fun getCompanionClassType(containerAsmType: Type, parcelerObject: ClassDescriptor): Pair<Type, String> { private fun getCompanionClassType(containerAsmType: Type, parcelerObject: ClassDescriptor): Pair<Type, String> {
@@ -166,11 +207,10 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
codegen: ImplementationBodyCodegen, codegen: ImplementationBodyCodegen,
parcelableClass: ClassDescriptor parcelableClass: ClassDescriptor
): List<PropertyToSerialize> { ): List<PropertyToSerialize> {
val constructor = parcelableClass.constructors.first { it.isPrimary } val constructor = parcelableClass.constructors.firstOrNull { it.isPrimary } ?: return emptyList()
val propertiesToSerialize = constructor.valueParameters.map { param -> val propertiesToSerialize = constructor.valueParameters.mapNotNull { param ->
codegen.bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, param] codegen.bindingContext[BindingContext.VALUE_PARAMETER_AS_PROPERTY, param]
?: error("Value parameter should have 'val' or 'var' keyword")
} }
val classParcelers = getTypeParcelers(parcelableClass.annotations) val classParcelers = getTypeParcelers(parcelableClass.annotations)
@@ -228,12 +268,11 @@ open class ParcelableCodegenExtension : ExpressionCodegenExtension {
} }
} }
private fun writeCreatorAccessField(codegen: ImplementationBodyCodegen, parcelableClass: ClassDescriptor) { private fun writeCreatorAccessField(codegen: ImplementationBodyCodegen) {
val parcelableAsmType = codegen.typeMapper.mapType(parcelableClass.defaultType) val creatorType = Type.getObjectType("android/os/Parcelable\$Creator")
val creatorAsmType = Type.getObjectType(parcelableAsmType.internalName + "\$Creator")
codegen.v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_STATIC or ACC_PUBLIC or ACC_FINAL, "CREATOR", codegen.v.newField(JvmDeclarationOrigin.NO_ORIGIN, ACC_STATIC or ACC_PUBLIC or ACC_FINAL, "CREATOR",
creatorAsmType.descriptor, null, null) creatorType.descriptor, null, null)
} }
private fun writeCreatorClass( private fun writeCreatorClass(
@@ -33,14 +33,14 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.SimpleType import org.jetbrains.kotlin.types.SimpleType
open class ParcelableResolveExtension : SyntheticResolveExtension { open class ParcelableResolveExtension : SyntheticResolveExtension {
companion object { companion object {
fun resolveParcelClassType(module: ModuleDescriptor): SimpleType { fun resolveParcelClassType(module: ModuleDescriptor): SimpleType? {
return module.findClassAcrossModuleDependencies( return module.findClassAcrossModuleDependencies(ClassId.topLevel(FqName("android.os.Parcel")))?.defaultType
ClassId.topLevel(FqName("android.os.Parcel")))?.defaultType ?: error("Can't resolve 'android.os.Parcel' class")
} }
fun createMethod( fun createMethod(
@@ -103,7 +103,7 @@ open class ParcelableResolveExtension : SyntheticResolveExtension {
&& result.none { it.isWriteToParcel() } && result.none { it.isWriteToParcel() }
) { ) {
val builtIns = clazz.builtIns val builtIns = clazz.builtIns
val parcelClassType = resolveParcelClassType(clazz.module) val parcelClassType = resolveParcelClassType(clazz.module) ?: ErrorUtils.createErrorType("Unresolved 'Parcel' type")
result += createMethod(clazz, WRITE_TO_PARCEL, builtIns.unitType, "parcel" to parcelClassType, "flags" to builtIns.intType) result += createMethod(clazz, WRITE_TO_PARCEL, builtIns.unitType, "parcel" to parcelClassType, "flags" to builtIns.intType)
} }
} }
@@ -120,12 +120,11 @@ open class ParcelableResolveExtension : SyntheticResolveExtension {
internal fun SimpleFunctionDescriptor.isWriteToParcel(): Boolean { internal fun SimpleFunctionDescriptor.isWriteToParcel(): Boolean {
return typeParameters.isEmpty() return typeParameters.isEmpty()
&& valueParameters.size == 2 && valueParameters.size == 2
&& valueParameters[0].type.isParcel() // Unfortunately, we can't check the first parameter cause it can be unresolved
&& KotlinBuiltIns.isInt(valueParameters[1].type) && KotlinBuiltIns.isInt(valueParameters[1].type)
&& returnType?.let { KotlinBuiltIns.isUnit(it) } == true
} }
private fun KotlinType.isParcel() = constructor.declarationDescriptor?.fqNameSafe == ANDROID_PARCEL_CLASS_FQNAME
interface ParcelableSyntheticComponent { interface ParcelableSyntheticComponent {
val componentKind: ComponentKind val componentKind: ComponentKind
@@ -534,7 +534,7 @@ internal class EfficientParcelableParcelSerializer(override val asmType: Type, p
override fun readValue(v: InstructionAdapter) { override fun readValue(v: InstructionAdapter) {
// -> parcel // -> parcel
v.getstatic(asmType.internalName, "CREATOR", creatorAsmType.descriptor) // -> parcel, creator v.getstatic(asmType.internalName, "CREATOR", "Landroid/os/Parcelable\$Creator;") // -> parcel, creator
v.swap() // -> creator, parcel v.swap() // -> creator, parcel
v.invokeinterface("android/os/Parcelable\$Creator", "createFromParcel", "(Landroid/os/Parcel;)Ljava/lang/Object;") v.invokeinterface("android/os/Parcelable\$Creator", "createFromParcel", "(Landroid/os/Parcel;)Ljava/lang/Object;")
v.castIfNeeded(asmType) v.castIfNeeded(asmType)
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.android.synthetic.descriptors.ContainerOptionsProxy
import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor import org.jetbrains.kotlin.android.synthetic.descriptors.AndroidSyntheticPackageFragmentDescriptor
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticFunction
import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty import org.jetbrains.kotlin.android.synthetic.res.AndroidSyntheticProperty
import org.jetbrains.kotlin.codegen.ClassBuilder import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.FunctionCodegen
import org.jetbrains.kotlin.codegen.ImplementationBodyCodegen
import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -50,7 +50,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.os.IBinder binder private final android.os.IBinder binder
@@ -7,7 +7,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final int age private final int age
@@ -22,7 +22,7 @@ public final class test/Foo$Creator : java/lang/Object, android/os/Parcelable$Cr
} }
public final class test/Foo : java/lang/Object, android/os/Parcelable { public final class test/Foo : java/lang/Object, android/os/Parcelable {
public final static test.Foo$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.accounts.Account kp private final android.accounts.Account kp
@@ -30,7 +30,7 @@ public final class test/Foo : java/lang/Object, android/os/Parcelable {
NEW NEW
DUP DUP
INVOKESPECIAL (test/Foo$Creator, <init>, ()V) INVOKESPECIAL (test/Foo$Creator, <init>, ()V)
PUTSTATIC (CREATOR, Ltest/Foo$Creator;) PUTSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
RETURN RETURN
} }
@@ -112,7 +112,7 @@ public final class test/Foo$Creator : java/lang/Object, android/os/Parcelable$Cr
NEW NEW
DUP DUP
ALOAD (1) ALOAD (1)
GETSTATIC (CREATOR, Lk/KotlinParcelable$Creator;) GETSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
SWAP SWAP
INVOKEINTERFACE (android/os/Parcelable$Creator, createFromParcel, (Landroid/os/Parcel;)Ljava/lang/Object;) INVOKEINTERFACE (android/os/Parcelable$Creator, createFromParcel, (Landroid/os/Parcel;)Ljava/lang/Object;)
CHECKCAST CHECKCAST
@@ -125,7 +125,7 @@ public final class test/Foo$Creator : java/lang/Object, android/os/Parcelable$Cr
} }
public final class test/Foo : java/lang/Object, android/os/Parcelable { public final class test/Foo : java/lang/Object, android/os/Parcelable {
public final static test.Foo$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final k.KotlinParcelable kp private final k.KotlinParcelable kp
@@ -133,7 +133,7 @@ public final class test/Foo : java/lang/Object, android/os/Parcelable {
NEW NEW
DUP DUP
INVOKESPECIAL (test/Foo$Creator, <init>, ()V) INVOKESPECIAL (test/Foo$Creator, <init>, ()V)
PUTSTATIC (CREATOR, Ltest/Foo$Creator;) PUTSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
RETURN RETURN
} }
@@ -58,7 +58,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
public final static User$Companion Companion public final static User$Companion Companion
@@ -47,7 +47,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
public final static User$Companion Companion public final static User$Companion Companion
@@ -19,7 +19,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : AbstractUser { public final class User : AbstractUser {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final int age private final int age
@@ -19,7 +19,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
public final static User$Companion Companion public final static User$Companion Companion
@@ -42,7 +42,7 @@ public final class User : java/lang/Object, android/os/Parcelable {
NEW NEW
DUP DUP
INVOKESPECIAL (User$Creator, <init>, ()V) INVOKESPECIAL (User$Creator, <init>, ()V)
PUTSTATIC (CREATOR, LUser$Creator;) PUTSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
RETURN RETURN
} }
@@ -7,7 +7,7 @@ public final class Test$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class Test : java/lang/Object { public final class Test : java/lang/Object {
public final static Test$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final java.util.List names private final java.util.List names
@@ -7,7 +7,7 @@ public final class TestNotNull$Creator : java/lang/Object, android/os/Parcelable
} }
public final class TestNotNull : java/lang/Object { public final class TestNotNull : java/lang/Object {
public final static TestNotNull$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.util.Size a private final android.util.Size a
@@ -42,7 +42,7 @@ public final class TestNullable$Creator : java/lang/Object, android/os/Parcelabl
} }
public final class TestNullable : java/lang/Object { public final class TestNullable : java/lang/Object {
public final static TestNullable$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.util.Size a private final android.util.Size a
@@ -1,6 +1,25 @@
// CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit> // CURIOUS_ABOUT writeToParcel, createFromParcel, <clinit>
// WITH_RUNTIME // WITH_RUNTIME
//FILE: test/JavaClass.java
package test;
class JavaClass {
void test() {
// Here we test access to CREATOR
Object o = Foo.CREATOR;
}
}
//FILE: android/os/Parcelable.java
package android.os;
public interface Parcelable {
public static interface Creator<T> {}
}
//FILE: test.kt
package test package test
import kotlinx.android.parcel.* import kotlinx.android.parcel.*
@@ -21,7 +21,7 @@ public final class test/Foo$Creator : java/lang/Object, android/os/Parcelable$Cr
} }
public final class test/Foo : java/lang/Object, android/os/Parcelable { public final class test/Foo : java/lang/Object, android/os/Parcelable {
public final static test.Foo$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.os.Parcelable parcelable private final android.os.Parcelable parcelable
@@ -29,7 +29,7 @@ public final class test/Foo : java/lang/Object, android/os/Parcelable {
NEW NEW
DUP DUP
INVOKESPECIAL (test/Foo$Creator, <init>, ()V) INVOKESPECIAL (test/Foo$Creator, <init>, ()V)
PUTSTATIC (CREATOR, Ltest/Foo$Creator;) PUTSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
RETURN RETURN
} }
@@ -35,7 +35,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final SerializableSimple notNull private final SerializableSimple notNull
@@ -45,7 +45,7 @@ public final class User : java/lang/Object, android/os/Parcelable {
NEW NEW
DUP DUP
INVOKESPECIAL (User$Creator, <init>, ()V) INVOKESPECIAL (User$Creator, <init>, ()V)
PUTSTATIC (CREATOR, LUser$Creator;) PUTSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
RETURN RETURN
} }
@@ -36,7 +36,7 @@ public final class User$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class User : java/lang/Object, android/os/Parcelable { public final class User : java/lang/Object, android/os/Parcelable {
public final static User$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final int age private final int age
@@ -50,7 +50,7 @@ public final class User : java/lang/Object, android/os/Parcelable {
NEW NEW
DUP DUP
INVOKESPECIAL (User$Creator, <init>, ()V) INVOKESPECIAL (User$Creator, <init>, ()V)
PUTSTATIC (CREATOR, LUser$Creator;) PUTSTATIC (CREATOR, Landroid/os/Parcelable$Creator;)
RETURN RETURN
} }
@@ -7,7 +7,7 @@ public final class Test$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class Test : java/lang/Object { public final class Test : java/lang/Object {
public final static Test$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final java.util.List names private final java.util.List names
@@ -29,7 +29,7 @@ public final class Test$Creator : java/lang/Object, android/os/Parcelable$Creato
} }
public final class Test : java/lang/Object, android/os/Parcelable { public final class Test : java/lang/Object, android/os/Parcelable {
public final static Test$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.util.Size nullable private final android.util.Size nullable
@@ -119,7 +119,7 @@ public final class TestF$Creator : java/lang/Object, android/os/Parcelable$Creat
} }
public final class TestF : java/lang/Object, android/os/Parcelable { public final class TestF : java/lang/Object, android/os/Parcelable {
public final static TestF$Creator CREATOR public final static android.os.Parcelable$Creator CREATOR
private final android.util.SizeF nullable private final android.util.SizeF nullable
@@ -95,11 +95,6 @@ public class ParcelDetector extends Detector implements Detector.UastScanner {
return; return;
} }
// Do not report errors on our Android Extensions-improved Parcelables
if (declaration.findAnnotation(Parcelize.class.getName()) != null) {
return;
}
PsiField field = declaration.findFieldByName("CREATOR", false); PsiField field = declaration.findFieldByName("CREATOR", false);
if (field == null) { if (field == null) {
Location location = context.getUastNameLocation(declaration); Location location = context.getUastNameLocation(declaration);