Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4d40815

Browse files
smowtonigfoo
authored andcommitted
When extracting a call to an inherited method, substitute the callee's type parameters appropriately.
1 parent 8c9c37c commit 4d40815

8 files changed

Lines changed: 51 additions & 28 deletions

File tree

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import com.github.codeql.comments.CommentExtractor
44
import com.github.codeql.utils.TypeSubstitution
55
import com.github.codeql.utils.versions.functionN
66
import com.github.codeql.utils.substituteTypeAndArguments
7+
import com.github.codeql.utils.substituteTypeArguments
78
import com.github.codeql.utils.toRawType
89
import com.semmle.extractor.java.OdasaOutput
910
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
11+
import org.jetbrains.kotlin.backend.common.pop
1012
import org.jetbrains.kotlin.builtins.functions.BuiltInFunctionArity
1113
import org.jetbrains.kotlin.descriptors.*
1214
import org.jetbrains.kotlin.descriptors.java.JavaVisibilities
@@ -927,6 +929,42 @@ open class KotlinFileExtractor(
927929
}
928930
}
929931

932+
private fun getDeclaringTypeArguments(callTarget: IrFunction, receiverType: IrSimpleType): List<IrTypeArgument> {
933+
val declaringType = callTarget.parentAsClass
934+
val receiverClass = receiverType.classifier.owner as? IrClass ?: return listOf()
935+
val ancestorTypes = ArrayList<IrSimpleType>()
936+
937+
// Populate ancestorTypes with the path from receiverType's class to its ancestor, callTarget's declaring type.
938+
fun walkFrom(c: IrClass): Boolean {
939+
if(declaringType == c)
940+
return true
941+
else {
942+
c.superTypes.forEach {
943+
val ancestorClass = (it as? IrSimpleType)?.classifier?.owner as? IrClass ?: return false
944+
ancestorTypes.add(it)
945+
if (walkFrom(ancestorClass))
946+
return true
947+
else
948+
ancestorTypes.pop()
949+
}
950+
return false
951+
}
952+
}
953+
954+
// If a path was found, repeatedly substitute types to get the corresponding specialisation of that ancestor.
955+
return if (!walkFrom(receiverClass)) {
956+
logger.warnElement(Severity.ErrorSevere, "Failed to find a class declaring ${callTarget.name}", callTarget)
957+
listOf()
958+
} else {
959+
var subbedType = receiverType
960+
ancestorTypes.forEach {
961+
val thisClass = subbedType.classifier.owner as IrClass
962+
subbedType = it.substituteTypeArguments(thisClass.typeParameters, subbedType.arguments) as IrSimpleType
963+
}
964+
subbedType.arguments
965+
}
966+
}
967+
930968
fun extractCall(c: IrCall, callable: Label<out DbCallable>, parent: Label<out DbExprparent>, idx: Int, enclosingStmt: Label<out DbStmt>) {
931969
with("call", c) {
932970
fun isFunction(pkgName: String, className: String, fName: String, hasQuestionMark: Boolean = false): Boolean {
@@ -1028,7 +1066,7 @@ open class KotlinFileExtractor(
10281066
val drType = dr?.type
10291067
val methodId =
10301068
if (drType != null && extractClassTypeArguments && drType is IrSimpleType && !isUnspecialised(drType))
1031-
useFunction<DbCallable>(callTarget, drType.arguments)
1069+
useFunction<DbCallable>(callTarget, getDeclaringTypeArguments(callTarget, drType))
10321070
else
10331071
useFunction<DbCallable>(callTarget)
10341072

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
| A.java:4:19:4:29 | someFun(...) | OC$C.class:0:0:0:0 | someFun |
1+
| A.java:4:19:4:29 | someFun(...) | OC$C.class:0:0:0:0 | someFun | OC$C.class:0:0:0:0 | C<D1,D2,E1,E2> | OC.class:0:0:0:0 | OC<F1,F2> |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import java
22

33
from MethodAccess c
4-
select c, c.getCallee()
4+
select c, c.getCallee(), c.getCallee().getDeclaringType(), c.getCallee().getDeclaringType().(NestedType).getEnclosingType()

java/ql/test/kotlin/library-tests/fake_overrides/all_kotlin/A.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11

22
class A {
3-
fun foo(z: OB.B<E1, E2>) {
3+
fun foo(z: OB<G1, G2>.B<E1, E2>) {
44
val foo = z.someFun()
55
}
66
}
77

88
class OB<S1, S2>: OC<F1, F2>() {
9-
public class B<T1, T2>: OC.C<D1, D2, T1, T2>() {
9+
public inner class B<T1, T2>: OC<F1, F2>.C<D1, D2, T1, T2>() {
1010
}
1111
}
1212

1313
open class OC<U1, U2> {
14-
open class C<X1, X2, Y1, Y2> {
14+
open inner class C<X1, X2, Y1, Y2> {
1515
fun someFun(): Int {
1616
return 5
1717
}
Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
| A.kt:2:1:6:1 | <obinit>(...) | A.kt:2:1:6:1 | <obinit> |
2-
| A.kt:4:21:4:29 | someFun(...) | A.kt:9:9:10:2 | someFun |
3-
| A.kt:8:1:11:1 | <obinit>(...) | A.kt:8:1:11:1 | <obinit> |
4-
| A.kt:9:2:10:2 | <obinit>(...) | A.kt:9:2:10:2 | <obinit> |
5-
| A.kt:13:1:19:1 | <obinit>(...) | A.kt:13:1:19:1 | <obinit> |
6-
| A.kt:14:2:18:2 | <obinit>(...) | A.kt:14:2:18:2 | <obinit> |
7-
| A.kt:21:1:21:11 | <obinit>(...) | A.kt:21:1:21:11 | <obinit> |
8-
| A.kt:22:1:22:11 | <obinit>(...) | A.kt:22:1:22:11 | <obinit> |
9-
| A.kt:24:1:24:11 | <obinit>(...) | A.kt:24:1:24:11 | <obinit> |
10-
| A.kt:25:1:25:11 | <obinit>(...) | A.kt:25:1:25:11 | <obinit> |
11-
| A.kt:27:1:27:11 | <obinit>(...) | A.kt:27:1:27:11 | <obinit> |
12-
| A.kt:28:1:28:11 | <obinit>(...) | A.kt:28:1:28:11 | <obinit> |
13-
| A.kt:30:1:30:11 | <obinit>(...) | A.kt:30:1:30:11 | <obinit> |
14-
| A.kt:31:1:31:11 | <obinit>(...) | A.kt:31:1:31:11 | <obinit> |
1+
| A.kt:4:21:4:29 | someFun(...) | A.kt:15:6:17:6 | someFun | A.kt:14:2:18:2 | C<D1,D2,E1,E2> | A.kt:13:1:19:1 | OC<F1,F2> |
2+
| A.kt:9:2:10:2 | <obinit>(...) | A.kt:9:2:10:2 | <obinit> | A.kt:9:2:10:2 | B | A.kt:8:1:11:1 | OB |
3+
| A.kt:14:2:18:2 | <obinit>(...) | A.kt:14:2:18:2 | <obinit> | A.kt:14:2:18:2 | C | A.kt:13:1:19:1 | OC |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import java
22

33
from MethodAccess c
4-
select c, c.getCallee()
4+
select c, c.getCallee(), c.getCallee().getDeclaringType(), c.getCallee().getDeclaringType().(NestedType).getEnclosingType()
Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
1-
| A.kt:2:1:6:1 | <obinit>(...) | A.kt:2:1:6:1 | <obinit> |
2-
| A.kt:4:21:4:29 | someFun(...) | file:///!unknown-binary-location/OB$B.class:0:0:0:0 | someFun |
3-
| A.kt:8:1:8:11 | <obinit>(...) | A.kt:8:1:8:11 | <obinit> |
4-
| A.kt:9:1:9:11 | <obinit>(...) | A.kt:9:1:9:11 | <obinit> |
5-
| A.kt:11:1:11:11 | <obinit>(...) | A.kt:11:1:11:11 | <obinit> |
6-
| A.kt:12:1:12:11 | <obinit>(...) | A.kt:12:1:12:11 | <obinit> |
1+
| A.kt:4:21:4:29 | someFun(...) | file:///!unknown-binary-location/OC$C.class:0:0:0:0 | someFun | file:///!unknown-binary-location/OC$C.class:0:0:0:0 | C<D1,D2,E1,E2> | OC.class:0:0:0:0 | OC<F1,F2> |
2+
| A.kt:4:21:4:29 | someFun(...) | file:///!unknown-binary-location/OC$C.class:0:0:0:0 | someFun | file:///!unknown-binary-location/OC$C.class:0:0:0:0 | C<D1,D2,E1,E2> | file:///!unknown-binary-location/OC.class:0:0:0:0 | OC<F1,F2> |
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import java
22

33
from MethodAccess c
4-
select c, c.getCallee()
4+
select c, c.getCallee(), c.getCallee().getDeclaringType(), c.getCallee().getDeclaringType().(NestedType).getEnclosingType()

0 commit comments

Comments
 (0)