@@ -419,31 +419,35 @@ open class KotlinUsesExtractor(
419
419
420
420
// `typeArgs` can be null to describe a raw generic type.
421
421
// 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 > {
423
423
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)
425
429
426
430
var instanceSeenBefore = true
427
431
428
- val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel, {
432
+ val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel) {
429
433
instanceSeenBefore = false
430
434
431
- extractClassLaterIfExternal(c )
432
- })
435
+ extractClassLaterIfExternal(replacedClass )
436
+ }
433
437
434
- if (argsIncludingOuterClasses == null || argsIncludingOuterClasses .isNotEmpty()) {
438
+ if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses .isNotEmpty()) {
435
439
// If this is a generic type instantiation or a raw type then it has no
436
440
// 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 ) }
438
442
439
443
if (! instanceSeenBefore) {
440
- extractorWithCSource.extractClassInstance(c, argsIncludingOuterClasses )
444
+ extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses )
441
445
}
442
446
443
447
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)
447
451
}
448
452
}
449
453
@@ -453,6 +457,35 @@ open class KotlinUsesExtractor(
453
457
classLabelResult.shortName)
454
458
}
455
459
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
+
456
489
fun useAnonymousClass (c : IrClass ) =
457
490
tw.lm.anonymousTypeMapping.getOrPut(c) {
458
491
TypeResults (
@@ -721,7 +754,15 @@ open class KotlinUsesExtractor(
721
754
} else {
722
755
extractFileClass(dp)
723
756
}
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
+ }
725
766
is IrFunction -> useFunction(dp)
726
767
is IrExternalPackageFragment -> {
727
768
// TODO
@@ -1281,13 +1322,13 @@ open class KotlinUsesExtractor(
1281
1322
unquotedLabel.shortName)
1282
1323
}
1283
1324
1284
- fun useClassSource (c : IrClass ): Label <out DbClassorinterface > {
1325
+ fun useClassSource (c : IrClass , inReceiverContext : Boolean = false ): Label <out DbClassorinterface > {
1285
1326
if (c.isAnonymousObject) {
1286
1327
return useAnonymousClass(c).javaResult.id.cast<DbClass >()
1287
1328
}
1288
1329
1289
1330
// For source classes, the label doesn't include and type arguments
1290
- val classTypeResult = addClassLabel(c, listOf ())
1331
+ val classTypeResult = addClassLabel(c, listOf (), inReceiverContext )
1291
1332
return classTypeResult.id
1292
1333
}
1293
1334
0 commit comments