diff --git a/ql/src/codeql_ql/ast/Ast.qll b/ql/src/codeql_ql/ast/Ast.qll index 6f9ae44b407..df6838bd432 100644 --- a/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/src/codeql_ql/ast/Ast.qll @@ -228,10 +228,14 @@ class ClassPredicate extends TClassPredicate, Predicate { override string getAPrimaryQlClass() { result = "ClassPredicate" } - predicate isPrivate() { + override Class getParent() { result.getAClassPredicate() = this } + + predicate isPrivate() { hasAnnotation("private") } + + predicate hasAnnotation(string name) { exists(Generated::ClassMember member | pred = member.getChild(_) and - member.getAFieldOrChild().(Generated::Annotation).getName().getValue() = "private" + member.getAFieldOrChild().(Generated::Annotation).getName().getValue() = name ) } diff --git a/ql/src/queries/style/MissingOverride.ql b/ql/src/queries/style/MissingOverride.ql new file mode 100644 index 00000000000..52b690940d2 --- /dev/null +++ b/ql/src/queries/style/MissingOverride.ql @@ -0,0 +1,20 @@ +/** + * @name Missing override annotation + * @description Predicates that overide another predicate should have an `override` annotation. + * @kind problem + * @problem.severity warning + * @precision very-high + * @id ql/missing-override + * @tags maintainability + */ + +import ql + +string getQualifiedName(ClassPredicate p) { + result = p.getDeclaringType().getName() + "." + p.getName() +} + +from ClassPredicate pred, ClassPredicate sup +where pred.overrides(sup) and not pred.hasAnnotation("override") +select pred, getQualifiedName(pred) + "overrides $@ but does not have an override annotation.", sup, + getQualifiedName(sup) diff --git a/ql/test/queries/style/MissingOverride/MissingOverride.expected b/ql/test/queries/style/MissingOverride/MissingOverride.expected new file mode 100644 index 00000000000..d6a2a7e365d --- /dev/null +++ b/ql/test/queries/style/MissingOverride/MissingOverride.expected @@ -0,0 +1 @@ +| Test.qll:12:3:12:33 | ClassPredicate | Wrong.testoverrides $@ but does not have an override annotation. | Test.qll:4:3:4:40 | ClassPredicate | Super.test | diff --git a/ql/test/queries/style/MissingOverride/MissingOverride.qlref b/ql/test/queries/style/MissingOverride/MissingOverride.qlref new file mode 100644 index 00000000000..3a83310f4a2 --- /dev/null +++ b/ql/test/queries/style/MissingOverride/MissingOverride.qlref @@ -0,0 +1 @@ +queries/style/MissingOverride.ql \ No newline at end of file diff --git a/ql/test/queries/style/MissingOverride/Test.qll b/ql/test/queries/style/MissingOverride/Test.qll new file mode 100644 index 00000000000..e7f6a2c6b87 --- /dev/null +++ b/ql/test/queries/style/MissingOverride/Test.qll @@ -0,0 +1,13 @@ +import ql + +class Super extends AstNode { + predicate test(int i) { i = [1 .. 5] } +} + +class Correct extends Super { + override predicate test(int i) { i = 3 } +} + +class Wrong extends Super { + predicate test(int i) { i = 2 } +}