mirror of
https://github.com/github/codeql.git
synced 2025-12-24 20:56:33 +01:00
Kotlin: Rewrite array type extraction
It's now simpler, and doesn't require we ask the Kotlin compiler to build as many types for us.
This commit is contained in:
@@ -539,21 +539,52 @@ open class KotlinUsesExtractor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun useArrayType(arrayType: IrSimpleType, componentType: IrType, elementType: IrType, dimensions: Int, isPrimitiveArray: Boolean): TypeResults {
|
data class ArrayInfo(val elementTypeResults: TypeResults,
|
||||||
|
val componentTypeResults: TypeResults,
|
||||||
|
val dimensions: Int)
|
||||||
|
|
||||||
val arrayClass = arrayType.classifier.owner
|
/**
|
||||||
if (arrayClass !is IrClass) {
|
* `t` is somewhere in a stack of array types, or possibly the
|
||||||
error("Unexpected owner type for array type: ${arrayClass.javaClass}")
|
* element type of the innermost array. For example, in
|
||||||
return extractErrorType()
|
* `Array<Array<Int>>`, we will be called with `t` being
|
||||||
|
* `Array<Array<Int>>`, then `Array<Int>`, then `Int`.
|
||||||
|
* `isPrimitiveArray` is true if we are immediately nested
|
||||||
|
* inside a primitive array.
|
||||||
|
*/
|
||||||
|
private fun useArrayType(t: IrType, isPrimitiveArray: Boolean): ArrayInfo {
|
||||||
|
|
||||||
|
if (!t.isBoxedArray && !t.isPrimitiveArray()) {
|
||||||
|
val nullableT = if (t.isPrimitiveType() && !isPrimitiveArray) t.makeNullable() else t
|
||||||
|
val typeResults = useType(nullableT)
|
||||||
|
return ArrayInfo(typeResults, typeResults, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure we extract Array<Int> as Integer[], not int[], for example:
|
if (t !is IrSimpleType) {
|
||||||
fun nullableIfNotPrimitive(type: IrType) = if (type.isPrimitiveType() && !isPrimitiveArray) type.makeNullable() else type
|
logger.error("Unexpected non-simple array type: ${t.javaClass}")
|
||||||
|
return ArrayInfo(extractErrorType(), extractErrorType(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
val componentTypeResults = useType(nullableIfNotPrimitive(componentType))
|
val arrayClass = t.classifier.owner
|
||||||
val elementTypeLabel = useType(nullableIfNotPrimitive(elementType)).javaResult.id
|
if (arrayClass !is IrClass) {
|
||||||
|
logger.error("Unexpected owner type for array type: ${arrayClass.javaClass}")
|
||||||
|
return ArrayInfo(extractErrorType(), extractErrorType(), 0)
|
||||||
|
}
|
||||||
|
|
||||||
val javaShortName = componentTypeResults.javaResult.shortName + "[]"
|
// Because Java's arrays are covariant, Kotlin will render
|
||||||
|
// Array<in X> as Object[], Array<Array<in X>> as Object[][] etc.
|
||||||
|
val elementType = if ((t.arguments.singleOrNull() as? IrTypeProjection)?.variance == Variance.IN_VARIANCE) {
|
||||||
|
pluginContext.irBuiltIns.anyType
|
||||||
|
} else {
|
||||||
|
t.getArrayElementType(pluginContext.irBuiltIns)
|
||||||
|
}
|
||||||
|
|
||||||
|
val recInfo = useArrayType(elementType, t.isPrimitiveArray())
|
||||||
|
|
||||||
|
val javaShortName = recInfo.componentTypeResults.javaResult.shortName + "[]"
|
||||||
|
val kotlinShortName = recInfo.componentTypeResults.kotlinResult.shortName + "[]"
|
||||||
|
val elementTypeLabel = recInfo.elementTypeResults.javaResult.id
|
||||||
|
val componentTypeLabel = recInfo.componentTypeResults.javaResult.id
|
||||||
|
val dimensions = recInfo.dimensions + 1
|
||||||
|
|
||||||
val id = tw.getLabelFor<DbArray>("@\"array;$dimensions;{${elementTypeLabel}}\"") {
|
val id = tw.getLabelFor<DbArray>("@\"array;$dimensions;{${elementTypeLabel}}\"") {
|
||||||
tw.writeArrays(
|
tw.writeArrays(
|
||||||
@@ -561,9 +592,9 @@ open class KotlinUsesExtractor(
|
|||||||
javaShortName,
|
javaShortName,
|
||||||
elementTypeLabel,
|
elementTypeLabel,
|
||||||
dimensions,
|
dimensions,
|
||||||
componentTypeResults.javaResult.id)
|
componentTypeLabel)
|
||||||
|
|
||||||
extractClassSupertypes(arrayClass, it, ExtractSupertypesMode.Specialised(arrayType.arguments))
|
extractClassSupertypes(arrayClass, it, ExtractSupertypesMode.Specialised(t.arguments))
|
||||||
|
|
||||||
// array.length
|
// array.length
|
||||||
val length = tw.getLabelFor<DbField>("@\"field;{$it};length\"")
|
val length = tw.getLabelFor<DbField>("@\"field;{$it};length\"")
|
||||||
@@ -574,7 +605,7 @@ open class KotlinUsesExtractor(
|
|||||||
|
|
||||||
// Note we will only emit one `clone()` method per Java array type, so we choose `Array<C?>` as its Kotlin
|
// Note we will only emit one `clone()` method per Java array type, so we choose `Array<C?>` as its Kotlin
|
||||||
// return type, where C is the component type with any nested arrays themselves invariant and nullable.
|
// return type, where C is the component type with any nested arrays themselves invariant and nullable.
|
||||||
val kotlinCloneReturnType = getInvariantNullableArrayType(arrayType).makeNullable()
|
val kotlinCloneReturnType = getInvariantNullableArrayType(t).makeNullable()
|
||||||
val kotlinCloneReturnTypeLabel = useType(kotlinCloneReturnType).kotlinResult.id
|
val kotlinCloneReturnTypeLabel = useType(kotlinCloneReturnType).kotlinResult.id
|
||||||
|
|
||||||
val clone = tw.getLabelFor<DbMethod>("@\"callable;{$it}.clone(){$it}\"")
|
val clone = tw.getLabelFor<DbMethod>("@\"callable;{$it}.clone(){$it}\"")
|
||||||
@@ -585,11 +616,15 @@ open class KotlinUsesExtractor(
|
|||||||
|
|
||||||
val javaResult = TypeResult(
|
val javaResult = TypeResult(
|
||||||
id,
|
id,
|
||||||
componentTypeResults.javaResult.signature + "[]",
|
recInfo.componentTypeResults.javaResult.signature + "[]",
|
||||||
javaShortName)
|
javaShortName)
|
||||||
|
val kotlinResult = TypeResult(
|
||||||
|
fakeKotlinType(),
|
||||||
|
recInfo.componentTypeResults.kotlinResult.signature + "[]",
|
||||||
|
kotlinShortName)
|
||||||
|
val typeResults = TypeResults(javaResult, kotlinResult)
|
||||||
|
|
||||||
val arrayClassResult = useSimpleTypeClass(arrayClass, arrayType.arguments, arrayType.hasQuestionMark)
|
return ArrayInfo(recInfo.elementTypeResults, typeResults, dimensions)
|
||||||
return TypeResults(javaResult, arrayClassResult.kotlinResult)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum class TypeContext {
|
enum class TypeContext {
|
||||||
@@ -662,45 +697,8 @@ open class KotlinUsesExtractor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
(s.isBoxedArray && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> {
|
(s.isBoxedArray && s.arguments.isNotEmpty()) || s.isPrimitiveArray() -> {
|
||||||
|
val arrayInfo = useArrayType(s, false)
|
||||||
fun replaceComponentTypeWithAny(t: IrSimpleType, dimensions: Int): IrType =
|
return arrayInfo.componentTypeResults
|
||||||
if (dimensions == 0)
|
|
||||||
pluginContext.irBuiltIns.anyType
|
|
||||||
else
|
|
||||||
t.toBuilder().also { it.arguments = (it.arguments[0] as IrTypeProjection)
|
|
||||||
.let { oldArg ->
|
|
||||||
listOf(makeTypeProjection(replaceComponentTypeWithAny(oldArg.type as IrSimpleType, dimensions - 1), oldArg.variance))
|
|
||||||
}
|
|
||||||
}.buildSimpleType()
|
|
||||||
|
|
||||||
var componentType: IrType = s.getArrayElementType(pluginContext.irBuiltIns)
|
|
||||||
var isPrimitiveArray = false
|
|
||||||
var dimensions = 0
|
|
||||||
var elementType: IrType = s
|
|
||||||
while (elementType.isBoxedArray || elementType.isPrimitiveArray()) {
|
|
||||||
dimensions++
|
|
||||||
if (elementType.isPrimitiveArray())
|
|
||||||
isPrimitiveArray = true
|
|
||||||
if (elementType is IrSimpleType) {
|
|
||||||
if ((elementType.arguments.singleOrNull() as? IrTypeProjection)?.variance == Variance.IN_VARIANCE) {
|
|
||||||
// Because Java's arrays are covariant, Kotlin will render Array<in X> as Object[], Array<Array<in X>> as Object[][] etc.
|
|
||||||
componentType = replaceComponentTypeWithAny(s, dimensions - 1)
|
|
||||||
elementType = pluginContext.irBuiltIns.anyType
|
|
||||||
break
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.warn("Unexpected element type representation ${elementType.javaClass} for ${s.render()}")
|
|
||||||
}
|
|
||||||
elementType = elementType.getArrayElementType(pluginContext.irBuiltIns)
|
|
||||||
}
|
|
||||||
|
|
||||||
return useArrayType(
|
|
||||||
s,
|
|
||||||
componentType,
|
|
||||||
elementType,
|
|
||||||
dimensions,
|
|
||||||
isPrimitiveArray
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
owner is IrClass -> {
|
owner is IrClass -> {
|
||||||
|
|||||||
Reference in New Issue
Block a user