@@ -417,42 +417,83 @@ open class KotlinUsesExtractor(
417417 } ? : f
418418 }
419419
420+ private fun tryReplaceType (cBeforeReplacement : IrClass , argsIncludingOuterClassesBeforeReplacement : List <IrTypeArgument >? ): Pair <IrClass , List <IrTypeArgument >? > {
421+ val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement)
422+ val p = tryReplaceParcelizeRawType(c)
423+ return Pair (
424+ p?.first ? : c,
425+ p?.second ? : argsIncludingOuterClassesBeforeReplacement
426+ )
427+ }
428+
420429 // `typeArgs` can be null to describe a raw generic type.
421430 // For non-generic types it will be zero-length list.
422- fun addClassLabel (cBeforeReplacement : IrClass , argsIncludingOuterClasses : List <IrTypeArgument >? , inReceiverContext : Boolean = false): TypeResult <DbClassorinterface > {
423- val c = tryReplaceAndroidSyntheticClass(cBeforeReplacement)
424- val classLabelResult = getClassLabel(c, argsIncludingOuterClasses)
431+ private fun addClassLabel (cBeforeReplacement : IrClass , argsIncludingOuterClassesBeforeReplacement : List <IrTypeArgument >? , inReceiverContext : Boolean = false): TypeResult <DbClassorinterface > {
432+ val replaced = tryReplaceType(cBeforeReplacement, argsIncludingOuterClassesBeforeReplacement)
433+ val replacedClass = replaced.first
434+ val replacedArgsIncludingOuterClasses = replaced.second
435+
436+ val classLabelResult = getClassLabel(replacedClass, replacedArgsIncludingOuterClasses)
425437
426438 var instanceSeenBefore = true
427439
428- val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel, {
440+ val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel) {
429441 instanceSeenBefore = false
430442
431- extractClassLaterIfExternal(c )
432- })
443+ extractClassLaterIfExternal(replacedClass )
444+ }
433445
434- if (argsIncludingOuterClasses == null || argsIncludingOuterClasses .isNotEmpty()) {
446+ if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses .isNotEmpty()) {
435447 // If this is a generic type instantiation or a raw type then it has no
436448 // source entity, so we need to extract it here
437- val extractorWithCSource by lazy { this .withFileOfClass(c ) }
449+ val extractorWithCSource by lazy { this .withFileOfClass(replacedClass ) }
438450
439451 if (! instanceSeenBefore) {
440- extractorWithCSource.extractClassInstance(c, argsIncludingOuterClasses )
452+ extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses )
441453 }
442454
443455 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)
456+ val supertypeMode = if (replacedArgsIncludingOuterClasses == null ) ExtractSupertypesMode .Raw else ExtractSupertypesMode .Specialised (replacedArgsIncludingOuterClasses )
457+ extractorWithCSource.extractClassSupertypes(replacedClass , classLabel, supertypeMode, true )
458+ extractorWithCSource.extractNonPrivateMemberPrototypes(replacedClass, replacedArgsIncludingOuterClasses , classLabel)
447459 }
448460 }
449461
450462 return TypeResult (
451463 classLabel,
452- c .fqNameWhenAvailable?.asString(),
464+ replacedClass .fqNameWhenAvailable?.asString(),
453465 classLabelResult.shortName)
454466 }
455467
468+ private fun tryReplaceParcelizeRawType (c : IrClass ): Pair <IrClass , List <IrTypeArgument >? >? {
469+ if (c.superTypes.isNotEmpty() ||
470+ c.origin != IrDeclarationOrigin .DEFINED ||
471+ c.hasEqualFqName(FqName (" java.lang.Object" ))) {
472+ return null
473+ }
474+
475+ fun tryGetPair (arity : Int ): Pair <IrClass , List <IrTypeArgument >? >? {
476+ val replaced = pluginContext.referenceClass(c.fqNameWhenAvailable!! )?.owner ? : return null
477+ return Pair (replaced, List (arity) { makeTypeProjection(pluginContext.irBuiltIns.anyNType, Variance .INVARIANT ) })
478+ }
479+
480+ // 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
481+ // Specifically, types are added for generic types created in AndroidSymbols.kt.
482+ // This replacement is from a raw type to its matching parameterized type with `Object` type arguments.
483+ return when (c.fqNameWhenAvailable?.asString()) {
484+ " java.util.ArrayList" -> tryGetPair(1 )
485+ " java.util.LinkedHashMap" -> tryGetPair(2 )
486+ " java.util.LinkedHashSet" -> tryGetPair(1 )
487+ " java.util.List" -> tryGetPair(1 )
488+ " java.util.TreeMap" -> tryGetPair(2 )
489+ " java.util.TreeSet" -> tryGetPair(1 )
490+
491+ " java.lang.Class" -> tryGetPair(1 )
492+
493+ else -> null
494+ }
495+ }
496+
456497 fun useAnonymousClass (c : IrClass ) =
457498 tw.lm.anonymousTypeMapping.getOrPut(c) {
458499 TypeResults (
@@ -721,7 +762,17 @@ open class KotlinUsesExtractor(
721762 } else {
722763 extractFileClass(dp)
723764 }
724- is IrClass -> if (classTypeArguments != null && ! dp.isAnonymousObject) useClassInstance(dp, classTypeArguments, inReceiverContext).typeResult.id else useClassSource(dp)
765+ is IrClass ->
766+ if (classTypeArguments != null && ! dp.isAnonymousObject) {
767+ useClassInstance(dp, classTypeArguments, inReceiverContext).typeResult.id
768+ } else {
769+ val replacedType = tryReplaceParcelizeRawType(dp)
770+ if (replacedType == null ) {
771+ useClassSource(dp)
772+ } else {
773+ useClassInstance(replacedType.first, replacedType.second, inReceiverContext).typeResult.id
774+ }
775+ }
725776 is IrFunction -> useFunction(dp)
726777 is IrExternalPackageFragment -> {
727778 // TODO
0 commit comments