@@ -419,31 +419,35 @@ open class KotlinUsesExtractor(
419419
420420 // `typeArgs` can be null to describe a raw generic type.
421421 // For non-generic types it will be zero-length list.
422- fun addClassLabel (cBeforeReplacement : IrClass , argsIncludingOuterClasses : List <IrTypeArgument >? , inReceiverContext : Boolean = false): TypeResult <DbClassorinterface > {
422+ private fun addClassLabel (cBeforeReplacement : IrClass , argsIncludingOuterClasses : List <IrTypeArgument >? , inReceiverContext : Boolean = false): TypeResult <DbClassorinterface > {
423423 val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement)
424- val classLabelResult = getClassLabel(c, argsIncludingOuterClasses)
424+ val p = tryReplaceParcelizeRawType(c)
425+ val replacedClass = p?.first ? : c
426+ val replacedArgsIncludingOuterClasses = p?.second ? : argsIncludingOuterClasses
427+
428+ val classLabelResult = getClassLabel(replacedClass, replacedArgsIncludingOuterClasses)
425429
426430 var instanceSeenBefore = true
427431
428- val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel, {
432+ val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel) {
429433 instanceSeenBefore = false
430434
431- extractClassLaterIfExternal(c )
432- })
435+ extractClassLaterIfExternal(replacedClass )
436+ }
433437
434- if (argsIncludingOuterClasses == null || argsIncludingOuterClasses .isNotEmpty()) {
438+ if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses .isNotEmpty()) {
435439 // If this is a generic type instantiation or a raw type then it has no
436440 // source entity, so we need to extract it here
437- val extractorWithCSource by lazy { this .withFileOfClass(c ) }
441+ val extractorWithCSource by lazy { this .withFileOfClass(replacedClass ) }
438442
439443 if (! instanceSeenBefore) {
440- extractorWithCSource.extractClassInstance(c, argsIncludingOuterClasses )
444+ extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses )
441445 }
442446
443447 if (inReceiverContext && tw.lm.genericSpecialisationsExtracted.add(classLabelResult.classLabel)) {
444- val supertypeMode = if (argsIncludingOuterClasses == null ) ExtractSupertypesMode .Raw else ExtractSupertypesMode .Specialised (argsIncludingOuterClasses )
445- extractorWithCSource.extractClassSupertypes(c , classLabel, supertypeMode, true )
446- extractorWithCSource.extractNonPrivateMemberPrototypes(c, argsIncludingOuterClasses , classLabel)
448+ val supertypeMode = if (replacedArgsIncludingOuterClasses == null ) ExtractSupertypesMode .Raw else ExtractSupertypesMode .Specialised (replacedArgsIncludingOuterClasses )
449+ extractorWithCSource.extractClassSupertypes(replacedClass , classLabel, supertypeMode, true )
450+ extractorWithCSource.extractNonPrivateMemberPrototypes(replacedClass, replacedArgsIncludingOuterClasses , classLabel)
447451 }
448452 }
449453
@@ -453,6 +457,35 @@ open class KotlinUsesExtractor(
453457 classLabelResult.shortName)
454458 }
455459
460+ private fun tryReplaceParcelizeRawType (c : IrClass ): Pair <IrClass , List <IrTypeArgument >? >? {
461+ if (c.superTypes.isNotEmpty() ||
462+ c.origin != IrDeclarationOrigin .DEFINED ||
463+ c.hasEqualFqName(FqName (" java.lang.Object" ))) {
464+ return null
465+ }
466+
467+ fun tryGetPair (arity : Int ): Pair <IrClass , List <IrTypeArgument >? >? {
468+ val replaced = pluginContext.referenceClass(c.fqNameWhenAvailable!! )?.owner ? : return null
469+ return Pair (replaced, List (arity) { makeTypeProjection(pluginContext.irBuiltIns.anyNType, Variance .INVARIANT ) })
470+ }
471+
472+ // The list of types handled here match https://github.com/JetBrains/kotlin/blob/d7c7d1efd2c0983c13b175e9e4b1cda979521159/plugins/parcelize/parcelize-compiler/src/org/jetbrains/kotlin/parcelize/ir/AndroidSymbols.kt
473+ // Specifically, types are added for generic types created in AndroidSymbols.kt.
474+ // This replacement is from a raw type to its matching parameterized type with `Object` type arguments.
475+ return when (c.fqNameWhenAvailable?.asString()) {
476+ " java.util.ArrayList" -> tryGetPair(1 )
477+ " java.util.LinkedHashMap" -> tryGetPair(2 )
478+ " java.util.LinkedHashSet" -> tryGetPair(1 )
479+ " java.util.List" -> tryGetPair(1 )
480+ " java.util.TreeMap" -> tryGetPair(2 )
481+ " java.util.TreeSet" -> tryGetPair(1 )
482+
483+ " java.lang.Class" -> tryGetPair(1 )
484+
485+ else -> null
486+ }
487+ }
488+
456489 fun useAnonymousClass (c : IrClass ) =
457490 tw.lm.anonymousTypeMapping.getOrPut(c) {
458491 TypeResults (
@@ -721,7 +754,15 @@ open class KotlinUsesExtractor(
721754 } else {
722755 extractFileClass(dp)
723756 }
724- is IrClass -> if (classTypeArguments != null && ! dp.isAnonymousObject) useClassInstance(dp, classTypeArguments, inReceiverContext).typeResult.id else useClassSource(dp)
757+ is IrClass ->
758+ if (classTypeArguments != null && ! dp.isAnonymousObject) {
759+ useClassInstance(dp, classTypeArguments, inReceiverContext).typeResult.id
760+ } else {
761+ // `inReceiverContext == false` is used unless we have identified that we're dealing with a raw type
762+ // produced by the Parcelize plugin. In that case we're using the original `inReceiverContext`. Note
763+ // that the type in this case is being replaced later in `addClassLabel` to a non-raw type.
764+ useClassSource(dp, inReceiverContext && tryReplaceParcelizeRawType(dp) != null )
765+ }
725766 is IrFunction -> useFunction(dp)
726767 is IrExternalPackageFragment -> {
727768 // TODO
@@ -1281,13 +1322,13 @@ open class KotlinUsesExtractor(
12811322 unquotedLabel.shortName)
12821323 }
12831324
1284- fun useClassSource (c : IrClass ): Label <out DbClassorinterface > {
1325+ fun useClassSource (c : IrClass , inReceiverContext : Boolean = false ): Label <out DbClassorinterface > {
12851326 if (c.isAnonymousObject) {
12861327 return useAnonymousClass(c).javaResult.id.cast<DbClass >()
12871328 }
12881329
12891330 // For source classes, the label doesn't include and type arguments
1290- val classTypeResult = addClassLabel(c, listOf ())
1331+ val classTypeResult = addClassLabel(c, listOf (), inReceiverContext )
12911332 return classTypeResult.id
12921333 }
12931334
0 commit comments