Update to inline expectations + fixes

This commit is contained in:
Joe Farebrother
2025-02-03 17:36:43 +00:00
parent aa2c84ea36
commit e8adef18a3
8 changed files with 44 additions and 25 deletions

View File

@@ -9,7 +9,7 @@ private predicate methodOfClass(Function f, Class c) { f.getScope() = c }
/** Holds if `c` is a metaclass. */
private predicate isMetaclass(Class c) {
c.getABase() = API::builtin("type").getASubclass*().asSource().asExpr()
c = API::builtin("type").getASubclass*().asSource().asExpr().(ClassExpr).getInnerScope()
}
/** Holds if `f` is a class method. */
@@ -26,13 +26,15 @@ private predicate isStaticMethod(Function f) {
/** Holds if `c` is a Zope interface. */
private predicate isZopeInterface(Class c) {
c.getABase() =
API::moduleImport("zone")
.getMember("interface")
c =
API::moduleImport("zope")
.getMember("interface")
.getMember("Interface")
.getASubclass*()
.asSource()
.asExpr()
.(ClassExpr)
.getInnerScope()
}
/**

View File

@@ -1,3 +0,0 @@
| parameter_names.py:17:5:17:24 | Function n_cmethod | Class methods or methods of a type deriving from type should have 'cls', rather than 'self', as their first parameter. |
| parameter_names.py:22:5:22:21 | Function n_cmethod2 | Class methods or methods of a type deriving from type should have 'cls' as their first parameter. |
| parameter_names.py:37:5:37:20 | Function c_method | Class methods or methods of a type deriving from type should have 'cls', rather than 'y', as their first parameter. |

View File

@@ -1 +0,0 @@
Functions/NonCls.ql

View File

@@ -1,4 +0,0 @@
| om_test.py:71:5:71:19 | Function __repr__ | Normal methods should have at least one parameter (the first of which should be 'self'). |
| parameter_names.py:50:5:50:20 | Function __init__ | Normal methods should have 'self', rather than 'x', as their first parameter. |
| parameter_names.py:53:5:53:20 | Function s_method | Normal methods should have 'self', rather than 'y', as their first parameter. |
| parameter_names.py:56:5:56:20 | Function s_method2 | Normal methods should have at least one parameter (the first of which should be 'self'). |

View File

@@ -1 +0,0 @@
Functions/NonSelf.ql

View File

@@ -14,46 +14,47 @@ class Normal(object):
# not ok
@classmethod
def n_cmethod(self):
def n_cmethod(self): # $shouldBeCls
pass
# not ok
@classmethod
def n_cmethod2():
def n_cmethod2(): # $shouldBeCls
pass
# this is allowed because it has a decorator other than @classmethod
@classmethod
@id
def n_suppress(any_name):
def n_dec(any_name): # $shouldBeCls
pass
# Metaclass - normal methods should be named cls, though self is also accepted
class Class(type):
def __init__(cls):
pass
def c_method(y):
def c_method(y): # $shouldBeCls
pass
def c_ok(cls):
pass
@id
def c_suppress(any_name):
# technically we could alert on mixing self for metaclasses with cls for metaclasses in the same codebase,
# but it's probably not too significant.
def c_self_ok(self):
pass
class NonSelf(object):
def __init__(x):
def __init__(x): # $shouldBeSelf
pass
def s_method(y):
def s_method(y): # $shouldBeSelf
pass
def s_method2():
def s_method2(): # $shouldBeSelf
pass
def s_ok(self):
@@ -67,11 +68,12 @@ class NonSelf(object):
def s_cmethod(cls):
pass
def s_smethod2(ok):
# we allow methods that are used in class initialization, but only detect this case when they are called.
def s_smethod2(ok): # $ SPURIOUS: shouldBeSelf
pass
s_smethod2 = staticmethod(s_smethod2)
def s_cmethod2(cls):
def s_cmethod2(cls): # $ SPURIOUS: shouldBeSelf
pass
s_cmethod2 = classmethod(s_cmethod2)

View File

@@ -0,0 +1,24 @@
import python
import Functions.MethodArgNames
import utils.test.InlineExpectationsTest
module MethodArgTest implements TestSig {
string getARelevantTag() { result = ["shouldBeSelf", "shouldBeCls"] }
predicate hasActualResult(Location location, string element, string tag, string value) {
exists(Function f |
element = f.toString() and
location = f.getLocation() and
value = "" and
(
firstArgShouldBeNamedSelfAndIsnt(f) and
tag = "shouldBeSelf"
or
firstArgShouldBeNamedClsAndIsnt(f) and
tag = "shouldBeCls"
)
)
}
}
import MakeTest<MethodArgTest>