diff --git a/ruby/ql/lib/codeql/ruby/ast/Module.qll b/ruby/ql/lib/codeql/ruby/ast/Module.qll index a511a8cf952..cb940b4a35a 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Module.qll @@ -23,6 +23,20 @@ class Module extends TModule { /** Gets an `include`d module. */ Module getAnIncludedModule() { result = getAnIncludedModule(this) } + /** Gets the super class or an included or prepended module. */ + Module getADirectAncestor() { + result = [this.getSuperClass(), this.getAPrependedModule(), this.getAnIncludedModule()] + } + + /** Gets a direct subclass or module including or prepending this one. */ + Module getADirectDescendent() { this = result.getADirectAncestor() } + + /** Gets a module that is transitively subclassed, included, or prepended by this module. */ + Module getAnAncestor() { result = this.getADirectAncestor*() } + + /** Gets a module that transitively subclasses, includes, or prepends this module. */ + Module getADescendent() { result = this.getADirectDescendent*() } + /** Holds if this module is a class. */ pragma[noinline] predicate isClass() { diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll index f4934500efd..7c2f7abbd75 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowPublic.qll @@ -703,6 +703,17 @@ class ModuleNode instanceof Module { /** Gets an `include`d module. */ final ModuleNode getAnIncludedModule() { result = super.getAnIncludedModule() } + /** Gets the super class or an included or prepended module. */ + final ModuleNode getADirectAncestor() { result = super.getADirectAncestor() } + + /** Gets a direct subclass or module including or prepending this one. */ + final ModuleNode getADirectDescendent() { result = super.getADirectDescendent() } + + /** Gets a module that is transitively subclassed, included, or prepended by this module. */ + final ModuleNode getAnAncestor() { result = super.getAnAncestor() } + + /** Gets a module that transitively subclasses, includes, or prepends this module. */ + final ModuleNode getADescendent() { result = super.getADescendent() } /** Holds if this module is a class. */ predicate isClass() { super.isClass() }