@@ -417,42 +417,83 @@ open class KotlinUsesExtractor(
417
417
} ? : f
418
418
}
419
419
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
+
420
429
// `typeArgs` can be null to describe a raw generic type.
421
430
// 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)
425
437
426
438
var instanceSeenBefore = true
427
439
428
- val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel, {
440
+ val classLabel : Label <out DbClassorinterface > = tw.getLabelFor(classLabelResult.classLabel) {
429
441
instanceSeenBefore = false
430
442
431
- extractClassLaterIfExternal(c )
432
- })
443
+ extractClassLaterIfExternal(replacedClass )
444
+ }
433
445
434
- if (argsIncludingOuterClasses == null || argsIncludingOuterClasses .isNotEmpty()) {
446
+ if (replacedArgsIncludingOuterClasses == null || replacedArgsIncludingOuterClasses .isNotEmpty()) {
435
447
// If this is a generic type instantiation or a raw type then it has no
436
448
// 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 ) }
438
450
439
451
if (! instanceSeenBefore) {
440
- extractorWithCSource.extractClassInstance(c, argsIncludingOuterClasses )
452
+ extractorWithCSource.extractClassInstance(replacedClass, replacedArgsIncludingOuterClasses )
441
453
}
442
454
443
455
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)
447
459
}
448
460
}
449
461
450
462
return TypeResult (
451
463
classLabel,
452
- c .fqNameWhenAvailable?.asString(),
464
+ replacedClass .fqNameWhenAvailable?.asString(),
453
465
classLabelResult.shortName)
454
466
}
455
467
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
+
456
497
fun useAnonymousClass (c : IrClass ) =
457
498
tw.lm.anonymousTypeMapping.getOrPut(c) {
458
499
TypeResults (
@@ -721,7 +762,17 @@ open class KotlinUsesExtractor(
721
762
} else {
722
763
extractFileClass(dp)
723
764
}
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
+ }
725
776
is IrFunction -> useFunction(dp)
726
777
is IrExternalPackageFragment -> {
727
778
// TODO
0 commit comments