@@ -539,31 +539,62 @@ open class KotlinUsesExtractor(
539
539
)
540
540
}
541
541
542
- private fun useArrayType (arrayType : IrSimpleType , componentType : IrType , elementType : IrType , dimensions : Int , isPrimitiveArray : Boolean ): TypeResults {
542
+ data class ArrayInfo (val elementTypeResults : TypeResults ,
543
+ val componentTypeResults : TypeResults ,
544
+ val dimensions : Int )
543
545
544
- val arrayClass = arrayType.classifier.owner
546
+ /* *
547
+ * `t` is somewhere in a stack of array types, or possibly the
548
+ * element type of the innermost array. For example, in
549
+ * `Array<Array<Int>>`, we will be called with `t` being
550
+ * `Array<Array<Int>>`, then `Array<Int>`, then `Int`.
551
+ * `isPrimitiveArray` is true if we are immediately nested
552
+ * inside a primitive array.
553
+ */
554
+ private fun useArrayType (t : IrType , isPrimitiveArray : Boolean ): ArrayInfo {
555
+
556
+ if (! t.isBoxedArray && ! t.isPrimitiveArray()) {
557
+ val nullableT = if (t.isPrimitiveType() && ! isPrimitiveArray) t.makeNullable() else t
558
+ val typeResults = useType(nullableT)
559
+ return ArrayInfo (typeResults, typeResults, 0 )
560
+ }
561
+
562
+ if (t !is IrSimpleType ) {
563
+ logger.error(" Unexpected non-simple array type: ${t.javaClass} " )
564
+ return ArrayInfo (extractErrorType(), extractErrorType(), 0 )
565
+ }
566
+
567
+ val arrayClass = t.classifier.owner
545
568
if (arrayClass !is IrClass ) {
546
- error(" Unexpected owner type for array type: ${arrayClass.javaClass} " )
547
- return extractErrorType()
569
+ logger. error(" Unexpected owner type for array type: ${arrayClass.javaClass} " )
570
+ return ArrayInfo ( extractErrorType(), extractErrorType(), 0 )
548
571
}
549
572
550
- // Ensure we extract Array<Int> as Integer[], not int[], for example:
551
- fun nullableIfNotPrimitive (type : IrType ) = if (type.isPrimitiveType() && ! isPrimitiveArray) type.makeNullable() else type
573
+ // Because Java's arrays are covariant, Kotlin will render
574
+ // Array<in X> as Object[], Array<Array<in X>> as Object[][] etc.
575
+ val elementType = if ((t.arguments.singleOrNull() as ? IrTypeProjection )?.variance == Variance .IN_VARIANCE ) {
576
+ pluginContext.irBuiltIns.anyType
577
+ } else {
578
+ t.getArrayElementType(pluginContext.irBuiltIns)
579
+ }
552
580
553
- val componentTypeResults = useType(nullableIfNotPrimitive(componentType))
554
- val elementTypeLabel = useType(nullableIfNotPrimitive(elementType)).javaResult.id
581
+ val recInfo = useArrayType(elementType, t.isPrimitiveArray())
555
582
556
- val javaShortName = componentTypeResults.javaResult.shortName + " []"
583
+ val javaShortName = recInfo.componentTypeResults.javaResult.shortName + " []"
584
+ val kotlinShortName = recInfo.componentTypeResults.kotlinResult.shortName + " []"
585
+ val elementTypeLabel = recInfo.elementTypeResults.javaResult.id
586
+ val componentTypeLabel = recInfo.componentTypeResults.javaResult.id
587
+ val dimensions = recInfo.dimensions + 1
557
588
558
589
val id = tw.getLabelFor<DbArray >(" @\" array;$dimensions ;{${elementTypeLabel} }\" " ) {
559
590
tw.writeArrays(
560
591
it,
561
592
javaShortName,
562
593
elementTypeLabel,
563
594
dimensions,
564
- componentTypeResults.javaResult.id )
595
+ componentTypeLabel )
565
596
566
- extractClassSupertypes(arrayClass, it, ExtractSupertypesMode .Specialised (arrayType .arguments))
597
+ extractClassSupertypes(arrayClass, it, ExtractSupertypesMode .Specialised (t .arguments))
567
598
568
599
// array.length
569
600
val length = tw.getLabelFor<DbField >(" @\" field;{$it };length\" " )
@@ -574,7 +605,7 @@ open class KotlinUsesExtractor(
574
605
575
606
// Note we will only emit one `clone()` method per Java array type, so we choose `Array<C?>` as its Kotlin
576
607
// return type, where C is the component type with any nested arrays themselves invariant and nullable.
577
- val kotlinCloneReturnType = getInvariantNullableArrayType(arrayType ).makeNullable()
608
+ val kotlinCloneReturnType = getInvariantNullableArrayType(t ).makeNullable()
578
609
val kotlinCloneReturnTypeLabel = useType(kotlinCloneReturnType).kotlinResult.id
579
610
580
611
val clone = tw.getLabelFor<DbMethod >(" @\" callable;{$it }.clone(){$it }\" " )
@@ -585,11 +616,15 @@ open class KotlinUsesExtractor(
585
616
586
617
val javaResult = TypeResult (
587
618
id,
588
- componentTypeResults.javaResult.signature + " []" ,
619
+ recInfo. componentTypeResults.javaResult.signature + " []" ,
589
620
javaShortName)
621
+ val kotlinResult = TypeResult (
622
+ fakeKotlinType(),
623
+ recInfo.componentTypeResults.kotlinResult.signature + " []" ,
624
+ kotlinShortName)
625
+ val typeResults = TypeResults (javaResult, kotlinResult)
590
626
591
- val arrayClassResult = useSimpleTypeClass(arrayClass, arrayType.arguments, arrayType.hasQuestionMark)
592
- return TypeResults (javaResult, arrayClassResult.kotlinResult)
627
+ return ArrayInfo (recInfo.elementTypeResults, typeResults, dimensions)
593
628
}
594
629
595
630
enum class TypeContext {
@@ -662,45 +697,8 @@ open class KotlinUsesExtractor(
662
697
}
663
698
664
699
(s.isBoxedArray && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> {
665
-
666
- fun replaceComponentTypeWithAny (t : IrSimpleType , dimensions : Int ): IrType =
667
- if (dimensions == 0 )
668
- pluginContext.irBuiltIns.anyType
669
- else
670
- t.toBuilder().also { it.arguments = (it.arguments[0 ] as IrTypeProjection )
671
- .let { oldArg ->
672
- listOf (makeTypeProjection(replaceComponentTypeWithAny(oldArg.type as IrSimpleType , dimensions - 1 ), oldArg.variance))
673
- }
674
- }.buildSimpleType()
675
-
676
- var componentType: IrType = s.getArrayElementType(pluginContext.irBuiltIns)
677
- var isPrimitiveArray = false
678
- var dimensions = 0
679
- var elementType: IrType = s
680
- while (elementType.isBoxedArray || elementType.isPrimitiveArray()) {
681
- dimensions++
682
- if (elementType.isPrimitiveArray())
683
- isPrimitiveArray = true
684
- if (elementType is IrSimpleType ) {
685
- if ((elementType.arguments.singleOrNull() as ? IrTypeProjection )?.variance == Variance .IN_VARIANCE ) {
686
- // Because Java's arrays are covariant, Kotlin will render Array<in X> as Object[], Array<Array<in X>> as Object[][] etc.
687
- componentType = replaceComponentTypeWithAny(s, dimensions - 1 )
688
- elementType = pluginContext.irBuiltIns.anyType
689
- break
690
- }
691
- } else {
692
- logger.warn(" Unexpected element type representation ${elementType.javaClass} for ${s.render()} " )
693
- }
694
- elementType = elementType.getArrayElementType(pluginContext.irBuiltIns)
695
- }
696
-
697
- return useArrayType(
698
- s,
699
- componentType,
700
- elementType,
701
- dimensions,
702
- isPrimitiveArray
703
- )
700
+ val arrayInfo = useArrayType(s, false )
701
+ return arrayInfo.componentTypeResults
704
702
}
705
703
706
704
owner is IrClass -> {
0 commit comments