Skip to content

Commit 2e2621a

Browse files
authored
Merge pull request #10154 from igfoo/igfoo/findSubType
Kotlin: Implement and use fun <T,reified S: T> Iterable<T>.findSubType
2 parents ba1ad00 + 12eab3d commit 2e2621a

File tree

3 files changed

+42
-30
lines changed

3 files changed

+42
-30
lines changed

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,7 +1584,7 @@ open class KotlinFileExtractor(
15841584
}
15851585
}
15861586

1587-
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.find { it is IrFunction && it.name.asString() == name } as IrFunction?
1587+
private fun findFunction(cls: IrClass, name: String): IrFunction? = cls.declarations.findSubType<IrFunction> { it.name.asString() == name }
15881588

15891589
val jvmIntrinsicsClass by lazy {
15901590
val result = pluginContext.referenceClass(FqName("kotlin.jvm.internal.Intrinsics"))?.owner
@@ -1641,22 +1641,21 @@ open class KotlinFileExtractor(
16411641
}
16421642

16431643
val stringValueOfObjectMethod by lazy {
1644-
val result = javaLangString?.declarations?.find {
1645-
it is IrFunction &&
1644+
val result = javaLangString?.declarations?.findSubType<IrFunction> {
16461645
it.name.asString() == "valueOf" &&
16471646
it.valueParameters.size == 1 &&
16481647
it.valueParameters[0].type == pluginContext.irBuiltIns.anyNType
1649-
} as IrFunction?
1648+
}
16501649
if (result == null) {
16511650
logger.error("Couldn't find declaration java.lang.String.valueOf(Object)")
16521651
}
16531652
result
16541653
}
16551654

16561655
val objectCloneMethod by lazy {
1657-
val result = javaLangObject?.declarations?.find {
1658-
it is IrFunction && it.name.asString() == "clone"
1659-
} as IrFunction?
1656+
val result = javaLangObject?.declarations?.findSubType<IrFunction> {
1657+
it.name.asString() == "clone"
1658+
}
16601659
if (result == null) {
16611660
logger.error("Couldn't find declaration java.lang.Object.clone(...)")
16621661
}
@@ -1670,10 +1669,9 @@ open class KotlinFileExtractor(
16701669
}
16711670

16721671
val kotlinNoWhenBranchMatchedConstructor by lazy {
1673-
val result = kotlinNoWhenBranchMatchedExn?.declarations?.find {
1674-
it is IrConstructor &&
1672+
val result = kotlinNoWhenBranchMatchedExn?.declarations?.findSubType<IrConstructor> {
16751673
it.valueParameters.isEmpty()
1676-
} as IrConstructor?
1674+
}
16771675
if (result == null) {
16781676
logger.error("Couldn't find no-arg constructor for kotlin.NoWhenBranchMatchedException")
16791677
}
@@ -1798,13 +1796,13 @@ open class KotlinFileExtractor(
17981796
return
17991797
}
18001798

1801-
val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.find { it is IrFunction && it.name.asString() == fnName }
1799+
val func = ((c.getTypeArgument(0) as? IrSimpleType)?.classifier?.owner as? IrClass)?.declarations?.findSubType<IrFunction> { it.name.asString() == fnName }
18021800
if (func == null) {
18031801
logger.errorElement("Couldn't find function $fnName on enum type", c)
18041802
return
18051803
}
18061804

1807-
extractMethodAccess(func as IrFunction, false)
1805+
extractMethodAccess(func, false)
18081806
}
18091807

18101808
fun binopReceiver(id: Label<out DbExpr>, receiver: IrExpression?, receiverDescription: String) {
@@ -2273,10 +2271,10 @@ open class KotlinFileExtractor(
22732271
logger.errorElement("Argument to dataClassArrayMemberToString not a class", c)
22742272
return
22752273
}
2276-
val realCallee = javaUtilArrays?.declarations?.find { decl ->
2277-
decl is IrFunction && decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
2274+
val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
2275+
decl.name.asString() == "toString" && decl.valueParameters.size == 1 &&
22782276
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
2279-
} as IrFunction?
2277+
}
22802278
if (realCallee == null) {
22812279
logger.errorElement("Couldn't find a java.lang.Arrays.toString method matching class ${realArrayClass.owner.name}", c)
22822280
} else {
@@ -2300,10 +2298,10 @@ open class KotlinFileExtractor(
23002298
logger.errorElement("Argument to dataClassArrayMemberHashCode not a class", c)
23012299
return
23022300
}
2303-
val realCallee = javaUtilArrays?.declarations?.find { decl ->
2304-
decl is IrFunction && decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
2301+
val realCallee = javaUtilArrays?.declarations?.findSubType<IrFunction> { decl ->
2302+
decl.name.asString() == "hashCode" && decl.valueParameters.size == 1 &&
23052303
decl.valueParameters[0].type.classOrNull?.let { it == realArrayClass } == true
2306-
} as IrFunction?
2304+
}
23072305
if (realCallee == null) {
23082306
logger.errorElement("Couldn't find a java.lang.Arrays.hashCode method matching class ${realArrayClass.owner.name}", c)
23092307
} else {
@@ -4452,7 +4450,7 @@ open class KotlinFileExtractor(
44524450
return
44534451
}
44544452

4455-
val invokeMethod = functionType.classOrNull?.owner?.declarations?.filterIsInstance<IrFunction>()?.find { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
4453+
val invokeMethod = functionType.classOrNull?.owner?.declarations?.findSubType<IrFunction> { it.name.asString() == OperatorNameConventions.INVOKE.asString()}
44564454
if (invokeMethod == null) {
44574455
logger.errorElement("Couldn't find `invoke` method on functional interface.", e)
44584456
return
@@ -4463,7 +4461,7 @@ open class KotlinFileExtractor(
44634461
logger.errorElement("Expected to find SAM conversion to IrClass. Found '${typeOwner.javaClass}' instead. Can't implement SAM interface.", e)
44644462
return
44654463
}
4466-
val samMember = typeOwner.declarations.filterIsInstance<IrFunction>().find { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
4464+
val samMember = typeOwner.declarations.findSubType<IrFunction> { it is IrOverridableMember && it.modality == Modality.ABSTRACT }
44674465
if (samMember == null) {
44684466
logger.errorElement("Couldn't find SAM member in type '${typeOwner.kotlinFqName.asString()}'. Can't implement SAM interface.", e)
44694467
return
@@ -4652,7 +4650,7 @@ open class KotlinFileExtractor(
46524650
val superCallId = tw.getFreshIdLabel<DbSuperconstructorinvocationstmt>()
46534651
tw.writeStmts_superconstructorinvocationstmt(superCallId, constructorBlockId, 0, ids.constructor)
46544652

4655-
val baseConstructor = baseClass.owner.declarations.find { it is IrFunction && it.symbol is IrConstructorSymbol }
4653+
val baseConstructor = baseClass.owner.declarations.findSubType<IrFunction> { it.symbol is IrConstructorSymbol }
46564654
val baseConstructorId = useFunction<DbConstructor>(baseConstructor as IrFunction)
46574655

46584656
tw.writeHasLocation(superCallId, locId)

java/kotlin-extractor/src/main/kotlin/KotlinUsesExtractor.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -326,11 +326,11 @@ open class KotlinUsesExtractor(
326326
if (replacementClass === parentClass)
327327
return f
328328
return globalExtensionState.syntheticToRealFunctionMap.getOrPut(f) {
329-
val result = replacementClass.declarations.find { replacementDecl ->
329+
val result = replacementClass.declarations.findSubType<IrSimpleFunction> { replacementDecl ->
330330
replacementDecl is IrSimpleFunction && replacementDecl.name == f.name && replacementDecl.valueParameters.size == f.valueParameters.size && replacementDecl.valueParameters.zip(f.valueParameters).all {
331331
erase(it.first.type) == erase(it.second.type)
332332
}
333-
} as IrFunction?
333+
}
334334
if (result == null) {
335335
logger.warn("Failed to replace synthetic class function ${f.name}")
336336
} else {
@@ -351,9 +351,9 @@ open class KotlinUsesExtractor(
351351
if (replacementClass === parentClass)
352352
return f
353353
return globalExtensionState.syntheticToRealFieldMap.getOrPut(f) {
354-
val result = replacementClass.declarations.find { replacementDecl ->
355-
replacementDecl is IrField && replacementDecl.name == f.name
356-
} as IrField?
354+
val result = replacementClass.declarations.findSubType<IrField> { replacementDecl ->
355+
replacementDecl.name == f.name
356+
}
357357
if (result == null) {
358358
logger.warn("Failed to replace synthetic class field ${f.name}")
359359
} else {
@@ -1097,7 +1097,7 @@ open class KotlinUsesExtractor(
10971097
return f.returnType
10981098
}
10991099

1100-
val otherKeySet = parentClass.declarations.filterIsInstance<IrFunction>().find { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
1100+
val otherKeySet = parentClass.declarations.findSubType<IrFunction> { it.name.asString() == "keySet" && it.valueParameters.size == 1 }
11011101
?: return f.returnType
11021102

11031103
return otherKeySet.returnType.codeQlWithHasQuestionMark(false)
@@ -1177,8 +1177,7 @@ open class KotlinUsesExtractor(
11771177
getJavaEquivalentClass(parentClass)?.let { javaClass ->
11781178
if (javaClass != parentClass)
11791179
// Look for an exact type match...
1180-
javaClass.declarations.find { decl ->
1181-
decl is IrFunction &&
1180+
javaClass.declarations.findSubType<IrFunction> { decl ->
11821181
decl.name == f.name &&
11831182
decl.valueParameters.size == f.valueParameters.size &&
11841183
// Note matching by classifier not the whole type so that generic arguments are allowed to differ,
@@ -1194,7 +1193,7 @@ open class KotlinUsesExtractor(
11941193
} ?:
11951194
// Or check property accessors:
11961195
if (f.isAccessor) {
1197-
val prop = javaClass.declarations.filterIsInstance<IrProperty>().find { decl ->
1196+
val prop = javaClass.declarations.findSubType<IrProperty> { decl ->
11981197
decl.name == (f.propertyIfAccessor as IrProperty).name
11991198
}
12001199
if (prop?.getter?.name == f.name)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.github.codeql
2+
3+
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
4+
5+
/**
6+
* This behaves the same as Iterable<IrDeclaration>.find, but requires
7+
* that the value found is of the subtype S, and it casts
8+
* the result for you appropriately.
9+
*/
10+
inline fun <reified S: IrDeclaration> Iterable<IrDeclaration>.findSubType(
11+
predicate: (S) -> Boolean
12+
): S? {
13+
return this.find { it is S && predicate(it) } as S?
14+
}
15+

0 commit comments

Comments
 (0)