|
1 | 1 | /** |
2 | | - * @name First argument of a method is not named 'self' |
3 | | - * @description Using an alternative name for the first argument of an instance method makes |
4 | | - * code more difficult to read; PEP8 states that the first argument to instance |
| 2 | + * @name First parameter of a method is not named 'self' |
| 3 | + * @description Using an alternative name for the first parameter of an instance method makes |
| 4 | + * code more difficult to read; PEP8 states that the first parameter to instance |
5 | 5 | * methods should be 'self'. |
6 | 6 | * @kind problem |
7 | 7 | * @tags maintainability |
|
16 | 16 | import python |
17 | 17 | import semmle.python.libraries.Zope |
18 | 18 |
|
19 | | -predicate first_arg_self(Function f) { |
20 | | - f.getArgName(0) = "self" |
| 19 | +predicate is_type_method(FunctionValue fv) { |
| 20 | + exists(ClassValue c | c.declaredAttribute(_) = fv and c.getASuperType() = ClassValue::type()) |
21 | 21 | } |
22 | 22 |
|
23 | | -predicate is_type_method(FunctionObject f) { |
24 | | - exists(ClassObject c | c.lookupAttribute(_) = f and c.getASuperType() = theTypeType()) |
| 23 | +predicate used_in_defining_scope(FunctionValue fv) { |
| 24 | + exists(Call c | c.getScope() = fv.getScope().getScope() and c.getFunc().pointsTo(fv)) |
25 | 25 | } |
26 | 26 |
|
27 | | -predicate used_in_defining_scope(FunctionObject f) { |
28 | | - exists(Call c | |
29 | | - c.getScope() = f.getFunction().getScope() and |
30 | | - c.getFunc().refersTo(f) |
31 | | - ) |
32 | | -} |
33 | | - |
34 | | -from Function f, PyFunctionObject func, string message |
| 27 | +from Function f, FunctionValue fv, string message |
35 | 28 | where |
36 | | -exists(ClassObject cls, string name | |
37 | | - cls.declaredAttribute(name) = func and cls.isNewStyle() and |
38 | | - not name = "__new__" and |
39 | | - not name = "__metaclass__" and |
40 | | - /* declared in scope */ |
41 | | - f.getScope() = cls.getPyClass() |
42 | | -) and |
43 | | -not first_arg_self(f) and not is_type_method(func) and |
44 | | -func.getFunction() = f and not f.getName() = "lambda" and |
45 | | -not used_in_defining_scope(func) and |
46 | | -( |
47 | | - if exists(f.getArgName(0)) then |
48 | | - message = "Normal methods should have 'self', rather than '" + f.getArgName(0) + "', as their first parameter." |
49 | | - else |
50 | | - message = "Normal methods should have at least one parameter (the first of which should be 'self')." and not f.hasVarArg() |
51 | | -) and |
52 | | -not func instanceof ZopeInterfaceMethod |
53 | | - |
| 29 | + exists(ClassValue cls, string name | |
| 30 | + cls.declaredAttribute(name) = fv and |
| 31 | + cls.isNewStyle() and |
| 32 | + not name = "__new__" and |
| 33 | + not name = "__metaclass__" and |
| 34 | + /* declared in scope */ |
| 35 | + f.getScope() = cls.getScope() |
| 36 | + ) and |
| 37 | + not f.getArgName(0) = "self" and |
| 38 | + not is_type_method(fv) and |
| 39 | + fv.getScope() = f and |
| 40 | + not f.getName() = "lambda" and |
| 41 | + not used_in_defining_scope(fv) and |
| 42 | + ( |
| 43 | + ( |
| 44 | + if exists(f.getArgName(0)) |
| 45 | + then |
| 46 | + message = "Normal methods should have 'self', rather than '" + f.getArgName(0) + |
| 47 | + "', as their first parameter." |
| 48 | + else |
| 49 | + message = "Normal methods should have at least one parameter (the first of which should be 'self')." |
| 50 | + ) and |
| 51 | + not f.hasVarArg() |
| 52 | + ) and |
| 53 | + not fv instanceof ZopeInterfaceMethodValue |
54 | 54 | select f, message |
0 commit comments