mirror of
https://github.com/github/codeql.git
synced 2025-12-22 11:46:32 +01:00
Merge pull request #10154 from igfoo/igfoo/findSubType
Kotlin: Implement and use fun <T,reified S: T> Iterable<T>.findSubType
This commit is contained in:
@@ -1584,7 +1584,7 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.find { it is IrFunction && it.name.asString() == name } as IrFunction?
|
||||
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.findSubType<IrFunction> { it.name.asString() == name }
|
||||
|
||||
val jvmIntrinsicsClass by lazy {
|
||||
val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner
|
||||
@@ -1641,12 +1641,11 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
|
||||
val stringValueOfObjectMethod by lazy {
|
||||
val result = javaLangString?.declarations?.find {
|
||||
it is IrFunction &&
|
||||
val result = javaLangString?.declarations?.findSubType<IrFunction> {
|
||||
it.name.asString() == "valueOf" &&
|
||||
it.valueParameters.size == 1 &&
|
||||
it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType
|
||||
} as IrFunction?
|
||||
}
|
||||
if (result == null) {
|
||||
logger.error("Couldn't find declaration java.lang.String.valueOf(Object)")
|
||||
}
|
||||
@@ -1654,9 +1653,9 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
|
||||
val objectCloneMethod by lazy {
|
||||
val result = javaLangObject?.declarations?.find {
|
||||
it is IrFunction && it.name.asString() == "clone"
|
||||
} as IrFunction?
|
||||
val result = javaLangObject?.declarations?.findSubType<IrFunction> {
|
||||
it.name.asString() == "clone"
|
||||
}
|
||||
if (result == null) {
|
||||
logger.error("Couldn't find declaration java.lang.Object.clone(...)")
|
||||
}
|
||||
@@ -1670,10 +1669,9 @@ open class KotlinFileExtractor(
|
||||
}
|
||||
|
||||
val kotlinNoWhenBranchMatchedConstructor by lazy {
|
||||
val result = kotlinNoWhenBranchMatchedExn?.declarations?.find {
|
||||
it is IrConstructor &&
|
||||
val result = kotlinNoWhenBranchMatchedExn?.declarations?.findSubType<IrConstructor> {
|
||||
it.valueParameters.isEmpty()
|
||||
} as IrConstructor?
|
||||
}
|
||||
if (result == null) {
|
||||
logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException")
|
||||
}
|
||||
@@ -1798,13 +1796,13 @@ open class KotlinFileExtractor(
|
||||
return
|
||||
}
|
||||
|
||||
val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.find { it is IrFunction && it.name.asString() == fnName }
|
||||
val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.findSubType<IrFunction> { it.name.asString() == fnName }
|
||||
if (func == null) {
|
||||
logger.errorElement("Couldn't find function $fnName on enum type", c)
|
||||
return
|
||||
}
|
||||
|
||||
extractMethodAccess(func as IrFunction, false)
|
||||
extractMethodAccess(func, false)
|
||||
}
|
||||
|
||||
fun binopReceiver(id: Label<out DbExpr>, receiver: IrExpression?, receiverDescription: String) {
|
||||
@@ -2273,10 +2271,10 @@ open class KotlinFileExtractor(
|
||||
logger.errorElement("Argument to dataClassArrayMemberToString not a class", c)
|
||||
return
|
||||
}
|
||||
val realCallee = javaUtilArrays?.declarations?.find { decl ->
|
||||
decl is IrFunction && decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
|
||||
val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
|
||||
decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
|
||||
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
|
||||
} as IrFunction?
|
||||
}
|
||||
if (realCallee == null) {
|
||||
logger.errorElement("Couldn't find a java.lang.Arrays.toString method matching class ${realArrayClass.owner.name}", c)
|
||||
} else {
|
||||
@@ -2300,10 +2298,10 @@ open class KotlinFileExtractor(
|
||||
logger.errorElement("Argument to dataClassArrayMemberHashCode not a class", c)
|
||||
return
|
||||
}
|
||||
val realCallee = javaUtilArrays?.declarations?.find { decl ->
|
||||
decl is IrFunction && decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
|
||||
val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
|
||||
decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
|
||||
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
|
||||
} as IrFunction?
|
||||
}
|
||||
if (realCallee == null) {
|
||||
logger.errorElement("Couldn't find a java.lang.Arrays.hashCode method matching class ${realArrayClass.owner.name}", c)
|
||||
} else {
|
||||
@@ -4452,7 +4450,7 @@ open class KotlinFileExtractor(
|
||||
return
|
||||
}
|
||||
|
||||
val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction>()?.find { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
|
||||
val invokeMethod = functionType.classOrNull?.owner?.declarations?.findSubType<IrFunction> { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
|
||||
if (invokeMethod == null) {
|
||||
logger.errorElement("Couldn't find `invoke` method on functional interface.", e)
|
||||
return
|
||||
@@ -4463,7 +4461,7 @@ open class KotlinFileExtractor(
|
||||
logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e)
|
||||
return
|
||||
}
|
||||
val samMember = typeOwner.declarations.filterIsInstance<IrFunction>().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
|
||||
val samMember = typeOwner.declarations.findSubType<IrFunction> { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
|
||||
if (samMember == null) {
|
||||
logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e)
|
||||
return
|
||||
@@ -4652,7 +4650,7 @@ open class KotlinFileExtractor(
|
||||
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
|
||||
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
|
||||
|
||||
val baseConstructor = baseClass.owner.declarations.find { it is IrFunction && it.symbol is IrConstructorSymbol }
|
||||
val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol }
|
||||
val baseConstructorId = useFunction<DbConstructor>(baseConstructor as IrFunction)
|
||||
|
||||
tw.writeHasLocation(superCallId, locId)
|
||||
|
||||
@@ -326,11 +326,11 @@ open class KotlinUsesExtractor(
|
||||
if (replacementClass === parentClass)
|
||||
return f
|
||||
return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) {
|
||||
val result = replacementClass.declarations.find { replacementDecl ->
|
||||
val result = replacementClass.declarations.findSubType<IrSimpleFunction> { replacementDecl ->
|
||||
replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all {
|
||||
erase(it.first.type) == erase(it.second.type)
|
||||
}
|
||||
} as IrFunction?
|
||||
}
|
||||
if (result == null) {
|
||||
logger.warn("Failed to replace synthetic class function ${f.name}")
|
||||
} else {
|
||||
@@ -351,9 +351,9 @@ open class KotlinUsesExtractor(
|
||||
if (replacementClass === parentClass)
|
||||
return f
|
||||
return globalExtensionState.syntheticToRealFieldMap.getOrPut(f) {
|
||||
val result = replacementClass.declarations.find { replacementDecl ->
|
||||
replacementDecl is IrField && replacementDecl.name == f.name
|
||||
} as IrField?
|
||||
val result = replacementClass.declarations.findSubType<IrField> { replacementDecl ->
|
||||
replacementDecl.name == f.name
|
||||
}
|
||||
if (result == null) {
|
||||
logger.warn("Failed to replace synthetic class field ${f.name}")
|
||||
} else {
|
||||
@@ -1097,7 +1097,7 @@ open class KotlinUsesExtractor(
|
||||
return f.returnType
|
||||
}
|
||||
|
||||
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
|
||||
val otherKeySet = parentClass.declarations.findSubType<IrFunction> { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
|
||||
?: return f.returnType
|
||||
|
||||
return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
|
||||
@@ -1177,8 +1177,7 @@ open class KotlinUsesExtractor(
|
||||
getJavaEquivalentClass(parentClass)?.let { javaClass ->
|
||||
if (javaClass != parentClass)
|
||||
// Look for an exact type match...
|
||||
javaClass.declarations.find { decl ->
|
||||
decl is IrFunction &&
|
||||
javaClass.declarations.findSubType<IrFunction> { decl ->
|
||||
decl.name == f.name &&
|
||||
decl.valueParameters.size == f.valueParameters.size &&
|
||||
// Note matching by classifier not the whole type so that generic arguments are allowed to differ,
|
||||
@@ -1194,7 +1193,7 @@ open class KotlinUsesExtractor(
|
||||
} ?:
|
||||
// Or check property accessors:
|
||||
if (f.isAccessor) {
|
||||
val prop = javaClass.declarations.filterIsInstance<IrProperty>().find { decl ->
|
||||
val prop = javaClass.declarations.findSubType<IrProperty> { decl ->
|
||||
decl.name == (f.propertyIfAccessor as IrProperty).name
|
||||
}
|
||||
if (prop?.getter?.name == f.name)
|
||||
|
||||
15
java/kotlin-extractor/src/main/kotlin/utils/Iterable.kt
Normal file
15
java/kotlin-extractor/src/main/kotlin/utils/Iterable.kt
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.github.codeql
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
|
||||
/**
|
||||
* This behaves the same as Iterable<IrDeclaration>.find, but requires
|
||||
* that the value found is of the subtype S, and it casts
|
||||
* the result for you appropriately.
|
||||
*/
|
||||
inline fun <reified S: IrDeclaration> Iterable<IrDeclaration>.findSubType(
|
||||
predicate: (S) -> Boolean
|
||||
): S? {
|
||||
return this.find { it is S && predicate(it) } as S?
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user