Skip to content

Commit 336e48c

Browse files
committed
Python: ObjectAPI to ValueAPI: IncorrectlySpecifiedOverriddenMethod: Adds preliminary modernization
1 parent 9f18a15 commit 336e48c

File tree

3 files changed

+39
-15
lines changed

3 files changed

+39
-15
lines changed

python/ql/src/Functions/IncorrectlySpecifiedOverriddenMethod.ql

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@
1313
import python
1414
import Expressions.CallArgs
1515

16-
from Call call, FunctionObject func, FunctionObject overriding, string problem
16+
from Call call, FunctionValue func, FunctionValue overriding, string problem
1717
where
1818
not func.getName() = "__init__" and
1919
overriding.overrides(func) and
2020
call = overriding.getAMethodCall().getNode() and
21-
correct_args_if_called_as_method_objectapi(call, overriding) and
21+
correct_args_if_called_as_method(call, overriding) and
2222
(
23-
arg_count_objectapi(call) + 1 < func.minParameters() and problem = "too few arguments"
23+
arg_count(call) + 1 < func.minParameters() and problem = "too few arguments"
2424
or
25-
arg_count_objectapi(call) >= func.maxParameters() and problem = "too many arguments"
25+
arg_count(call) >= func.maxParameters() and problem = "too many arguments"
2626
or
2727
exists(string name |
2828
call.getAKeyword().getArg() = name and
29-
overriding.getFunction().getAnArg().(Name).getId() = name and
30-
not func.getFunction().getAnArg().(Name).getId() = name and
29+
overriding.getScope().getAnArg().(Name).getId() = name and
30+
not func.getScope().getAnArg().(Name).getId() = name and
3131
problem = "an argument named '" + name + "'"
3232
)
3333
)

python/ql/src/semmle/python/objects/ObjectAPI.qll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,9 @@ class ClassValue extends Value {
573573
abstract class FunctionValue extends CallableValue {
574574
abstract string getQualifiedName();
575575

576+
/** Gets a longer, more descriptive version of toString() */
577+
abstract string descriptiveString();
578+
576579
/** Gets the minimum number of parameters that can be correctly passed to this function */
577580
abstract int minParameters();
578581

@@ -605,6 +608,14 @@ abstract class FunctionValue extends CallableValue {
605608
)
606609
}
607610

611+
/** Gets a call-site from where this function is called as a method */
612+
CallNode getAMethodCall() {
613+
exists(BoundMethodObjectInternal bm |
614+
result.getFunction().pointsTo() = bm and
615+
bm.getFunction() = this
616+
)
617+
}
618+
608619
/** Gets a class that this function may return */
609620
abstract ClassValue getAnInferredReturnType();
610621
}
@@ -617,6 +628,15 @@ class PythonFunctionValue extends FunctionValue {
617628
result = this.(PythonFunctionObjectInternal).getScope().getQualifiedName()
618629
}
619630

631+
override string descriptiveString() {
632+
if this.getScope().isMethod()
633+
then
634+
exists(Class cls | this.getScope().getScope() = cls |
635+
result = "method " + this.getQualifiedName()
636+
)
637+
else result = "function " + this.getQualifiedName()
638+
}
639+
620640
override int minParameters() {
621641
exists(Function f |
622642
f = this.getScope() and
@@ -650,6 +670,8 @@ class BuiltinFunctionValue extends FunctionValue {
650670

651671
override string getQualifiedName() { result = this.(BuiltinFunctionObjectInternal).getName() }
652672

673+
override string descriptiveString() { result = "builtin-function " + this.getName() }
674+
653675
override int minParameters() { none() }
654676

655677
override int maxParameters() { none() }
@@ -674,6 +696,8 @@ class BuiltinMethodValue extends FunctionValue {
674696
)
675697
}
676698

699+
override string descriptiveString() { result = "builtin-method " + this.getQualifiedName() }
700+
677701
override int minParameters() { none() }
678702

679703
override int maxParameters() { none() }
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 |
2-
| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 |
3-
| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:16:9:16:21 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 |
4-
| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 |
5-
| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:35:9:35:21 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 |
6-
| test.py:5:5:5:20 | Function meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function meth1 | method Derived.meth1 |
7-
| test.py:8:5:8:26 | Function meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:17:9:17:20 | Attribute() | call | test.py:27:5:27:20 | Function meth2 | method Derived.meth2 |
8-
| test.py:8:5:8:26 | Function meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:36:9:36:20 | Attribute() | call | test.py:27:5:27:20 | Function meth2 | method Derived.meth2 |
9-
| test.py:64:5:64:19 | Function meth | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:78:1:78:12 | Attribute() | call | test.py:74:5:74:24 | Function meth | method Correct2.meth |
1+
| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 |
2+
| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed an argument named 'spam'. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 |
3+
| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:16:9:16:21 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 |
4+
| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:19:9:19:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 |
5+
| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:35:9:35:21 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 |
6+
| test.py:5:5:5:20 | Function Base.meth1 | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:38:9:38:31 | Attribute() | call | test.py:24:5:24:26 | Function Derived.meth1 | method Derived.meth1 |
7+
| test.py:8:5:8:26 | Function Base.meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:17:9:17:20 | Attribute() | call | test.py:27:5:27:20 | Function Derived.meth2 | method Derived.meth2 |
8+
| test.py:8:5:8:26 | Function Base.meth2 | Overridden method signature does not match $@, where it is passed too few arguments. Overriding method $@ matches the call. | test.py:36:9:36:20 | Attribute() | call | test.py:27:5:27:20 | Function Derived.meth2 | method Derived.meth2 |
9+
| test.py:64:5:64:19 | Function BlameBase.meth | Overridden method signature does not match $@, where it is passed too many arguments. Overriding method $@ matches the call. | test.py:78:1:78:12 | Attribute() | call | test.py:74:5:74:24 | Function Correct2.meth | method Correct2.meth |

0 commit comments

Comments
 (0)