@@ -539,31 +539,62 @@ open class KotlinUsesExtractor(
539539 )
540540 }
541541
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 )
543545
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
545568 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 )
548571 }
549572
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+ }
552580
553- val componentTypeResults = useType(nullableIfNotPrimitive(componentType))
554- val elementTypeLabel = useType(nullableIfNotPrimitive(elementType)).javaResult.id
581+ val recInfo = useArrayType(elementType, t.isPrimitiveArray())
555582
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
557588
558589 val id = tw.getLabelFor<DbArray >(" @\" array;$dimensions ;{${elementTypeLabel} }\" " ) {
559590 tw.writeArrays(
560591 it,
561592 javaShortName,
562593 elementTypeLabel,
563594 dimensions,
564- componentTypeResults.javaResult.id )
595+ componentTypeLabel )
565596
566- extractClassSupertypes(arrayClass, it, ExtractSupertypesMode .Specialised (arrayType .arguments))
597+ extractClassSupertypes(arrayClass, it, ExtractSupertypesMode .Specialised (t .arguments))
567598
568599 // array.length
569600 val length = tw.getLabelFor<DbField >(" @\" field;{$it };length\" " )
@@ -574,7 +605,7 @@ open class KotlinUsesExtractor(
574605
575606 // Note we will only emit one `clone()` method per Java array type, so we choose `Array<C?>` as its Kotlin
576607 // 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()
578609 val kotlinCloneReturnTypeLabel = useType(kotlinCloneReturnType).kotlinResult.id
579610
580611 val clone = tw.getLabelFor<DbMethod >(" @\" callable;{$it }.clone(){$it }\" " )
@@ -585,11 +616,15 @@ open class KotlinUsesExtractor(
585616
586617 val javaResult = TypeResult (
587618 id,
588- componentTypeResults.javaResult.signature + " []" ,
619+ recInfo. componentTypeResults.javaResult.signature + " []" ,
589620 javaShortName)
621+ val kotlinResult = TypeResult (
622+ fakeKotlinType(),
623+ recInfo.componentTypeResults.kotlinResult.signature + " []" ,
624+ kotlinShortName)
625+ val typeResults = TypeResults (javaResult, kotlinResult)
590626
591- val arrayClassResult = useSimpleTypeClass(arrayClass, arrayType.arguments, arrayType.hasQuestionMark)
592- return TypeResults (javaResult, arrayClassResult.kotlinResult)
627+ return ArrayInfo (recInfo.elementTypeResults, typeResults, dimensions)
593628 }
594629
595630 enum class TypeContext {
@@ -662,45 +697,8 @@ open class KotlinUsesExtractor(
662697 }
663698
664699 (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
704702 }
705703
706704 owner is IrClass -> {
0 commit comments