Skip to content

Commit 4f5c06f

Browse files
authored
Merge pull request #10169 from tamasvajk/kotlin-array-iterator
Kotlin: fix array iterator extraction
2 parents 06afe9c + 15305fd commit 4f5c06f

File tree

5 files changed

+55
-5
lines changed

5 files changed

+55
-5
lines changed

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

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,11 +1600,13 @@ open class KotlinFileExtractor(
16001600
return result
16011601
}
16021602

1603-
private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, warnAgainstElement: IrElement): IrFunction? {
1603+
private fun findTopLevelFunctionOrWarn(functionFilter: String, type: String, parameterTypes: Array<String>, warnAgainstElement: IrElement): IrFunction? {
16041604

16051605
val fn = pluginContext.referenceFunctions(FqName(functionFilter))
1606-
.firstOrNull { it.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type }
1607-
?.owner
1606+
.firstOrNull { fnSymbol ->
1607+
fnSymbol.owner.parentClassOrNull?.fqNameWhenAvailable?.asString() == type &&
1608+
fnSymbol.owner.valueParameters.map { it.type.classFqName?.asString() }.toTypedArray() contentEquals parameterTypes
1609+
}?.owner
16081610

16091611
if (fn != null) {
16101612
if (fn.parentClassOrNull != null) {
@@ -1754,6 +1756,12 @@ open class KotlinFileExtractor(
17541756
else -> false
17551757
}
17561758

1759+
private fun isGenericArrayType(typeName: String) =
1760+
when(typeName) {
1761+
"Array" -> true
1762+
else -> false
1763+
}
1764+
17571765
private fun extractCall(c: IrCall, callable: Label<out DbCallable>, stmtExprParent: StmtExprParent) {
17581766
with("call", c) {
17591767
val target = tryReplaceSyntheticFunction(c.symbol.owner)
@@ -2175,8 +2183,20 @@ open class KotlinFileExtractor(
21752183
extractRawMethodAccess(getter, c, callable, parent, idx, enclosingStmt, listOf(), null, ext, typeArguments)
21762184
}
21772185
}
2178-
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") && c.origin == IrStatementOrigin.FOR_LOOP_ITERATOR -> {
2179-
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", "kotlin.jvm.internal.ArrayIteratorKt", c)?.let { iteratorFn ->
2186+
isFunction(target, "kotlin", "(some array type)", { isArrayType(it) }, "iterator") -> {
2187+
val parentClass = target.parent
2188+
if (parentClass !is IrClass) {
2189+
logger.errorElement("Iterator parent is not a class", c)
2190+
return
2191+
}
2192+
2193+
var typeFilter = if (isGenericArrayType(parentClass.name.asString())) {
2194+
"kotlin.jvm.internal.ArrayIteratorKt"
2195+
} else {
2196+
"kotlin.jvm.internal.ArrayIteratorsKt"
2197+
}
2198+
2199+
findTopLevelFunctionOrWarn("kotlin.jvm.internal.iterator", typeFilter, arrayOf(parentClass.kotlinFqName.asString()), c)?.let { iteratorFn ->
21802200
val dispatchReceiver = c.dispatchReceiver
21812201
if (dispatchReceiver == null) {
21822202
logger.errorElement("No dispatch receiver found for array iterator call", c)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
| arrayIterators.kt:6:15:6:15 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt |
2+
| arrayIterators.kt:7:15:7:15 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt |
3+
| arrayIterators.kt:8:15:8:15 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |
4+
| arrayIterators.kt:10:16:10:25 | iterator(...) | iterator(java.lang.Object[]) | kotlin.jvm.internal.ArrayIteratorKt |
5+
| arrayIterators.kt:11:16:11:25 | iterator(...) | iterator(int[]) | kotlin.jvm.internal.ArrayIteratorsKt |
6+
| arrayIterators.kt:12:16:12:25 | iterator(...) | iterator(boolean[]) | kotlin.jvm.internal.ArrayIteratorsKt |
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun test(
2+
a: Array<Int>,
3+
b: IntArray,
4+
c: BooleanArray) {
5+
6+
for (i in a) { }
7+
for (i in b) { }
8+
for (i in c) { }
9+
10+
val i1 = a.iterator()
11+
val i2 = b.iterator()
12+
val i3 = c.iterator()
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import java
2+
3+
query predicate iterator(MethodAccess ma, string mn, string t) {
4+
exists(Method m |
5+
ma.getMethod() = m and
6+
m.getName() = "iterator" and
7+
mn = m.getSignature() and
8+
t = ma.getMethod().getDeclaringType().getQualifiedName()
9+
)
10+
}

java/ql/test/kotlin/library-tests/arrays/test.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ sourceSignatures
1818
| arrayCreations.kt:27:24:27:38 | invoke | invoke(int) |
1919
| arrayGetsSets.kt:1:1:22:1 | arrayGetSet | arrayGetSet(int[],short[],byte[],long[],float[],double[],boolean[],char[],java.lang.Object[]) |
2020
| arrayGetsSets.kt:24:1:41:1 | arrayGetSetInPlace | arrayGetSetInPlace(int[],long[],float[],double[]) |
21+
| arrayIterators.kt:1:1:13:1 | test | test(java.lang.Integer[],int[],boolean[]) |
2122
| primitiveArrays.kt:3:1:7:1 | Test | Test() |
2223
| primitiveArrays.kt:5:3:5:123 | test | test(java.lang.Integer[],java.lang.Integer[],int[],java.lang.Integer[][],java.lang.Integer[][],int[][]) |
2324
#select

0 commit comments

Comments
 (0)