Python: Magic subscript and format

(this in preparation for addressing reviews)
This commit is contained in:
Rasmus Lerchedahl Petersen
2020-08-18 12:56:15 +02:00
parent ca7c045d31
commit bbf925fcc4
2 changed files with 63 additions and 6 deletions

View File

@@ -22,8 +22,10 @@ module MagicMethod {
/** Gets the controlflow node that would be passed as the specified argument. */
abstract ControlFlowNode getArg(int n);
/** Gets the control flow node corresponding to the instance
* that would define the magic method. */
/**
* Gets the control flow node corresponding to the instance
* that would define the magic method.
*/
ControlFlowNode getSelf() { result = this.getArg(0) }
}
@@ -47,11 +49,9 @@ module MagicMethod {
class MagicBinOp extends MagicMethod::Potential, BinaryExprNode {
Operator operator;
MagicBinOp() { this.getOp() = operator}
MagicBinOp() { this.getOp() = operator }
override string getMagicMethodName() {
result = operator.getSpecialMethodName()
}
override string getMagicMethodName() { result = operator.getSpecialMethodName() }
override ControlFlowNode getArg(int n) {
n = 0 and result = this.getLeft()
@@ -59,3 +59,53 @@ class MagicBinOp extends MagicMethod::Potential, BinaryExprNode {
n = 1 and result = this.getRight()
}
}
/** A subscript expression node that might correspond to a magic method call. */
abstract class MagicSubscript extends MagicMethod::Potential, SubscriptNode {
override ControlFlowNode getArg(int n) {
n = 0 and result = this.getObject()
or
n = 1 and result = this.getIndex()
}
}
/** A subscript expression node that might correspond to a call to __getitem__. */
class MagicGetItem extends MagicSubscript {
MagicGetItem() { this.isLoad() }
override string getMagicMethodName() { result = "__getitem__" }
}
/** A subscript expression node that might correspond to a call to __setitem__. */
class MagicSetItem extends MagicSubscript {
MagicSetItem() { this.isStore() }
override string getMagicMethodName() { result = "__setitem__" }
override ControlFlowNode getArg(int n) {
n = 0 and result = this.getObject()
or
n = 1 and result = this.getIndex()
or
n = 2 and result = this.getValueNode()
}
private ControlFlowNode getValueNode() {
exists(AssignStmt a |
a.getATarget() = this.getNode() and
result.getNode() = a.getValue()
)
or
exists(AugAssign a |
a.getTarget() = this.getNode() and
result.getNode() = a.getValue()
)
}
}
/** A subscript expression node that might correspond to a call to __delitem__. */
class MagicDelItem extends MagicSubscript {
MagicDelItem() { this.isDelete() }
override string getMagicMethodName() { result = "__delitem__" }
}

View File

@@ -3,6 +3,13 @@
| classes.py:178:7:178:28 | ControlFlowNode for frozenset() | classes.py:178:7:178:28 | ControlFlowNode for frozenset() |
| classes.py:182:7:182:26 | ControlFlowNode for dict() | classes.py:182:7:182:26 | ControlFlowNode for dict() |
| classes.py:303:28:303:51 | ControlFlowNode for dict() | classes.py:303:28:303:51 | ControlFlowNode for dict() |
| classes.py:428:3:428:14 | ControlFlowNode for with_getitem | classes.py:422:19:422:22 | SSA variable self |
| classes.py:428:16:428:16 | ControlFlowNode for IntegerLiteral | classes.py:422:25:422:27 | SSA variable key |
| classes.py:438:3:438:14 | ControlFlowNode for with_setitem | classes.py:433:19:433:22 | SSA variable self |
| classes.py:438:16:438:16 | ControlFlowNode for IntegerLiteral | classes.py:433:25:433:27 | SSA variable key |
| classes.py:438:21:438:22 | ControlFlowNode for Str | classes.py:433:30:433:34 | SSA variable value |
| classes.py:448:7:448:18 | ControlFlowNode for with_delitem | classes.py:443:19:443:22 | SSA variable self |
| classes.py:448:20:448:20 | ControlFlowNode for IntegerLiteral | classes.py:443:25:443:27 | SSA variable key |
| classes.py:466:12:466:24 | ControlFlowNode for Attribute() | classes.py:466:12:466:24 | ControlFlowNode for Attribute() |
| classes.py:505:3:505:10 | ControlFlowNode for with_add | classes.py:499:15:499:18 | SSA variable self |
| classes.py:505:14:505:21 | ControlFlowNode for with_add | classes.py:499:21:499:25 | SSA variable other |