mirror of
https://github.com/github/codeql.git
synced 2025-12-22 19:56:32 +01:00
Extract a generic specialisation using its own type parameters in the same order like an unbound type
This replicates an oddity in the Java extractor that it doesn't differentiate a specialisation Generic<T1, T2, ...> from the unbound type, if T1, T2, ... are Generic's declared type variables occurring in the same order. For example, in `class MyList<T> { void addAll(MyList<T> param) { ... } }`, the type of `param` is an instantiated type, but
gets extracted as an unbound type. This commit can be reverted (except for the improvement to isUnspecialised) if/when that is fixed.
This commit is contained in:
committed by
Ian Lynagh
parent
f3bd89a5cf
commit
d63124a761
@@ -922,7 +922,12 @@ open class KotlinUsesExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
val reorderedArgs = orderTypeArgsLeftToRight(c, argsIncludingOuterClasses)
|
||||
// C<T1, T2, ...>, where C is declared (class|interface) C<T1, T2, ...> { ... }, takes the class label C without
|
||||
// qualification, even in contexts like `class MyList<T> { public void addAll(List<T> otherList) { ... } }`
|
||||
// where this would normally constitute a constructed type. This replicates a quirk of the Java extractor.
|
||||
val typeArgsIfSpecialised = argsIncludingOuterClasses?.let { if (isUnspecialised(c, it)) listOf() else it }
|
||||
|
||||
val reorderedArgs = orderTypeArgsLeftToRight(c, typeArgsIfSpecialised)
|
||||
val typeArgLabels = reorderedArgs?.map { getTypeArgumentLabel(it) }
|
||||
val typeArgsShortName =
|
||||
if (typeArgLabels == null)
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.addConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
@@ -20,6 +21,7 @@ import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.util.constructedClassType
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
@@ -194,14 +196,23 @@ fun IrTypeArgument.withQuestionMark(b: Boolean): IrTypeArgument =
|
||||
typealias TypeSubstitution = (IrType, KotlinUsesExtractor.TypeContext, IrPluginContext) -> IrType
|
||||
|
||||
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
|
||||
fun isUnspecialised(classType: IrClass, args: List<IrTypeArgument>) =
|
||||
classType.typeParameters.zip(args).all { paramAndArg ->
|
||||
fun isUnspecialised(paramsContainer: IrTypeParametersContainer, args: List<IrTypeArgument>): Boolean {
|
||||
val unspecialisedHere = paramsContainer.typeParameters.zip(args).all { paramAndArg ->
|
||||
(paramAndArg.second as? IrTypeProjection)?.let {
|
||||
// Type arg refers to the class' own type parameter?
|
||||
it.variance == Variance.INVARIANT &&
|
||||
it.type.classifierOrNull?.owner === paramAndArg.first
|
||||
} ?: false
|
||||
}
|
||||
val remainingArgs = args.drop(paramsContainer.typeParameters.size)
|
||||
val parent = paramsContainer.parent as? IrTypeParametersContainer
|
||||
val parentUnspecialised = when {
|
||||
remainingArgs.isEmpty() -> true
|
||||
parent == null -> false
|
||||
else -> isUnspecialised(paramsContainer.parentAsClass, remainingArgs)
|
||||
}
|
||||
return unspecialisedHere && parentUnspecialised
|
||||
}
|
||||
|
||||
// Returns true if type is C<T1, T2, ...> where C is declared `class C<T1, T2, ...> { ... }`
|
||||
fun isUnspecialised(type: IrSimpleType) = (type.classifier.owner as? IrClass)?.let {
|
||||
|
||||
Reference in New Issue
Block a user