mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
Add PropertyRefExpr QL class, change extraction to use it, and add tests
This commit is contained in:
@@ -2811,6 +2811,8 @@ open class KotlinFileExtractor(
|
||||
return callId
|
||||
}
|
||||
|
||||
val idPropertyRef = tw.getFreshIdLabel<DbPropertyref>()
|
||||
|
||||
if (getter != null) {
|
||||
val getterParameterTypes = parameters.map { it.type }
|
||||
val getLabels = addFunctionManual(tw.getFreshIdLabel(), "get", getterParameterTypes, getter.owner.returnType, classId, locId)
|
||||
@@ -2820,6 +2822,8 @@ open class KotlinFileExtractor(
|
||||
getter,
|
||||
{ r, c -> extractAccessToTarget(getLabels.methodId, r, c) }
|
||||
)
|
||||
|
||||
tw.writePropertyRefGetBinding(idPropertyRef, getLabels.methodId)
|
||||
}
|
||||
|
||||
if (setter != null) {
|
||||
@@ -2831,27 +2835,24 @@ open class KotlinFileExtractor(
|
||||
setter,
|
||||
{ r, c -> extractAccessToTarget(setLabels.methodId, r, c) }
|
||||
)
|
||||
|
||||
tw.writePropertyRefSetBinding(idPropertyRef, setLabels.methodId)
|
||||
}
|
||||
|
||||
// todo: property ref
|
||||
// Add constructor (property ref) call:
|
||||
val exprParent = parent.expr(propertyReferenceExpr, callable)
|
||||
val idCtorRef = tw.getFreshIdLabel<DbNewexpr>()
|
||||
tw.writeExprs_newexpr(idCtorRef, ids.type.javaResult.id, exprParent.parent, exprParent.idx)
|
||||
tw.writeExprsKotlinType(idCtorRef, ids.type.kotlinResult.id)
|
||||
tw.writeHasLocation(idCtorRef, locId)
|
||||
tw.writeCallableEnclosingExpr(idCtorRef, callable)
|
||||
tw.writeStatementEnclosingExpr(idCtorRef, exprParent.enclosingStmt)
|
||||
tw.writeCallableBinding(idCtorRef, ids.constructor)
|
||||
tw.writeExprs_propertyref(idPropertyRef, ids.type.javaResult.id, exprParent.parent, exprParent.idx)
|
||||
tw.writeExprsKotlinType(idPropertyRef, ids.type.kotlinResult.id)
|
||||
tw.writeHasLocation(idPropertyRef, locId)
|
||||
tw.writeCallableEnclosingExpr(idPropertyRef, callable)
|
||||
tw.writeStatementEnclosingExpr(idPropertyRef, exprParent.enclosingStmt)
|
||||
tw.writeCallableBinding(idPropertyRef, ids.constructor)
|
||||
|
||||
extractTypeAccess(kPropertyType, locId, callable, idCtorRef, -3, exprParent.enclosingStmt)
|
||||
extractTypeAccess(kPropertyType, locId, callable, idPropertyRef, -3, exprParent.enclosingStmt)
|
||||
|
||||
// todo: property ref:
|
||||
//tw.writeMemberRefBinding(idMemberRef, targetCallableId)
|
||||
helper.extractConstructorArguments(callable, idPropertyRef, exprParent.enclosingStmt)
|
||||
|
||||
helper.extractConstructorArguments(callable, idCtorRef, exprParent.enclosingStmt)
|
||||
|
||||
tw.writeIsAnonymClass(classId, idCtorRef)
|
||||
tw.writeIsAnonymClass(classId, idPropertyRef)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -749,6 +749,7 @@ case @expr.kind of
|
||||
| 85 = @unsafecoerceexpr
|
||||
| 86 = @valueeqexpr
|
||||
| 87 = @valueneexpr
|
||||
| 88 = @propertyref
|
||||
;
|
||||
|
||||
/** Holds if this `when` expression was written as an `if` expression. */
|
||||
@@ -764,7 +765,7 @@ when_branch(
|
||||
/** Holds if this `when` branch was written as an `else` branch. */
|
||||
when_branch_else(unique int id: @whenbranch ref);
|
||||
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref
|
||||
@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref
|
||||
|
||||
@annotation = @declannotation | @typeannotation
|
||||
@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess
|
||||
@@ -845,6 +846,16 @@ memberRefBinding(
|
||||
int callable: @callable ref
|
||||
);
|
||||
|
||||
propertyRefGetBinding(
|
||||
unique int id: @expr ref,
|
||||
int getter: @callable ref
|
||||
);
|
||||
|
||||
propertyRefSetBinding(
|
||||
unique int id: @expr ref,
|
||||
int setter: @callable ref
|
||||
);
|
||||
|
||||
@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @class | @interface | @param | @localvar | @typevariable;
|
||||
|
||||
variableBinding(
|
||||
|
||||
@@ -1438,6 +1438,42 @@ class MemberRefExpr extends FunctionalExpr, @memberref {
|
||||
override string getAPrimaryQlClass() { result = "MemberRefExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Property references are represented by their implicit class instance expressions,
|
||||
* which instantiate an anonymous class that overrides the `get` and `set` methods designated by
|
||||
* their functional interface type.
|
||||
*/
|
||||
class PropertyRefExpr extends ClassInstanceExpr, @propertyref {
|
||||
/**
|
||||
* Gets the implicit `get` method corresponding to this property reference expression, if any.
|
||||
*/
|
||||
Method asGetMethod() {
|
||||
result = this.getAnonymousClass().getAMethod() and result.getName() = "get"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implicit `set` method corresponding to this property reference expression, if any.
|
||||
*/
|
||||
Method asSetMethod() {
|
||||
result = this.getAnonymousClass().getAMethod() and result.getName() = "set"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the property getter referenced by this property reference expression, if any.
|
||||
*/
|
||||
Callable getGetterCallable() { propertyRefGetBinding(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the property setter referenced by this property reference expression, if any.
|
||||
*/
|
||||
Callable getSetterCallable() { propertyRefSetBinding(this, result) }
|
||||
|
||||
/** Gets a printable representation of this expression. */
|
||||
override string toString() { result = "...::..." }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "PropertyRefExpr" }
|
||||
}
|
||||
|
||||
/** A conditional expression or a `switch` expression. */
|
||||
class ChooseExpr extends Expr {
|
||||
ChooseExpr() { this instanceof ConditionalExpr or this instanceof SwitchExpr }
|
||||
|
||||
@@ -18,7 +18,7 @@ reflection.kt:
|
||||
# 48| 0: [MethodAccess] println(...)
|
||||
# 48| -1: [TypeAccess] ConsoleKt
|
||||
# 48| 0: [MethodAccess] get(...)
|
||||
# 48| -1: [ClassInstanceExpr] new (...)
|
||||
# 48| -1: [PropertyRefExpr] ...::...
|
||||
# 48| -4: [AnonymousClass] new KProperty1<String,Character>(...) { ... }
|
||||
# 48| 1: [Constructor]
|
||||
# 48| 5: [BlockStmt] { ... }
|
||||
@@ -36,7 +36,7 @@ reflection.kt:
|
||||
# 49| 0: [MethodAccess] println(...)
|
||||
# 49| -1: [TypeAccess] ConsoleKt
|
||||
# 49| 0: [MethodAccess] get(...)
|
||||
# 49| -1: [ClassInstanceExpr] new (...)
|
||||
# 49| -1: [PropertyRefExpr] ...::...
|
||||
# 49| -4: [AnonymousClass] new KProperty0<Character>(...) { ... }
|
||||
# 49| 1: [Constructor]
|
||||
#-----| 4: (Parameters)
|
||||
@@ -90,7 +90,7 @@ reflection.kt:
|
||||
# 6| -1: [VarAccess] ref
|
||||
# 8| 2: [LocalVariableDeclStmt] var ...;
|
||||
# 8| 1: [LocalVariableDeclExpr] x0
|
||||
# 8| 0: [ClassInstanceExpr] new (...)
|
||||
# 8| 0: [PropertyRefExpr] ...::...
|
||||
# 8| -4: [AnonymousClass] new KProperty1<C,Integer>(...) { ... }
|
||||
# 8| 1: [Constructor]
|
||||
# 8| 5: [BlockStmt] { ... }
|
||||
@@ -146,7 +146,7 @@ reflection.kt:
|
||||
# 12| 0: [VarAccess] x0
|
||||
# 13| 7: [LocalVariableDeclStmt] var ...;
|
||||
# 13| 1: [LocalVariableDeclExpr] x5
|
||||
# 13| 0: [ClassInstanceExpr] new (...)
|
||||
# 13| 0: [PropertyRefExpr] ...::...
|
||||
# 13| -4: [AnonymousClass] new KProperty0<Integer>(...) { ... }
|
||||
# 13| 1: [Constructor]
|
||||
#-----| 4: (Parameters)
|
||||
@@ -171,7 +171,7 @@ reflection.kt:
|
||||
# 13| -3: [TypeAccess] C
|
||||
# 15| 8: [LocalVariableDeclStmt] var ...;
|
||||
# 15| 1: [LocalVariableDeclExpr] y0
|
||||
# 15| 0: [ClassInstanceExpr] new (...)
|
||||
# 15| 0: [PropertyRefExpr] ...::...
|
||||
# 15| -4: [AnonymousClass] new KMutableProperty1<C,Integer>(...) { ... }
|
||||
# 15| 1: [Constructor]
|
||||
# 15| 5: [BlockStmt] { ... }
|
||||
@@ -239,7 +239,7 @@ reflection.kt:
|
||||
# 19| 0: [VarAccess] y0
|
||||
# 20| 13: [LocalVariableDeclStmt] var ...;
|
||||
# 20| 1: [LocalVariableDeclExpr] y5
|
||||
# 20| 0: [ClassInstanceExpr] new (...)
|
||||
# 20| 0: [PropertyRefExpr] ...::...
|
||||
# 20| -4: [AnonymousClass] new KMutableProperty0<Integer>(...) { ... }
|
||||
# 20| 1: [Constructor]
|
||||
#-----| 4: (Parameters)
|
||||
|
||||
@@ -34,3 +34,15 @@ invocation
|
||||
| reflection.kt:23:23:23:33 | get(...) | file://<external>/KProperty2.class:0:0:0:0 | get |
|
||||
| reflection.kt:48:30:48:39 | get(...) | file://<external>/KProperty1.class:0:0:0:0 | get |
|
||||
| reflection.kt:49:30:49:34 | get(...) | file://<external>/KProperty0.class:0:0:0:0 | get |
|
||||
functionReferences
|
||||
| reflection.kt:5:49:5:54 | ...::... | reflection.kt:5:49:5:54 | invoke | reflection.kt:27:9:27:33 | m |
|
||||
propertyGetReferences
|
||||
| reflection.kt:8:38:8:42 | ...::... | reflection.kt:8:38:8:42 | get | reflection.kt:8:38:8:42 | get |
|
||||
| reflection.kt:13:35:13:41 | ...::... | reflection.kt:13:35:13:41 | get | reflection.kt:13:35:13:41 | get |
|
||||
| reflection.kt:15:45:15:49 | ...::... | reflection.kt:15:45:15:49 | get | reflection.kt:15:45:15:49 | get |
|
||||
| reflection.kt:20:42:20:48 | ...::... | reflection.kt:20:42:20:48 | get | reflection.kt:20:42:20:48 | get |
|
||||
| reflection.kt:48:13:48:28 | ...::... | reflection.kt:48:13:48:28 | get | reflection.kt:48:13:48:28 | get |
|
||||
| reflection.kt:49:13:49:28 | ...::... | reflection.kt:49:13:49:28 | get | reflection.kt:49:13:49:28 | get |
|
||||
propertySetReferences
|
||||
| reflection.kt:15:45:15:49 | ...::... | reflection.kt:15:45:15:49 | set | reflection.kt:15:45:15:49 | set |
|
||||
| reflection.kt:20:42:20:48 | ...::... | reflection.kt:20:42:20:48 | set | reflection.kt:20:42:20:48 | set |
|
||||
|
||||
@@ -39,3 +39,18 @@ query predicate variableInitializerType(
|
||||
query predicate invocation(Call c, Callable callee) {
|
||||
c.getCallee() = callee and callee.getDeclaringType().getPackage().getName() = "kotlin.reflect"
|
||||
}
|
||||
|
||||
query predicate functionReferences(MemberRefExpr e, Method m, Callable c) {
|
||||
e.asMethod() = m and
|
||||
e.getReferencedCallable() = c
|
||||
}
|
||||
|
||||
query predicate propertyGetReferences(PropertyRefExpr e, Method m, Callable c) {
|
||||
e.asGetMethod() = m and
|
||||
e.getGetterCallable() = c
|
||||
}
|
||||
|
||||
query predicate propertySetReferences(PropertyRefExpr e, Method m, Callable c) {
|
||||
e.asSetMethod() = m and
|
||||
e.getSetterCallable() = c
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user