diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtDelegatedSuperTypeEntry.java b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtDelegatedSuperTypeEntry.java index b52122255da..ec27c591011 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/KtDelegatedSuperTypeEntry.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/KtDelegatedSuperTypeEntry.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi; import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub; import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes; @@ -40,4 +41,8 @@ public class KtDelegatedSuperTypeEntry extends KtSuperTypeListEntry { public KtExpression getDelegateExpression() { return findChildByClass(KtExpression.class); } + + public ASTNode getByKeywordNode() { + return getNode().findChildByType(KtTokens.BY_KEYWORD); + } } 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 f1d0f909f53..341e39716fa 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 @@ -188,7 +188,7 @@ class ParcelableCodegenExtension : ExpressionCodegenExtension { val asmType = codegen.typeMapper.mapType(type) asmConstructorParameters.append(asmType.descriptor) - val serializer = ParcelSerializer.get(type, asmType, codegen.typeMapper, forceBoxed = false, strict = false) + val serializer = ParcelSerializer.get(type, asmType, codegen.typeMapper) v.load(1, parcelAsmType) serializer.readValue(v) } @@ -276,12 +276,12 @@ class ParcelableCodegenExtension : ExpressionCodegenExtension { if (parcelerObject != null) { val newArrayMethod = parcelerObject.unsubstitutedMemberScope .getContributedFunctions(Name.identifier("newArray"), NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS) - .filter { + .firstOrNull { it.typeParameters.isEmpty() && it.kind == CallableMemberDescriptor.Kind.DECLARATION && (it.valueParameters.size == 1 && KotlinBuiltIns.isInt(it.valueParameters[0].type)) && !((it.containingDeclaration as? ClassDescriptor)?.defaultType?.isParceler() ?: true) - }.firstOrNull() + } if (newArrayMethod != null) { val containerAsmType = codegen.typeMapper.mapType(parcelableClass.defaultType) diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt index 5a5d56cd6ff..8f32793433f 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/ParcelableDeclarationChecker.kt @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.android.parcel import org.jetbrains.kotlin.android.parcel.serializers.ParcelSerializer +import org.jetbrains.kotlin.android.parcel.serializers.isParcelable import org.jetbrains.kotlin.android.synthetic.diagnostic.ErrorsAndroid import org.jetbrains.kotlin.codegen.ClassBuilderMode import org.jetbrains.kotlin.codegen.state.IncompatibleClassTracker @@ -65,7 +66,7 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker { val containingClass = descriptor.containingDeclaration as? ClassDescriptor val ktProperty = declaration as? KtProperty if (containingClass != null && ktProperty != null) { - checkParcelableClassProperty(descriptor, containingClass, ktProperty, diagnosticHolder) + checkParcelableClassProperty(descriptor, containingClass, ktProperty, diagnosticHolder, bindingContext) } } } @@ -79,9 +80,9 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker { ) { if (!containingClass.isMagicParcelable) return - if (method.isWriteToParcel()) { + if (method.isWriteToParcel() && declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) { val reportElement = declaration.modifierList?.getModifier(KtTokens.OVERRIDE_KEYWORD) ?: declaration.nameIdentifier ?: declaration - diagnosticHolder.report(ErrorsAndroid.OVERRIDING_WRITE_TO_PARCEL_IS_FORBIDDEN.on(reportElement)) + diagnosticHolder.report(ErrorsAndroid.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED.on(reportElement)) } } @@ -89,22 +90,21 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker { property: PropertyDescriptor, containingClass: ClassDescriptor, declaration: KtProperty, - diagnosticHolder: DiagnosticSink + diagnosticHolder: DiagnosticSink, + bindingContext: BindingContext ) { - if (containingClass.isMagicParcelable) { - // Do not report on calculated properties - if (declaration.getter?.hasBody() == true) return - - if (!property.annotations.hasAnnotation(TRANSIENT_FQNAME)) { - diagnosticHolder.report(ErrorsAndroid.PROPERTY_WONT_BE_SERIALIZED.on(declaration.nameIdentifier ?: declaration)) - } + if (containingClass.isMagicParcelable + && (declaration.hasDelegate() || bindingContext[BindingContext.BACKING_FIELD_REQUIRED, property] == true) + && !property.annotations.hasAnnotation(TRANSIENT_FQNAME) + ) { + diagnosticHolder.report(ErrorsAndroid.PROPERTY_WONT_BE_SERIALIZED.on(declaration.nameIdentifier ?: declaration)) } // @JvmName is not applicable to property so we can check just the descriptor name if (property.name.asString() == "CREATOR" && property.findJvmFieldAnnotation() != null && containingClass.isCompanionObject) { val outerClass = containingClass.containingDeclaration as? ClassDescriptor if (outerClass != null && outerClass.isMagicParcelable) { - diagnosticHolder.report(ErrorsAndroid.CREATOR_DEFINITION_IS_FORBIDDEN.on(declaration.nameIdentifier ?: declaration)) + diagnosticHolder.report(ErrorsAndroid.CREATOR_DEFINITION_IS_NOT_ALLOWED.on(declaration.nameIdentifier ?: declaration)) } } } @@ -117,12 +117,18 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker { ) { if (!descriptor.isMagicParcelable) return - if (declaration !is KtClass || (declaration.isAnnotation() || declaration.isInterface() || declaration.isEnum())) { + if (declaration !is KtClass || (declaration.isAnnotation() || declaration.isInterface())) { val reportElement = (declaration as? KtClassOrObject)?.nameIdentifier ?: declaration diagnosticHolder.report(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS.on(reportElement)) return } + if (declaration.isEnum()) { + val reportElement = (declaration as? KtClass)?.nameIdentifier ?: declaration + diagnosticHolder.report(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS.on(reportElement)) + return + } + val sealedOrAbstract = declaration.modifierList?.let { it.getModifier(KtTokens.ABSTRACT_KEYWORD) ?: it.getModifier(KtTokens.SEALED_KEYWORD) } if (sealedOrAbstract != null) { diagnosticHolder.report(ErrorsAndroid.PARCELABLE_SHOULD_BE_INSTANTIABLE.on(sealedOrAbstract)) @@ -142,9 +148,21 @@ class ParcelableDeclarationChecker : SimpleDeclarationChecker { diagnosticHolder.report(ErrorsAndroid.NO_PARCELABLE_SUPERTYPE.on(declaration.nameIdentifier ?: declaration)) } + for (supertypeEntry in declaration.superTypeListEntries) { + supertypeEntry as? KtDelegatedSuperTypeEntry ?: continue + val delegateExpression = supertypeEntry.delegateExpression ?: continue + val type = bindingContext[BindingContext.TYPE, supertypeEntry.typeReference] ?: continue + if (type.isParcelable()) { + val reportElement = supertypeEntry.byKeywordNode?.psi ?: delegateExpression + diagnosticHolder.report(ErrorsAndroid.PARCELABLE_DELEGATE_IS_NOT_ALLOWED.on(reportElement)) + } + } + val primaryConstructor = declaration.primaryConstructor if (primaryConstructor == null && declaration.secondaryConstructors.isNotEmpty()) { diagnosticHolder.report(ErrorsAndroid.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR.on(declaration.nameIdentifier ?: declaration)) + } else if (primaryConstructor != null && primaryConstructor.valueParameters.isEmpty()) { + diagnosticHolder.report(ErrorsAndroid.PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY.on(declaration.nameIdentifier ?: declaration)) } val typeMapper = KotlinTypeMapper( diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt index b09f00778f7..e3026c87f93 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/parcel/serializers/ParcelSerializer.kt @@ -225,7 +225,6 @@ interface ParcelSerializer { private fun KotlinType.isException() = matchesFqNameWithSupertypes("java.lang.Exception") private fun KotlinType.isIBinder() = matchesFqNameWithSupertypes("android.os.IBinder") private fun KotlinType.isIInterface() = matchesFqNameWithSupertypes("android.os.IInterface") - private fun KotlinType.isParcelable() = matchesFqNameWithSupertypes("android.os.Parcelable") private fun KotlinType.isCharSequence() = matchesFqName("kotlin.CharSequence") || matchesFqName("java.lang.CharSequence") private fun KotlinType.isNamedObject(): Boolean { @@ -253,17 +252,19 @@ interface ParcelSerializer { "Ljava/lang/Double;" -> true else -> false } - - private fun KotlinType.matchesFqNameWithSupertypes(fqName: String): Boolean { - if (this.matchesFqName(fqName)) { - return true - } - - return TypeUtils.getAllSupertypes(this).any { it.matchesFqName(fqName) } - } - - private fun KotlinType.matchesFqName(fqName: String): Boolean { - return this.constructor.declarationDescriptor?.fqNameSafe?.asString() == fqName - } } +} + +internal fun KotlinType.isParcelable() = matchesFqNameWithSupertypes("android.os.Parcelable") + +private fun KotlinType.matchesFqName(fqName: String): Boolean { + return this.constructor.declarationDescriptor?.fqNameSafe?.asString() == fqName +} + +private fun KotlinType.matchesFqNameWithSupertypes(fqName: String): Boolean { + if (this.matchesFqName(fqName)) { + return true + } + + return TypeUtils.getAllSupertypes(this).any { it.matchesFqName(fqName) } } \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt index 57ab5f1639c..32e3b2c09a8 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/DefaultErrorMessagesAndroid.kt @@ -43,6 +43,12 @@ class DefaultErrorMessagesAndroid : DefaultErrorMessages.Extension { MAP.put(ErrorsAndroid.PARCELABLE_SHOULD_BE_CLASS, "'Parcelable' should be a class") + MAP.put(ErrorsAndroid.PARCELABLE_DELEGATE_IS_NOT_ALLOWED, + "Delegating 'Parcelable' is now allowed") + + MAP.put(ErrorsAndroid.PARCELABLE_SHOULD_NOT_BE_ENUM_CLASS, + "'Parcelable' should not be a 'enum class'") + MAP.put(ErrorsAndroid.PARCELABLE_SHOULD_BE_INSTANTIABLE, "'Parcelable' should not be a 'sealed' or 'abstract' class") @@ -58,20 +64,23 @@ class DefaultErrorMessagesAndroid : DefaultErrorMessages.Extension { MAP.put(ErrorsAndroid.PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR, "'Parcelable' should have a primary constructor") + MAP.put(ErrorsAndroid.PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY, + "The primary constructor is empty, no data will be serialized to 'Parcel'") + MAP.put(ErrorsAndroid.PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR, "'Parcelable' constructor parameter should be 'val' or 'var'") MAP.put(ErrorsAndroid.PROPERTY_WONT_BE_SERIALIZED, "Property would not be serialized into a 'Parcel'. Add '@Transient' annotation to it") - MAP.put(ErrorsAndroid.OVERRIDING_WRITE_TO_PARCEL_IS_FORBIDDEN, - "Overriding 'writeToParcel' is forbidden. Use 'Parceler' companion object instead.") + MAP.put(ErrorsAndroid.OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED, + "Overriding 'writeToParcel' is not allowed. Use 'Parceler' companion object instead.") - MAP.put(ErrorsAndroid.CREATOR_DEFINITION_IS_FORBIDDEN, - "'CREATOR' definition is forbidden. Use 'Parceler' companion object instead.") + MAP.put(ErrorsAndroid.CREATOR_DEFINITION_IS_NOT_ALLOWED, + "'CREATOR' definition is not allowed. Use 'Parceler' companion object instead.") MAP.put(ErrorsAndroid.PARCELABLE_TYPE_NOT_SUPPORTED, - "Type is not supported by 'Parcelable'. " + + "Type is not directly supported by 'MagicParcelable'. " + "Annotate the parameter type with '@RawValue' if you want it to be serialized using 'writeValue()'") } } diff --git a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/ErrorsAndroid.java b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/ErrorsAndroid.java index ab8b34c2362..efbff9a9d11 100644 --- a/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/ErrorsAndroid.java +++ b/plugins/android-extensions/android-extensions-compiler/src/org/jetbrains/kotlin/android/synthetic/diagnostic/ErrorsAndroid.java @@ -32,15 +32,18 @@ public interface ErrorsAndroid { DiagnosticFactory0 UNSAFE_CALL_ON_PARTIALLY_DEFINED_RESOURCE = DiagnosticFactory0.create(WARNING); DiagnosticFactory0 PARCELABLE_SHOULD_BE_CLASS = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 PARCELABLE_DELEGATE_IS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 PARCELABLE_SHOULD_NOT_BE_ENUM_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PARCELABLE_SHOULD_BE_INSTANTIABLE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PARCELABLE_CANT_BE_INNER_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PARCELABLE_CANT_BE_LOCAL_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NO_PARCELABLE_SUPERTYPE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PARCELABLE_SHOULD_HAVE_PRIMARY_CONSTRUCTOR = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 PARCELABLE_PRIMARY_CONSTRUCTOR_IS_EMPTY = DiagnosticFactory0.create(WARNING); DiagnosticFactory0 PARCELABLE_CONSTRUCTOR_PARAMETER_SHOULD_BE_VAL_OR_VAR = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_WONT_BE_SERIALIZED = DiagnosticFactory0.create(WARNING); - DiagnosticFactory0 OVERRIDING_WRITE_TO_PARCEL_IS_FORBIDDEN = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 CREATOR_DEFINITION_IS_FORBIDDEN = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 OVERRIDING_WRITE_TO_PARCEL_IS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 CREATOR_DEFINITION_IS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PARCELABLE_TYPE_NOT_SUPPORTED = DiagnosticFactory0.create(ERROR); @SuppressWarnings("UnusedDeclaration") diff --git a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customCreator.kt b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customCreator.kt index 7c1278337ed..70a85f715f7 100644 --- a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customCreator.kt +++ b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customCreator.kt @@ -8,7 +8,7 @@ import android.os.Parcel class A(val a: String) : Parcelable { companion object { @JvmField - val CREATOR = object : Parcelable.Creator { + val CREATOR = object : Parcelable.Creator { override fun createFromParcel(source: Parcel): A = A("") override fun newArray(size: Int) = arrayOfNulls(size) } diff --git a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customWriteToParcel.kt b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customWriteToParcel.kt index 9be5f4029f9..8eda68549e5 100644 --- a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customWriteToParcel.kt +++ b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/customWriteToParcel.kt @@ -6,16 +6,16 @@ import android.os.Parcel @MagicParcel class A(val a: String) : Parcelable { - override fun writeToParcel(p: Parcel?, flags: Int) {} + override fun writeToParcel(p: Parcel?, flags: Int) {} override fun describeContents() = 0 } @MagicParcel class B(val a: String) : Parcelable { - override fun writeToParcel(p: Parcel?, flags: Int) {} + override fun writeToParcel(p: Parcel?, flags: Int) {} } @MagicParcel class C(val a: String) : Parcelable { - override fun writeToParcel(p: Parcel, flags: Int) {} + override fun writeToParcel(p: Parcel, flags: Int) {} } \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/delegate.kt b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/delegate.kt new file mode 100644 index 00000000000..0722a4661a6 --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/delegate.kt @@ -0,0 +1,13 @@ +package test + +import kotlinx.android.parcel.MagicParcel +import android.os.Parcelable +import android.os.Parcel + +open class Delegate : Parcelable { + override fun writeToParcel(dest: Parcel?, flags: Int) {} + override fun describeContents() = 0 +} + +@MagicParcel +class Test : Parcelable by Delegate() \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/emptyPrimaryConstructor.kt b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/emptyPrimaryConstructor.kt new file mode 100644 index 00000000000..c181fa9e501 --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/emptyPrimaryConstructor.kt @@ -0,0 +1,10 @@ +package test + +import kotlinx.android.parcel.MagicParcel +import android.os.Parcelable + +@MagicParcel +class User : Parcelable + +@MagicParcel +class User2() : Parcelable \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/unsupportedType.kt b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/unsupportedType.kt new file mode 100644 index 00000000000..61fd4429480 --- /dev/null +++ b/plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/unsupportedType.kt @@ -0,0 +1,17 @@ +package test + +import kotlinx.android.parcel.MagicParcel +import kotlinx.android.parcel.RawValue +import android.os.Parcelable + +@MagicParcel +class User( + val a: String, + val b: Any, + val c: Any?, + val d: Map, + val e: @RawValue Any?, + val f: @RawValue Map, + val g: Map, + val h: Map<@RawValue Any, List<@RawValue Any>> +) : Parcelable \ No newline at end of file diff --git a/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/ParcelCheckerTestGenerated.java b/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/ParcelCheckerTestGenerated.java index 7959229c54b..7d1ba009588 100644 --- a/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/ParcelCheckerTestGenerated.java +++ b/plugins/android-extensions/android-extensions-idea/tests/org/jetbrains/kotlin/android/ParcelCheckerTestGenerated.java @@ -54,6 +54,18 @@ public class ParcelCheckerTestGenerated extends AbstractParcelCheckerTest { doTest(fileName); } + @TestMetadata("delegate.kt") + public void testDelegate() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/delegate.kt"); + doTest(fileName); + } + + @TestMetadata("emptyPrimaryConstructor.kt") + public void testEmptyPrimaryConstructor() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/emptyPrimaryConstructor.kt"); + doTest(fileName); + } + @TestMetadata("modality.kt") public void testModality() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/modality.kt"); @@ -78,6 +90,12 @@ public class ParcelCheckerTestGenerated extends AbstractParcelCheckerTest { doTest(fileName); } + @TestMetadata("unsupportedType.kt") + public void testUnsupportedType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/unsupportedType.kt"); + doTest(fileName); + } + @TestMetadata("withoutParcelableSupertype.kt") public void testWithoutParcelableSupertype() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("plugins/android-extensions/android-extensions-idea/testData/android/parcel/checker/withoutParcelableSupertype.kt");