Skip to content

Commit 4a02505

Browse files
authored
Merge pull request #9400 from tamasvajk/kotlin-fix-parcelize-symbols
Kotlin: Fix fake raw type symbols used by the Parcelize plugin
2 parents 07c22a8 + 0a484aa commit 4a02505

File tree

1 file changed

+65
-14
lines changed

1 file changed

+65
-14
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)