mirror of
https://github.com/github/codeql.git
synced 2026-04-29 10:45:15 +02:00
Merge pull request #10788 from smowton/smowton/feature/kotlin-default-proxy-getter
Kotlin: Add Callable.getKotlinParameterDefaultsProxy
This commit is contained in:
@@ -294,6 +294,48 @@ class Callable extends StmtParent, Member, @callable {
|
||||
constrs(this, _, result, _, _, _) or
|
||||
methods(this, _, result, _, _, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this callable's Kotlin proxy that supplies default parameter values, if one exists.
|
||||
*
|
||||
* For example, for the Kotlin declaration `fun f(x: Int, y: Int = 0, z: String = "1")`,
|
||||
* this will get the synthetic proxy method that fills in the default values for `y` and `z`
|
||||
* if not supplied, and to which the Kotlin extractor dispatches calls to `f` that are missing
|
||||
* one or more parameter value. Similarly, constructors with one or more default parameter values
|
||||
* have a corresponding constructor that fills in default values.
|
||||
*/
|
||||
Callable getKotlinParameterDefaultsProxy() {
|
||||
this.getDeclaringType() = result.getDeclaringType() and
|
||||
exists(int proxyNParams, int extraLeadingParams, RefType lastParamType |
|
||||
proxyNParams = result.getNumberOfParameters() and
|
||||
extraLeadingParams = (proxyNParams - this.getNumberOfParameters()) - 2 and
|
||||
extraLeadingParams >= 0 and
|
||||
result.getParameterType(proxyNParams - 1) = lastParamType and
|
||||
result.getParameterType(proxyNParams - 2).(PrimitiveType).hasName("int") and
|
||||
(
|
||||
this instanceof Constructor and
|
||||
result instanceof Constructor and
|
||||
extraLeadingParams = 0 and
|
||||
lastParamType.hasQualifiedName("kotlin.jvm.internal", "DefaultConstructorMarker")
|
||||
or
|
||||
this instanceof Method and
|
||||
result instanceof Method and
|
||||
this.getName() + "$default" = result.getName() and
|
||||
extraLeadingParams <= 2 and
|
||||
lastParamType instanceof TypeObject
|
||||
)
|
||||
|
|
||||
forall(int paramIdx | paramIdx in [extraLeadingParams .. proxyNParams - 3] |
|
||||
this.getParameterType(paramIdx - extraLeadingParams).getErasure() =
|
||||
eraseRaw(result.getParameterType(paramIdx))
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the erasure of `t1` if it is a raw type, or `t1` itself otherwise. */
|
||||
private Type eraseRaw(Type t1) {
|
||||
if t1 instanceof RawType then result = t1.getErasure() else result = t1
|
||||
}
|
||||
|
||||
/** Holds if method `m1` overrides method `m2`. */
|
||||
|
||||
@@ -1221,3 +1221,82 @@ test.kt:
|
||||
# 173| 5: [BlockStmt] { ... }
|
||||
# 173| 0: [ReturnStmt] return ...
|
||||
# 173| 0: [VarAccess] t
|
||||
# 177| 17: [Class] TestOverloadsWithDefaults
|
||||
# 177| 1: [Constructor] TestOverloadsWithDefaults
|
||||
# 177| 5: [BlockStmt] { ... }
|
||||
# 177| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 177| 1: [BlockStmt] { ... }
|
||||
# 179| 2: [Method] f
|
||||
# 179| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 179| 0: [Parameter] x
|
||||
# 179| 0: [TypeAccess] int
|
||||
# 179| 1: [Parameter] y
|
||||
# 179| 0: [TypeAccess] String
|
||||
# 179| 5: [BlockStmt] { ... }
|
||||
# 179| 3: [Method] f$default
|
||||
# 179| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 179| 0: [Parameter] p0
|
||||
# 179| 0: [TypeAccess] TestOverloadsWithDefaults
|
||||
# 179| 1: [Parameter] p1
|
||||
# 179| 0: [TypeAccess] int
|
||||
# 179| 2: [Parameter] p2
|
||||
# 179| 0: [TypeAccess] String
|
||||
# 179| 3: [Parameter] p3
|
||||
# 179| 0: [TypeAccess] int
|
||||
# 179| 4: [Parameter] p4
|
||||
# 179| 0: [TypeAccess] Object
|
||||
# 179| 5: [BlockStmt] { ... }
|
||||
# 179| 0: [IfStmt] if (...)
|
||||
# 179| 0: [EQExpr] ... == ...
|
||||
# 179| 0: [AndBitwiseExpr] ... & ...
|
||||
# 179| 0: [IntegerLiteral] 2
|
||||
# 179| 1: [VarAccess] p3
|
||||
# 179| 1: [IntegerLiteral] 0
|
||||
# 179| 1: [ExprStmt] <Expr>;
|
||||
# 179| 0: [AssignExpr] ...=...
|
||||
# 179| 0: [VarAccess] p2
|
||||
# 179| 1: [StringLiteral] Hello world
|
||||
# 179| 1: [ReturnStmt] return ...
|
||||
# 179| 0: [MethodAccess] f(...)
|
||||
# 179| -1: [VarAccess] p0
|
||||
# 179| 0: [VarAccess] p1
|
||||
# 179| 1: [VarAccess] p2
|
||||
# 180| 4: [Method] f
|
||||
# 180| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 180| 0: [Parameter] z
|
||||
# 180| 0: [TypeAccess] String
|
||||
# 180| 1: [Parameter] w
|
||||
# 180| 0: [TypeAccess] int
|
||||
# 180| 5: [BlockStmt] { ... }
|
||||
# 180| 5: [Method] f$default
|
||||
# 180| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 180| 0: [Parameter] p0
|
||||
# 180| 0: [TypeAccess] TestOverloadsWithDefaults
|
||||
# 180| 1: [Parameter] p1
|
||||
# 180| 0: [TypeAccess] String
|
||||
# 180| 2: [Parameter] p2
|
||||
# 180| 0: [TypeAccess] int
|
||||
# 180| 3: [Parameter] p3
|
||||
# 180| 0: [TypeAccess] int
|
||||
# 180| 4: [Parameter] p4
|
||||
# 180| 0: [TypeAccess] Object
|
||||
# 180| 5: [BlockStmt] { ... }
|
||||
# 180| 0: [IfStmt] if (...)
|
||||
# 180| 0: [EQExpr] ... == ...
|
||||
# 180| 0: [AndBitwiseExpr] ... & ...
|
||||
# 180| 0: [IntegerLiteral] 2
|
||||
# 180| 1: [VarAccess] p3
|
||||
# 180| 1: [IntegerLiteral] 0
|
||||
# 180| 1: [ExprStmt] <Expr>;
|
||||
# 180| 0: [AssignExpr] ...=...
|
||||
# 180| 0: [VarAccess] p2
|
||||
# 180| 1: [IntegerLiteral] 0
|
||||
# 180| 1: [ReturnStmt] return ...
|
||||
# 180| 0: [MethodAccess] f(...)
|
||||
# 180| -1: [VarAccess] p0
|
||||
# 180| 0: [VarAccess] p1
|
||||
# 180| 1: [VarAccess] p2
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
| test.kt:5:3:7:3 | f | test.kt:5:3:7:3 | f$default |
|
||||
| test.kt:34:14:36:3 | f | test.kt:34:14:36:3 | f$default |
|
||||
| test.kt:68:1:80:1 | TestConstructor | test.kt:68:1:80:1 | TestConstructor |
|
||||
| test.kt:86:5:88:5 | f | test.kt:86:5:88:5 | f$default |
|
||||
| test.kt:106:7:108:7 | f | test.kt:106:7:108:7 | f$default |
|
||||
| test.kt:124:3:126:3 | f | test.kt:124:3:126:3 | f$default |
|
||||
| test.kt:135:3:135:43 | testReturn | test.kt:135:3:135:43 | testReturn$default |
|
||||
| test.kt:145:3:147:3 | f | test.kt:145:3:147:3 | f$default |
|
||||
| test.kt:158:3:158:35 | f | test.kt:158:3:158:35 | f$default |
|
||||
| test.kt:159:12:159:44 | g$main | test.kt:159:12:159:44 | g$main$default |
|
||||
| test.kt:160:13:160:45 | h | test.kt:160:13:160:45 | h$default |
|
||||
| test.kt:161:11:161:43 | i | test.kt:161:11:161:43 | i$default |
|
||||
| test.kt:171:3:171:97 | f | test.kt:171:3:171:97 | f$default |
|
||||
| test.kt:179:3:179:46 | f | test.kt:179:3:179:46 | f$default |
|
||||
| test.kt:180:3:180:34 | f | test.kt:180:3:180:34 | f$default |
|
||||
@@ -0,0 +1,7 @@
|
||||
import java
|
||||
|
||||
from Callable realMethod, Callable defaultsProxy
|
||||
where
|
||||
defaultsProxy = realMethod.getKotlinParameterDefaultsProxy() and
|
||||
realMethod.fromSource()
|
||||
select realMethod, defaultsProxy
|
||||
@@ -173,3 +173,10 @@ class TestGenericUsedWithinDefaultValue<T> {
|
||||
fun ident(t: T) = t
|
||||
|
||||
}
|
||||
|
||||
class TestOverloadsWithDefaults {
|
||||
|
||||
fun f(x: Int, y: String = "Hello world") { }
|
||||
fun f(z: String, w: Int = 0) { }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user