diff --git a/ql/src/codeql_ruby/AST.qll b/ql/src/codeql_ruby/AST.qll index 11f201ac6dd..518f42c69d9 100644 --- a/ql/src/codeql_ruby/AST.qll +++ b/ql/src/codeql_ruby/AST.qll @@ -13,6 +13,7 @@ import ast.Scope import ast.Statement import ast.Variable private import ast.internal.AST +private import ast.internal.Scope /** * A node in the abstract syntax tree. This class is the base class for all Ruby @@ -28,6 +29,20 @@ class AstNode extends TAstNode { */ string getAPrimaryQlClass() { result = "???" } + /** Gets the enclosing module, if any. */ + ModuleBase getEnclosingModule() { + exists(Scope::Range s | + s = scopeOf(toGenerated(this)) and toGenerated(result) = s.getEnclosingModule() + ) + } + + /** Gets the enclosing method, if any. */ + MethodBase getEnclosingMethod() { + exists(Scope::Range s | + s = scopeOf(toGenerated(this)) and toGenerated(result) = s.getEnclosingMethod() + ) + } + /** Gets a textual representation of this node. */ cached string toString() { none() } diff --git a/ql/src/codeql_ruby/ast/Expr.qll b/ql/src/codeql_ruby/ast/Expr.qll index a113103d09b..4e44bc98a25 100644 --- a/ql/src/codeql_ruby/ast/Expr.qll +++ b/ql/src/codeql_ruby/ast/Expr.qll @@ -137,11 +137,11 @@ class BodyStmt extends StmtSequence, TBodyStmt { result = any(Generated::Program g | this = TToplevel(g)).getChild(i) and not result instanceof Generated::BeginBlock or - result = any(Generated::Class g | this = TClass(g)).getChild(i) + result = any(Generated::Class g | this = TClassDeclaration(g)).getChild(i) or result = any(Generated::SingletonClass g | this = TSingletonClass(g)).getChild(i) or - result = any(Generated::Module g | this = TModule(g)).getChild(i) + result = any(Generated::Module g | this = TModuleDeclaration(g)).getChild(i) or result = any(Generated::Begin g | this = TBeginExpr(g)).getChild(i) } diff --git a/ql/src/codeql_ruby/ast/Method.qll b/ql/src/codeql_ruby/ast/Method.qll index 7c205f174ab..648392b28f0 100644 --- a/ql/src/codeql_ruby/ast/Method.qll +++ b/ql/src/codeql_ruby/ast/Method.qll @@ -4,7 +4,7 @@ private import internal.AST private import internal.TreeSitter /** A callable. */ -class Callable extends Expr, TCallable { +class Callable extends Expr, Scope, TCallable { /** Gets the number of parameters of this callable. */ final int getNumberOfParameters() { result = count(this.getAParameter()) } diff --git a/ql/src/codeql_ruby/ast/Module.qll b/ql/src/codeql_ruby/ast/Module.qll index 0eff778dbb8..d449a576e4a 100644 --- a/ql/src/codeql_ruby/ast/Module.qll +++ b/ql/src/codeql_ruby/ast/Module.qll @@ -1,12 +1,46 @@ private import codeql_ruby.AST private import codeql_ruby.ast.Constant private import internal.AST +private import internal.Module private import internal.TreeSitter +/** + * A representation of a run-time `module` or `class` value. + */ +class Module extends TModule { + /** Get a declaration of this module, if any. */ + ModuleBase getADeclaration() { result.getModule() = this } + + /** Gets a textual representation of this module. */ + string toString() { + this = TResolved(result) + or + exists(Namespace n | this = TUnresolved(n) and result = "...::" + n.toString()) + } + + /** Gets the location of this module. */ + Location getLocation() { + exists(Namespace n | this = TUnresolved(n) and result = n.getLocation()) + or + result = + min(Namespace n, string qName, Location loc, int weight | + this = TResolved(qName) and + qName = namespaceDeclaration(n) and + loc = n.getLocation() and + if exists(loc.getFile().getRelativePath()) then weight = 0 else weight = 1 + | + loc + order by + weight, count(n.getAStmt()) desc, loc.getFile().getAbsolutePath(), loc.getStartLine(), + loc.getStartColumn() + ) + } +} + /** * The base class for classes, singleton classes, and modules. */ -class ModuleBase extends BodyStmt, TModuleBase { +class ModuleBase extends BodyStmt, Scope, TModuleBase { /** Gets a method defined in this module/class. */ MethodBase getAMethod() { result = this.getAStmt() } @@ -14,16 +48,21 @@ class ModuleBase extends BodyStmt, TModuleBase { MethodBase getMethod(string name) { result = this.getAMethod() and result.getName() = name } /** Gets a class defined in this module/class. */ - Class getAClass() { result = this.getAStmt() } + ClassDeclaration getAClass() { result = this.getAStmt() } /** Gets the class named `name` in this module/class, if any. */ - Class getClass(string name) { result = this.getAClass() and result.getName() = name } + ClassDeclaration getClass(string name) { result = this.getAClass() and result.getName() = name } /** Gets a module defined in this module/class. */ - Module getAModule() { result = this.getAStmt() } + ModuleDeclaration getAModule() { result = this.getAStmt() } /** Gets the module named `name` in this module/class, if any. */ - Module getModule(string name) { result = this.getAModule() and result.getName() = name } + ModuleDeclaration getModule(string name) { + result = this.getAModule() and result.getName() = name + } + + /** Gets the representation of the run-time value of this module or class. */ + Module getModule() { none() } } /** @@ -62,6 +101,8 @@ class Toplevel extends ModuleBase, TToplevel { pred = "getBeginBlock" and result = this.getBeginBlock(_) } + final override Module getModule() { result = TResolved("Object") } + final override string toString() { result = g.getLocation().getFile().getBaseName() } } @@ -132,6 +173,12 @@ class Namespace extends ModuleBase, ConstantWriteAccess, TNamespace { */ override predicate hasGlobalScope() { none() } + final override Module getModule() { + result = any(string qName | qName = namespaceDeclaration(this) | TResolved(qName)) + or + result = TUnresolved(this) + } + override AstNode getAChild(string pred) { result = ModuleBase.super.getAChild(pred) or result = ConstantWriteAccess.super.getAChild(pred) @@ -150,12 +197,12 @@ class Namespace extends ModuleBase, ConstantWriteAccess, TNamespace { * end * ``` */ -class Class extends Namespace, TClass { +class ClassDeclaration extends Namespace, TClassDeclaration { private Generated::Class g; - Class() { this = TClass(g) } + ClassDeclaration() { this = TClassDeclaration(g) } - final override string getAPrimaryQlClass() { result = "Class" } + final override string getAPrimaryQlClass() { result = "ClassDeclaration" } /** * Gets the `Expr` used as the superclass in the class definition, if any. @@ -214,7 +261,7 @@ class SingletonClass extends ModuleBase, TSingletonClass { SingletonClass() { this = TSingletonClass(g) } - final override string getAPrimaryQlClass() { result = "Class" } + final override string getAPrimaryQlClass() { result = "ClassDeclaration" } /** * Gets the expression resulting in the object on which the singleton class @@ -249,7 +296,7 @@ class SingletonClass extends ModuleBase, TSingletonClass { * N.B. this class represents a single instance of a module definition. In the * following example, classes `Bar` and `Baz` are both defined in the module * `Foo`, but in two syntactically distinct definitions, meaning that there - * will be two instances of `Module` in the database. + * will be two instances of `ModuleDeclaration` in the database. * * ```rb * module Foo @@ -261,12 +308,12 @@ class SingletonClass extends ModuleBase, TSingletonClass { * end * ``` */ -class Module extends Namespace, TModule { +class ModuleDeclaration extends Namespace, TModuleDeclaration { private Generated::Module g; - Module() { this = TModule(g) } + ModuleDeclaration() { this = TModuleDeclaration(g) } - final override string getAPrimaryQlClass() { result = "Module" } + final override string getAPrimaryQlClass() { result = "ModuleDeclaration" } final override string getName() { result = g.getName().(Generated::Token).getValue() or diff --git a/ql/src/codeql_ruby/ast/Scope.qll b/ql/src/codeql_ruby/ast/Scope.qll index 36b23e880e5..a726236e410 100644 --- a/ql/src/codeql_ruby/ast/Scope.qll +++ b/ql/src/codeql_ruby/ast/Scope.qll @@ -8,12 +8,6 @@ class Scope extends AstNode, TScopeType { Scope() { range = toGenerated(this) } - /** Gets the enclosing module, if any. */ - ModuleBase getEnclosingModule() { toGenerated(result) = range.getEnclosingModule() } - - /** Gets the enclosing method, if any. */ - MethodBase getEnclosingMethod() { toGenerated(result) = range.getEnclosingMethod() } - /** Gets the scope in which this scope is nested, if any. */ Scope getOuterScope() { toGenerated(result) = range.getOuterScope() } diff --git a/ql/src/codeql_ruby/ast/internal/AST.qll b/ql/src/codeql_ruby/ast/internal/AST.qll index 37ef071d507..26e2e6149c3 100644 --- a/ql/src/codeql_ruby/ast/internal/AST.qll +++ b/ql/src/codeql_ruby/ast/internal/AST.qll @@ -82,7 +82,7 @@ private module Cached { TCaseEqExpr(Generated::Binary g) { g instanceof @binary_equalequalequal } or TCaseExpr(Generated::Case g) or TCharacterLiteral(Generated::Character g) or - TClass(Generated::Class g) or + TClassDeclaration(Generated::Class g) or TClassVariableAccess(Generated::ClassVariable g, AST::ClassVariable v) { ClassVariableAccess::range(g, v) } or @@ -139,7 +139,7 @@ private module Cached { } or TLogicalOrExpr(Generated::Binary g) { g instanceof @binary_or or g instanceof @binary_pipepipe } or TMethod(Generated::Method g) or - TModule(Generated::Module g) or + TModuleDeclaration(Generated::Module g) or TModuloExpr(Generated::Binary g) { g instanceof @binary_percent } or TMulExpr(Generated::Binary g) { g instanceof @binary_star } or TNEExpr(Generated::Binary g) { g instanceof @binary_bangequal } or @@ -257,7 +257,7 @@ private module Cached { n = TCaseEqExpr(result) or n = TCaseExpr(result) or n = TCharacterLiteral(result) or - n = TClass(result) or + n = TClassDeclaration(result) or n = TClassVariableAccess(result, _) or n = TComplementExpr(result) or n = TComplexLiteral(result) or @@ -302,7 +302,7 @@ private module Cached { n = TLogicalAndExpr(result) or n = TLogicalOrExpr(result) or n = TMethod(result) or - n = TModule(result) or + n = TModuleDeclaration(result) or n = TModuloExpr(result) or n = TMulExpr(result) or n = TNEExpr(result) or @@ -434,7 +434,7 @@ class TBlock = TDoBlock or TBraceBlock; class TModuleBase = TToplevel or TNamespace or TSingletonClass; -class TNamespace = TClass or TModule; +class TNamespace = TClassDeclaration or TModuleDeclaration; class TOperation = TUnaryOperation or TBinaryOperation or TAssignment; diff --git a/ql/src/codeql_ruby/ast/internal/Module.qll b/ql/src/codeql_ruby/ast/internal/Module.qll new file mode 100644 index 00000000000..8a0f98182af --- /dev/null +++ b/ql/src/codeql_ruby/ast/internal/Module.qll @@ -0,0 +1,218 @@ +private import codeql.Locations +private import codeql_ruby.ast.Call +private import codeql_ruby.ast.Constant +private import codeql_ruby.ast.Expr +private import codeql_ruby.ast.Module +private import codeql_ruby.ast.Operation +private import codeql_ruby.ast.Scope + +// Names of built-in modules and classes +private string builtin() { result = ["Object", "Kernel", "BasicObject", "Class", "Module"] } + +cached +private module Cached { + cached + newtype TModule = + TResolved(string qName) { + qName = builtin() + or + qName = namespaceDeclaration(_) + } or + TUnresolved(Namespace n) { not exists(namespaceDeclaration(n)) } + + cached + string namespaceDeclaration(Namespace n) { + isToplevel(n) and result = n.getName() + or + not isToplevel(n) and + not exists(n.getScopeExpr()) and + result = scopeAppend(namespaceDeclaration(n.getEnclosingModule()), n.getName()) + or + exists(string container | + TResolved(container) = resolveScopeExpr(n.getScopeExpr()) and + result = scopeAppend(container, n.getName()) + ) + } +} + +import Cached + +private predicate isToplevel(ConstantAccess n) { + not exists(n.getScopeExpr()) and + ( + n.hasGlobalScope() + or + n.getEnclosingModule() instanceof Toplevel + ) +} + +private predicate isDefinedConstant(string qualifiedModuleName) { + qualifiedModuleName = [builtin(), constantDefinition0(_)] +} + +/** + * Resolve constant read access (typically a scope expression) to a qualified module name. + * `resolveScopeExpr/1` picks the best (lowest priority number) result of + * `resolveScopeExpr/2` that resolves to a constant definition. If the constant + * definition is a Namespace then it is returned, if it's a constant assignment then + * the right-hand side of the assignment is resolved. + */ +private TResolved resolveScopeExpr(ConstantReadAccess r) { + exists(string qname | + qname = + min(string qn, int p | + isDefinedConstant(qn) and + qn = resolveScopeExpr(r, p) + | + qn order by p + ) + | + result = TResolved(qname) + or + exists(ConstantAssignment a | + qname = constantDefinition0(a) and + result = resolveScopeExpr(a.getParent().(Assignment).getRightOperand()) + ) + ) +} + +private int maxDepth() { result = 1 + max(int level | exists(enclosing(_, level))) } + +private ModuleBase enclosing(ModuleBase m, int level) { + result = m and level = 0 + or + result = enclosing(m.getEnclosingModule(), level - 1) +} + +/** + * Resolve constant read access (typically a scope expression) to a qualified name. The + * `priority` value indicates the precedence of the solution with respect to the lookup order. + * A constant name without scope specifier is resolved against its enclosing modules (inner-most first); + * if the constant is not found in any of the enclosing modules, then the constant will be resolved + * with respect to the ancestors (prepends, includes, super classes, and their ancestors) of the + * directly enclosing module. + */ +private string resolveScopeExpr(ConstantReadAccess c, int priority) { + c.hasGlobalScope() and result = c.getName() and priority = 0 + or + result = qualifiedModuleName(resolveScopeExpr(c.getScopeExpr(), priority), c.getName()) + or + not exists(c.getScopeExpr()) and + not c.hasGlobalScope() and + exists(Namespace n | + result = qualifiedModuleName(constantDefinition0(n), c.getName()) and + n = enclosing(c.getEnclosingModule(), priority) + ) + or + result = + qualifiedModuleName(ancestors(qualifiedModuleName(c.getEnclosingModule()), priority - maxDepth()), + c.getName()) + or + result = c.getName() and + priority = maxDepth() + 4 and + qualifiedModuleName(c.getEnclosingModule()) != "BasicObject" +} + +bindingset[qualifier, name] +private string scopeAppend(string qualifier, string name) { + if qualifier = "Object" then result = name else result = qualifier + "::" + name +} + +private string qualifiedModuleName(ModuleBase m) { + result = "Object" and m instanceof Toplevel + or + result = constantDefinition0(m) +} + +/** + * Get a qualified name for a constant definition. May return multiple qualified + * names because we over-approximate when resolving scope resolutions and ignore + * lookup order precedence. Taking lookup order into account here would lead to + * non-monotonic recursion. + */ +private string constantDefinition0(ConstantWriteAccess c) { + c.hasGlobalScope() and result = c.getName() + or + result = scopeAppend(resolveScopeExpr(c.getScopeExpr(), _), c.getName()) + or + not exists(c.getScopeExpr()) and + not c.hasGlobalScope() and + exists(ModuleBase enclosing | enclosing = c.getEnclosingModule() | + result = scopeAppend(qualifiedModuleName(enclosing), c.getName()) + ) +} + +/** + * The qualified names of the ancestors of a class/module. The ancestors should be an ordered list + * of the ancestores of `prepend`ed modules, the module itself , the ancestors or `include`d modules + * and the ancestors of the super class. The priority value only distinguishes the kind of ancestor, + * it does not order the ancestors within a group of the same kind. This is an over-approximation, however, + * computing the precise order is tricky because it depends on the evaluation/file loading order. + */ +// TODO: the order of super classes can be determined more precisely even without knowing the evaluation +// order, so we should be able to make this more precise. +private string ancestors(string qname, int priority) { + result = ancestors(prepends(qname), _) and priority = 0 + or + result = qname and priority = 1 and isDefinedConstant(qname) + or + result = ancestors(includes(qname), _) and priority = 2 + or + result = ancestors(superclass(qname), _) and priority = 3 +} + +private class IncludeOrPrependCall extends MethodCall { + IncludeOrPrependCall() { this.getMethodName() = ["include", "prepend"] } + + string getAModule() { result = resolveScopeExpr(this.getAnArgument(), _) } + + string getTarget() { + result = resolveScopeExpr(this.getReceiver(), _) + or + result = qualifiedModuleName(this.getEnclosingModule()) and + ( + this.getReceiver() instanceof Self + or + not exists(this.getReceiver()) + ) + } +} + +private string prepends(string qname) { + exists(IncludeOrPrependCall m | + m.getMethodName() = "prepend" and + qname = m.getTarget() and + result = m.getAModule() + ) +} + +private string includes(string qname) { + qname = "Object" and + result = "Kernel" + or + exists(IncludeOrPrependCall m | + m.getMethodName() = "include" and + qname = m.getTarget() and + result = m.getAModule() + ) +} + +private Expr superexpr(string qname) { + exists(ClassDeclaration c | qname = constantDefinition0(c) and result = c.getSuperclassExpr()) +} + +private string superclass(string qname) { + qname = "Object" and result = "BasicObject" + or + result = resolveScopeExpr(superexpr(qname), _) +} + +private string qualifiedModuleName(string container, string name) { + isDefinedConstant(result) and + ( + container = result.regexpCapture("(.+)::([^:]+)", 1) and + name = result.regexpCapture("(.+)::([^:]+)", 2) + or + container = "Object" and name = result + ) +} diff --git a/ql/src/codeql_ruby/ast/internal/Scope.qll b/ql/src/codeql_ruby/ast/internal/Scope.qll index 7c76ef8affa..fa030b2eb39 100644 --- a/ql/src/codeql_ruby/ast/internal/Scope.qll +++ b/ql/src/codeql_ruby/ast/internal/Scope.qll @@ -7,7 +7,7 @@ class TScopeType = TMethodBase or TModuleLike or TBlockLike; private class TBlockLike = TDoBlock or TLambda or TBlock or TEndBlock; -private class TModuleLike = TToplevel or TModule or TClass or TSingletonClass; +private class TModuleLike = TToplevel or TModuleDeclaration or TClassDeclaration or TSingletonClass; module Scope { class TypeRange = Callable::TypeRange or ModuleBase::TypeRange or @end_block; diff --git a/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll index 15097a58d85..a648a2c1b71 100644 --- a/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll +++ b/ql/src/codeql_ruby/controlflow/internal/ControlFlowGraphImpl.qll @@ -598,7 +598,7 @@ module Trees { private class CharacterTree extends LeafTree, CharacterLiteral { } - private class ClassTree extends BodyStmtPreOrderTree, Class { + private class ClassDeclarationTree extends BodyStmtPreOrderTree, ClassDeclaration { /** Gets the `i`th child in the body of this block. */ final override AstNode getBodyChild(int i, boolean rescuable) { result = this.getScopeExpr() and i = 0 and rescuable = false @@ -673,8 +673,8 @@ module Trees { private class ConstantAccessTree extends PostOrderTree, ConstantAccess { ConstantAccessTree() { - not this instanceof Class and - not this instanceof Module + not this instanceof ClassDeclaration and + not this instanceof ModuleDeclaration } final override predicate propagatesAbnormal(AstNode child) { child = this.getScopeExpr() } @@ -934,7 +934,7 @@ module Trees { } } - private class ModuleTree extends BodyStmtPreOrderTree, Module { + private class ModuleDeclarationTree extends BodyStmtPreOrderTree, ModuleDeclaration { /** Gets the `i`th child in the body of this block. */ final override AstNode getBodyChild(int i, boolean rescuable) { result = this.getScopeExpr() and i = 0 and rescuable = false diff --git a/ql/test/library-tests/ast/Ast.expected b/ql/test/library-tests/ast/Ast.expected index 5c411c581b7..30a91419de1 100644 --- a/ql/test/library-tests/ast/Ast.expected +++ b/ql/test/library-tests/ast/Ast.expected @@ -128,19 +128,19 @@ calls/calls.rb: # 111| getBody: [StmtSequence] then ... # 112| getStmt: [MethodCall] call to baz # 112| getReceiver: [ConstantReadAccess] X -# 116| getStmt: [Class] MyClass +# 116| getStmt: [ClassDeclaration] MyClass # 117| getStmt: [MethodCall] call to foo # 118| getStmt: [MethodCall] call to bar # 118| getReceiver: [ConstantReadAccess] X -# 122| getStmt: [Class] MyClass +# 122| getStmt: [ClassDeclaration] MyClass # 122| getSuperclassExpr: [MethodCall] call to foo -# 124| getStmt: [Class] MyClass2 +# 124| getStmt: [ClassDeclaration] MyClass2 # 124| getSuperclassExpr: [MethodCall] call to foo # 124| getReceiver: [ConstantReadAccess] X -# 128| getStmt: [Class] class << ... +# 128| getStmt: [ClassDeclaration] class << ... # 128| getValue: [MethodCall] call to foo # 129| getStmt: [MethodCall] call to bar -# 131| getStmt: [Class] class << ... +# 131| getStmt: [ClassDeclaration] class << ... # 131| getValue: [MethodCall] call to foo # 131| getReceiver: [ConstantReadAccess] X # 132| getStmt: [MethodCall] call to bar @@ -172,7 +172,7 @@ calls/calls.rb: # 156| getDefiningAccess: [LocalVariableAccess] param # 156| getDefaultValue: [MethodCall] call to foo # 156| getReceiver: [ConstantReadAccess] X -# 160| getStmt: [Module] SomeModule +# 160| getStmt: [ModuleDeclaration] SomeModule # 161| getStmt: [MethodCall] call to foo # 162| getStmt: [MethodCall] call to bar # 162| getReceiver: [ConstantReadAccess] X @@ -376,7 +376,7 @@ calls/calls.rb: # 279| getKey: [SymbolLiteral] :blah # 279| getValue: [MethodCall] call to bar # 279| getReceiver: [ConstantReadAccess] X -# 284| getStmt: [Class] MyClass +# 284| getStmt: [ClassDeclaration] MyClass # 285| getStmt: [Method] my_method # 286| getStmt: [SuperCall] call to super # 287| getStmt: [SuperCall] call to super @@ -419,7 +419,7 @@ calls/calls.rb: # 293| getStmt: [AddExpr] ... + ... # 293| getAnOperand/getLeftOperand: [LocalVariableAccess] x # 293| getAnOperand/getRightOperand: [IntegerLiteral] 200 -# 301| getStmt: [Class] AnotherClass +# 301| getStmt: [ClassDeclaration] AnotherClass # 302| getStmt: [Method] another_method # 303| getStmt: [MethodCall] call to super # 303| getReceiver: [MethodCall] call to foo @@ -522,16 +522,16 @@ control/cases.rb: # 21| getStmt: [IntegerLiteral] 30 modules/classes.rb: # 2| [Toplevel] classes.rb -# 3| getStmt: [Class] Foo -# 7| getStmt: [Class] Bar +# 3| getStmt: [ClassDeclaration] Foo +# 7| getStmt: [ClassDeclaration] Bar # 7| getSuperclassExpr: [ConstantReadAccess] BaseClass -# 11| getStmt: [Class] Baz +# 11| getStmt: [ClassDeclaration] Baz # 11| getSuperclassExpr: [MethodCall] call to superclass_for # 11| getArgument: [SymbolLiteral] :baz -# 15| getStmt: [Module] MyModule -# 16| getStmt: [Class] MyClass +# 15| getStmt: [ModuleDeclaration] MyModule +# 16| getStmt: [ClassDeclaration] MyClass # 16| getScopeExpr: [ConstantReadAccess] MyModule -# 20| getStmt: [Class] Wibble +# 20| getStmt: [ClassDeclaration] Wibble # 21| getStmt: [Method] method_a # 22| getStmt: [MethodCall] call to puts # 22| getArgument: [StringLiteral] "a" @@ -544,13 +544,13 @@ modules/classes.rb: # 30| getStmt: [AssignExpr] ... = ... # 30| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var # 30| getAnOperand/getRightOperand: [IntegerLiteral] 123 -# 32| getStmt: [Class] ClassInWibble -# 35| getStmt: [Module] ModuleInWibble +# 32| getStmt: [ClassDeclaration] ClassInWibble +# 35| getStmt: [ModuleDeclaration] ModuleInWibble # 40| getStmt: [AssignExpr] ... = ... # 40| getAnOperand/getLeftOperand: [LocalVariableAccess] x # 40| getAnOperand/getRightOperand: [StringLiteral] "hello" # 40| getComponent: [StringTextComponent] hello -# 41| getStmt: [Class] class << ... +# 41| getStmt: [ClassDeclaration] class << ... # 41| getValue: [LocalVariableAccess] x # 42| getStmt: [Method] length # 43| getStmt: [MulExpr] ... * ... @@ -564,7 +564,7 @@ modules/classes.rb: # 51| getStmt: [AssignExpr] ... = ... # 51| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var2 # 51| getAnOperand/getRightOperand: [IntegerLiteral] 456 -# 55| getStmt: [Class] MyClassInGlobalScope +# 55| getStmt: [ClassDeclaration] MyClassInGlobalScope control/conditionals.rb: # 1| [Toplevel] conditionals.rb # 2| getStmt: [AssignExpr] ... = ... @@ -687,12 +687,12 @@ control/conditionals.rb: # 69| getStmt: [LocalVariableAccess] c constants/constants.rb: # 1| [Toplevel] constants.rb -# 1| getStmt: [Module] ModuleA -# 2| getStmt: [Class] ClassA -# 5| getStmt: [Module] ModuleB -# 6| getStmt: [Class] ClassB +# 1| getStmt: [ModuleDeclaration] ModuleA +# 2| getStmt: [ClassDeclaration] ClassA +# 5| getStmt: [ModuleDeclaration] ModuleB +# 6| getStmt: [ClassDeclaration] ClassB # 6| getSuperclassExpr: [ConstantReadAccess] Base -# 9| getStmt: [Class] ClassC +# 9| getStmt: [ClassDeclaration] ClassC # 9| getSuperclassExpr: [ConstantReadAccess] Z # 9| getScopeExpr: [ConstantReadAccess] Y # 9| getScopeExpr: [ConstantReadAccess] X @@ -725,9 +725,9 @@ constants/constants.rb: # 25| getStmt: [MethodCall] call to Array # 25| getArgument: [StringLiteral] "foo" # 25| getComponent: [StringTextComponent] foo -# 28| getStmt: [Class] ClassD +# 28| getStmt: [ClassDeclaration] ClassD # 28| getScopeExpr: [ConstantReadAccess] ModuleA -# 31| getStmt: [Module] ModuleC +# 31| getStmt: [ModuleDeclaration] ModuleC # 31| getScopeExpr: [ConstantReadAccess] ModuleA # 34| getStmt: [AssignExpr] ... = ... # 34| getAnOperand/getLeftOperand: [ConstantAssignment] MAX_SIZE @@ -1322,10 +1322,10 @@ misc/misc.rb: # 10| getComponent: [StringTextComponent] foo modules/modules.rb: # 1| [Toplevel] modules.rb -# 1| getStmt: [Module] Empty -# 4| getStmt: [Module] Foo -# 5| getStmt: [Module] Bar -# 6| getStmt: [Class] ClassInFooBar +# 1| getStmt: [ModuleDeclaration] Empty +# 4| getStmt: [ModuleDeclaration] Foo +# 5| getStmt: [ModuleDeclaration] Bar +# 6| getStmt: [ClassDeclaration] ClassInFooBar # 9| getStmt: [Method] method_in_foo_bar # 12| getStmt: [MethodCall] call to puts # 12| getArgument: [StringLiteral] "module Foo::Bar" @@ -1334,23 +1334,23 @@ modules/modules.rb: # 13| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var # 13| getAnOperand/getRightOperand: [IntegerLiteral] 0 # 16| getStmt: [Method] method_in_foo -# 19| getStmt: [Class] ClassInFoo +# 19| getStmt: [ClassDeclaration] ClassInFoo # 22| getStmt: [MethodCall] call to puts # 22| getArgument: [StringLiteral] "module Foo" # 22| getComponent: [StringTextComponent] module Foo # 23| getStmt: [AssignExpr] ... = ... # 23| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var # 23| getAnOperand/getRightOperand: [IntegerLiteral] 1 -# 26| getStmt: [Module] Foo +# 26| getStmt: [ModuleDeclaration] Foo # 27| getStmt: [Method] method_in_another_definition_of_foo -# 30| getStmt: [Class] ClassInAnotherDefinitionOfFoo +# 30| getStmt: [ClassDeclaration] ClassInAnotherDefinitionOfFoo # 33| getStmt: [MethodCall] call to puts # 33| getArgument: [StringLiteral] "module Foo again" # 33| getComponent: [StringTextComponent] module Foo again # 34| getStmt: [AssignExpr] ... = ... # 34| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var # 34| getAnOperand/getRightOperand: [IntegerLiteral] 2 -# 37| getStmt: [Module] Bar +# 37| getStmt: [ModuleDeclaration] Bar # 38| getStmt: [Method] method_a # 41| getStmt: [Method] method_b # 44| getStmt: [MethodCall] call to puts @@ -1359,9 +1359,9 @@ modules/modules.rb: # 45| getStmt: [AssignExpr] ... = ... # 45| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var # 45| getAnOperand/getRightOperand: [IntegerLiteral] 3 -# 48| getStmt: [Module] Bar +# 48| getStmt: [ModuleDeclaration] Bar # 48| getScopeExpr: [ConstantReadAccess] Foo -# 49| getStmt: [Class] ClassInAnotherDefinitionOfFooBar +# 49| getStmt: [ClassDeclaration] ClassInAnotherDefinitionOfFooBar # 52| getStmt: [Method] method_in_another_definition_of_foo_bar # 55| getStmt: [MethodCall] call to puts # 55| getArgument: [StringLiteral] "module Foo::Bar again" @@ -1369,7 +1369,36 @@ modules/modules.rb: # 56| getStmt: [AssignExpr] ... = ... # 56| getAnOperand/getLeftOperand: [GlobalVariableAccess] $global_var # 56| getAnOperand/getRightOperand: [IntegerLiteral] 4 -# 60| getStmt: [Module] MyModuleInGlobalScope +# 60| getStmt: [ModuleDeclaration] MyModuleInGlobalScope +# 63| getStmt: [ModuleDeclaration] Test +# 65| getStmt: [ModuleDeclaration] Foo1 +# 66| getStmt: [ClassDeclaration] Bar +# 66| getScopeExpr: [ConstantReadAccess] Foo1 +# 70| getStmt: [ModuleDeclaration] Foo2 +# 71| getStmt: [ModuleDeclaration] Foo2 +# 72| getStmt: [ClassDeclaration] Bar +# 72| getScopeExpr: [ConstantReadAccess] Foo2 +# 76| getStmt: [ModuleDeclaration] Foo3 +# 77| getStmt: [AssignExpr] ... = ... +# 77| getAnOperand/getLeftOperand: [ConstantAssignment] Foo3 +# 77| getAnOperand/getRightOperand: [ConstantReadAccess] Object +# 78| getStmt: [ClassDeclaration] Bar +# 78| getScopeExpr: [ConstantReadAccess] Foo3 +# 83| getStmt: [ModuleDeclaration] IncludeTest +# 84| getStmt: [MethodCall] call to include +# 84| getArgument: [ConstantReadAccess] Test +# 85| getStmt: [ModuleDeclaration] Y +# 85| getScopeExpr: [ConstantReadAccess] Foo1 +# 89| getStmt: [ModuleDeclaration] IncludeTest2 +# 90| getStmt: [MethodCall] call to include +# 90| getArgument: [ConstantReadAccess] Test +# 91| getStmt: [ModuleDeclaration] Z +# 91| getScopeExpr: [ConstantReadAccess] Foo1 +# 95| getStmt: [ModuleDeclaration] PrependTest +# 96| getStmt: [MethodCall] call to prepend +# 96| getArgument: [ConstantReadAccess] Test +# 97| getStmt: [ModuleDeclaration] Y +# 97| getScopeExpr: [ConstantReadAccess] Foo2 operations/operations.rb: # 1| [Toplevel] operations.rb # 3| getStmt: [AssignExpr] ... = ... diff --git a/ql/test/library-tests/ast/constants/constants.expected b/ql/test/library-tests/ast/constants/constants.expected index c29abf34181..b77e525a21a 100644 --- a/ql/test/library-tests/ast/constants/constants.expected +++ b/ql/test/library-tests/ast/constants/constants.expected @@ -1,9 +1,9 @@ -| constants.rb:1:1:12:3 | ModuleA | write | ModuleA | Module | -| constants.rb:2:5:3:7 | ClassA | write | ClassA | Class | -| constants.rb:5:5:11:7 | ModuleB | write | ModuleB | Module | -| constants.rb:6:9:7:11 | ClassB | write | ClassB | Class | +| constants.rb:1:1:12:3 | ModuleA | write | ModuleA | ModuleDeclaration | +| constants.rb:2:5:3:7 | ClassA | write | ClassA | ClassDeclaration | +| constants.rb:5:5:11:7 | ModuleB | write | ModuleB | ModuleDeclaration | +| constants.rb:6:9:7:11 | ClassB | write | ClassB | ClassDeclaration | | constants.rb:6:24:6:27 | Base | read | Base | ConstantReadAccess | -| constants.rb:9:9:10:11 | ClassC | write | ClassC | Class | +| constants.rb:9:9:10:11 | ClassC | write | ClassC | ClassDeclaration | | constants.rb:9:24:9:24 | X | read | X | ConstantReadAccess | | constants.rb:9:24:9:27 | Y | read | Y | ConstantReadAccess | | constants.rb:9:24:9:30 | Z | read | Z | ConstantReadAccess | @@ -11,9 +11,9 @@ | constants.rb:17:5:17:9 | Names | write | Names | ConstantAssignment | | constants.rb:19:5:19:9 | Names | read | Names | ConstantReadAccess | | constants.rb:20:18:20:25 | GREETING | read | GREETING | ConstantReadAccess | -| constants.rb:28:1:29:3 | ClassD | write | ClassD | Class | +| constants.rb:28:1:29:3 | ClassD | write | ClassD | ClassDeclaration | | constants.rb:28:7:28:13 | ModuleA | read | ModuleA | ConstantReadAccess | -| constants.rb:31:1:32:3 | ModuleC | write | ModuleC | Module | +| constants.rb:31:1:32:3 | ModuleC | write | ModuleC | ModuleDeclaration | | constants.rb:31:8:31:14 | ModuleA | read | ModuleA | ConstantReadAccess | | constants.rb:34:1:34:7 | ModuleA | read | ModuleA | ConstantReadAccess | | constants.rb:34:1:34:16 | ModuleB | read | ModuleB | ConstantReadAccess | diff --git a/ql/test/library-tests/ast/modules/classes.expected b/ql/test/library-tests/ast/modules/classes.expected index 9eb7604f0df..0691684b668 100644 --- a/ql/test/library-tests/ast/modules/classes.expected +++ b/ql/test/library-tests/ast/modules/classes.expected @@ -1,17 +1,23 @@ classes -| classes.rb:3:1:4:3 | Foo | Class | Foo | -| classes.rb:7:1:8:3 | Bar | Class | Bar | -| classes.rb:11:1:12:3 | Baz | Class | Baz | -| classes.rb:16:1:17:3 | MyClass | Class | MyClass | -| classes.rb:20:1:37:3 | Wibble | Class | Wibble | -| classes.rb:32:3:33:5 | ClassInWibble | Class | ClassInWibble | -| classes.rb:55:1:56:3 | MyClassInGlobalScope | Class | MyClassInGlobalScope | -| modules.rb:6:5:7:7 | ClassInFooBar | Class | ClassInFooBar | -| modules.rb:19:3:20:5 | ClassInFoo | Class | ClassInFoo | -| modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | Class | ClassInAnotherDefinitionOfFoo | -| modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | Class | ClassInAnotherDefinitionOfFooBar | +| classes.rb:3:1:4:3 | Foo | ClassDeclaration | Foo | +| classes.rb:7:1:8:3 | Bar | ClassDeclaration | Bar | +| classes.rb:11:1:12:3 | Baz | ClassDeclaration | Baz | +| classes.rb:16:1:17:3 | MyClass | ClassDeclaration | MyClass | +| classes.rb:20:1:37:3 | Wibble | ClassDeclaration | Wibble | +| classes.rb:32:3:33:5 | ClassInWibble | ClassDeclaration | ClassInWibble | +| classes.rb:55:1:56:3 | MyClassInGlobalScope | ClassDeclaration | MyClassInGlobalScope | +| modules.rb:6:5:7:7 | ClassInFooBar | ClassDeclaration | ClassInFooBar | +| modules.rb:19:3:20:5 | ClassInFoo | ClassDeclaration | ClassInFoo | +| modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | ClassDeclaration | ClassInAnotherDefinitionOfFoo | +| modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | ClassDeclaration | ClassInAnotherDefinitionOfFooBar | +| modules.rb:66:5:67:7 | Bar | ClassDeclaration | Bar | +| modules.rb:72:5:73:7 | Bar | ClassDeclaration | Bar | +| modules.rb:78:5:79:7 | Bar | ClassDeclaration | Bar | classesWithNameScopeExprs | classes.rb:16:1:17:3 | MyClass | classes.rb:16:7:16:14 | MyModule | +| modules.rb:66:5:67:7 | Bar | modules.rb:66:11:66:14 | Foo1 | +| modules.rb:72:5:73:7 | Bar | modules.rb:72:11:72:14 | Foo2 | +| modules.rb:78:5:79:7 | Bar | modules.rb:78:11:78:14 | Foo3 | classesWithGlobalNameScopeExprs | classes.rb:55:1:56:3 | MyClassInGlobalScope | exprsInClasses @@ -19,8 +25,8 @@ exprsInClasses | classes.rb:20:1:37:3 | Wibble | 1 | classes.rb:25:3:27:5 | method_b | Method | | classes.rb:20:1:37:3 | Wibble | 2 | classes.rb:29:3:29:20 | call to some_method_call | MethodCall | | classes.rb:20:1:37:3 | Wibble | 3 | classes.rb:30:3:30:19 | ... = ... | AssignExpr | -| classes.rb:20:1:37:3 | Wibble | 4 | classes.rb:32:3:33:5 | ClassInWibble | Class | -| classes.rb:20:1:37:3 | Wibble | 5 | classes.rb:35:3:36:5 | ModuleInWibble | Module | +| classes.rb:20:1:37:3 | Wibble | 4 | classes.rb:32:3:33:5 | ClassInWibble | ClassDeclaration | +| classes.rb:20:1:37:3 | Wibble | 5 | classes.rb:35:3:36:5 | ModuleInWibble | ModuleDeclaration | methodsInClasses | classes.rb:20:1:37:3 | Wibble | classes.rb:21:3:23:5 | method_a | method_a | | classes.rb:20:1:37:3 | Wibble | classes.rb:25:3:27:5 | method_b | method_b | diff --git a/ql/test/library-tests/ast/modules/classes.ql b/ql/test/library-tests/ast/modules/classes.ql index 52d6ed21e51..a4b392a32cb 100644 --- a/ql/test/library-tests/ast/modules/classes.ql +++ b/ql/test/library-tests/ast/modules/classes.ql @@ -1,21 +1,29 @@ import ruby -query predicate classes(Class c, string pClass, string name) { +query predicate classes(ClassDeclaration c, string pClass, string name) { pClass = c.getAPrimaryQlClass() and name = c.getName() } -query predicate classesWithNameScopeExprs(Class c, Expr se) { se = c.getScopeExpr() } +query predicate classesWithNameScopeExprs(ClassDeclaration c, Expr se) { se = c.getScopeExpr() } -query predicate classesWithGlobalNameScopeExprs(Class c) { c.hasGlobalScope() } +query predicate classesWithGlobalNameScopeExprs(ClassDeclaration c) { c.hasGlobalScope() } -query predicate exprsInClasses(Class c, int i, Expr e, string eClass) { +query predicate exprsInClasses(ClassDeclaration c, int i, Expr e, string eClass) { e = c.getStmt(i) and eClass = e.getAPrimaryQlClass() } -query predicate methodsInClasses(Class c, Method m, string name) { m = c.getMethod(name) } +query predicate methodsInClasses(ClassDeclaration c, Method m, string name) { + m = c.getMethod(name) +} -query predicate classesInClasses(Class c, Class child, string name) { child = c.getClass(name) } +query predicate classesInClasses(ClassDeclaration c, ClassDeclaration child, string name) { + child = c.getClass(name) +} -query predicate modulesInClasses(Class c, Module m, string name) { m = c.getModule(name) } +query predicate modulesInClasses(ClassDeclaration c, ModuleDeclaration m, string name) { + m = c.getModule(name) +} -query predicate classesWithASuperclass(Class c, Expr scExpr) { scExpr = c.getSuperclassExpr() } +query predicate classesWithASuperclass(ClassDeclaration c, Expr scExpr) { + scExpr = c.getSuperclassExpr() +} diff --git a/ql/test/library-tests/ast/modules/module_base.expected b/ql/test/library-tests/ast/modules/module_base.expected index 1e26e369d5f..647f94c86f5 100644 --- a/ql/test/library-tests/ast/modules/module_base.expected +++ b/ql/test/library-tests/ast/modules/module_base.expected @@ -1,27 +1,41 @@ moduleBases | classes.rb:2:1:56:3 | classes.rb | Toplevel | -| classes.rb:3:1:4:3 | Foo | Class | -| classes.rb:7:1:8:3 | Bar | Class | -| classes.rb:11:1:12:3 | Baz | Class | -| classes.rb:15:1:15:20 | MyModule | Module | -| classes.rb:16:1:17:3 | MyClass | Class | -| classes.rb:20:1:37:3 | Wibble | Class | -| classes.rb:32:3:33:5 | ClassInWibble | Class | -| classes.rb:35:3:36:5 | ModuleInWibble | Module | -| classes.rb:41:1:52:3 | class << ... | Class | -| classes.rb:55:1:56:3 | MyClassInGlobalScope | Class | -| modules.rb:1:1:2:3 | Empty | Module | -| modules.rb:1:1:61:3 | modules.rb | Toplevel | -| modules.rb:4:1:24:3 | Foo | Module | -| modules.rb:5:3:14:5 | Bar | Module | -| modules.rb:6:5:7:7 | ClassInFooBar | Class | -| modules.rb:19:3:20:5 | ClassInFoo | Class | -| modules.rb:26:1:35:3 | Foo | Module | -| modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | Class | -| modules.rb:37:1:46:3 | Bar | Module | -| modules.rb:48:1:57:3 | Bar | Module | -| modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | Class | -| modules.rb:60:1:61:3 | MyModuleInGlobalScope | Module | +| classes.rb:3:1:4:3 | Foo | ClassDeclaration | +| classes.rb:7:1:8:3 | Bar | ClassDeclaration | +| classes.rb:11:1:12:3 | Baz | ClassDeclaration | +| classes.rb:15:1:15:20 | MyModule | ModuleDeclaration | +| classes.rb:16:1:17:3 | MyClass | ClassDeclaration | +| classes.rb:20:1:37:3 | Wibble | ClassDeclaration | +| classes.rb:32:3:33:5 | ClassInWibble | ClassDeclaration | +| classes.rb:35:3:36:5 | ModuleInWibble | ModuleDeclaration | +| classes.rb:41:1:52:3 | class << ... | ClassDeclaration | +| classes.rb:55:1:56:3 | MyClassInGlobalScope | ClassDeclaration | +| modules.rb:1:1:2:3 | Empty | ModuleDeclaration | +| modules.rb:1:1:99:3 | modules.rb | Toplevel | +| modules.rb:4:1:24:3 | Foo | ModuleDeclaration | +| modules.rb:5:3:14:5 | Bar | ModuleDeclaration | +| modules.rb:6:5:7:7 | ClassInFooBar | ClassDeclaration | +| modules.rb:19:3:20:5 | ClassInFoo | ClassDeclaration | +| modules.rb:26:1:35:3 | Foo | ModuleDeclaration | +| modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | ClassDeclaration | +| modules.rb:37:1:46:3 | Bar | ModuleDeclaration | +| modules.rb:48:1:57:3 | Bar | ModuleDeclaration | +| modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | ClassDeclaration | +| modules.rb:60:1:61:3 | MyModuleInGlobalScope | ModuleDeclaration | +| modules.rb:63:1:81:3 | Test | ModuleDeclaration | +| modules.rb:65:3:68:5 | Foo1 | ModuleDeclaration | +| modules.rb:66:5:67:7 | Bar | ClassDeclaration | +| modules.rb:70:3:74:5 | Foo2 | ModuleDeclaration | +| modules.rb:71:5:71:19 | Foo2 | ModuleDeclaration | +| modules.rb:72:5:73:7 | Bar | ClassDeclaration | +| modules.rb:76:3:80:5 | Foo3 | ModuleDeclaration | +| modules.rb:78:5:79:7 | Bar | ClassDeclaration | +| modules.rb:83:1:87:3 | IncludeTest | ModuleDeclaration | +| modules.rb:85:3:86:5 | Y | ModuleDeclaration | +| modules.rb:89:1:93:3 | IncludeTest2 | ModuleDeclaration | +| modules.rb:91:3:92:5 | Z | ModuleDeclaration | +| modules.rb:95:1:99:3 | PrependTest | ModuleDeclaration | +| modules.rb:97:3:98:5 | Y | ModuleDeclaration | | toplevel.rb:1:1:5:23 | toplevel.rb | Toplevel | moduleBaseClasses | classes.rb:2:1:56:3 | classes.rb | classes.rb:3:1:4:3 | Foo | @@ -35,6 +49,9 @@ moduleBaseClasses | modules.rb:5:3:14:5 | Bar | modules.rb:6:5:7:7 | ClassInFooBar | | modules.rb:26:1:35:3 | Foo | modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | | modules.rb:48:1:57:3 | Bar | modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | +| modules.rb:65:3:68:5 | Foo1 | modules.rb:66:5:67:7 | Bar | +| modules.rb:70:3:74:5 | Foo2 | modules.rb:72:5:73:7 | Bar | +| modules.rb:76:3:80:5 | Foo3 | modules.rb:78:5:79:7 | Bar | moduleBaseMethods | classes.rb:20:1:37:3 | Wibble | classes.rb:21:3:23:5 | method_a | | classes.rb:20:1:37:3 | Wibble | classes.rb:25:3:27:5 | method_b | @@ -49,10 +66,21 @@ moduleBaseMethods moduleBaseModules | classes.rb:2:1:56:3 | classes.rb | classes.rb:15:1:15:20 | MyModule | | classes.rb:20:1:37:3 | Wibble | classes.rb:35:3:36:5 | ModuleInWibble | -| modules.rb:1:1:61:3 | modules.rb | modules.rb:1:1:2:3 | Empty | -| modules.rb:1:1:61:3 | modules.rb | modules.rb:4:1:24:3 | Foo | -| modules.rb:1:1:61:3 | modules.rb | modules.rb:26:1:35:3 | Foo | -| modules.rb:1:1:61:3 | modules.rb | modules.rb:37:1:46:3 | Bar | -| modules.rb:1:1:61:3 | modules.rb | modules.rb:48:1:57:3 | Bar | -| modules.rb:1:1:61:3 | modules.rb | modules.rb:60:1:61:3 | MyModuleInGlobalScope | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:1:1:2:3 | Empty | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:4:1:24:3 | Foo | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:26:1:35:3 | Foo | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:37:1:46:3 | Bar | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:48:1:57:3 | Bar | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:60:1:61:3 | MyModuleInGlobalScope | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:63:1:81:3 | Test | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:83:1:87:3 | IncludeTest | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:89:1:93:3 | IncludeTest2 | +| modules.rb:1:1:99:3 | modules.rb | modules.rb:95:1:99:3 | PrependTest | | modules.rb:4:1:24:3 | Foo | modules.rb:5:3:14:5 | Bar | +| modules.rb:63:1:81:3 | Test | modules.rb:65:3:68:5 | Foo1 | +| modules.rb:63:1:81:3 | Test | modules.rb:70:3:74:5 | Foo2 | +| modules.rb:63:1:81:3 | Test | modules.rb:76:3:80:5 | Foo3 | +| modules.rb:70:3:74:5 | Foo2 | modules.rb:71:5:71:19 | Foo2 | +| modules.rb:83:1:87:3 | IncludeTest | modules.rb:85:3:86:5 | Y | +| modules.rb:89:1:93:3 | IncludeTest2 | modules.rb:91:3:92:5 | Z | +| modules.rb:95:1:99:3 | PrependTest | modules.rb:97:3:98:5 | Y | diff --git a/ql/test/library-tests/ast/modules/module_base.ql b/ql/test/library-tests/ast/modules/module_base.ql index e4e72ed1c69..e95faa62969 100644 --- a/ql/test/library-tests/ast/modules/module_base.ql +++ b/ql/test/library-tests/ast/modules/module_base.ql @@ -2,8 +2,8 @@ import ruby query predicate moduleBases(ModuleBase mb, string pClass) { pClass = mb.getAPrimaryQlClass() } -query predicate moduleBaseClasses(ModuleBase mb, Class c) { c = mb.getAClass() } +query predicate moduleBaseClasses(ModuleBase mb, ClassDeclaration c) { c = mb.getAClass() } query predicate moduleBaseMethods(ModuleBase mb, Method m) { m = mb.getAMethod() } -query predicate moduleBaseModules(ModuleBase mb, Module m) { m = mb.getAModule() } +query predicate moduleBaseModules(ModuleBase mb, ModuleDeclaration m) { m = mb.getAModule() } diff --git a/ql/test/library-tests/ast/modules/modules.expected b/ql/test/library-tests/ast/modules/modules.expected index b21ae05c813..fb8d891c4f2 100644 --- a/ql/test/library-tests/ast/modules/modules.expected +++ b/ql/test/library-tests/ast/modules/modules.expected @@ -1,39 +1,67 @@ modules -| classes.rb:15:1:15:20 | MyModule | Module | MyModule | -| classes.rb:35:3:36:5 | ModuleInWibble | Module | ModuleInWibble | -| modules.rb:1:1:2:3 | Empty | Module | Empty | -| modules.rb:4:1:24:3 | Foo | Module | Foo | -| modules.rb:5:3:14:5 | Bar | Module | Bar | -| modules.rb:26:1:35:3 | Foo | Module | Foo | -| modules.rb:37:1:46:3 | Bar | Module | Bar | -| modules.rb:48:1:57:3 | Bar | Module | Bar | -| modules.rb:60:1:61:3 | MyModuleInGlobalScope | Module | MyModuleInGlobalScope | +| classes.rb:15:1:15:20 | MyModule | ModuleDeclaration | MyModule | +| classes.rb:35:3:36:5 | ModuleInWibble | ModuleDeclaration | ModuleInWibble | +| modules.rb:1:1:2:3 | Empty | ModuleDeclaration | Empty | +| modules.rb:4:1:24:3 | Foo | ModuleDeclaration | Foo | +| modules.rb:5:3:14:5 | Bar | ModuleDeclaration | Bar | +| modules.rb:26:1:35:3 | Foo | ModuleDeclaration | Foo | +| modules.rb:37:1:46:3 | Bar | ModuleDeclaration | Bar | +| modules.rb:48:1:57:3 | Bar | ModuleDeclaration | Bar | +| modules.rb:60:1:61:3 | MyModuleInGlobalScope | ModuleDeclaration | MyModuleInGlobalScope | +| modules.rb:63:1:81:3 | Test | ModuleDeclaration | Test | +| modules.rb:65:3:68:5 | Foo1 | ModuleDeclaration | Foo1 | +| modules.rb:70:3:74:5 | Foo2 | ModuleDeclaration | Foo2 | +| modules.rb:71:5:71:19 | Foo2 | ModuleDeclaration | Foo2 | +| modules.rb:76:3:80:5 | Foo3 | ModuleDeclaration | Foo3 | +| modules.rb:83:1:87:3 | IncludeTest | ModuleDeclaration | IncludeTest | +| modules.rb:85:3:86:5 | Y | ModuleDeclaration | Y | +| modules.rb:89:1:93:3 | IncludeTest2 | ModuleDeclaration | IncludeTest2 | +| modules.rb:91:3:92:5 | Z | ModuleDeclaration | Z | +| modules.rb:95:1:99:3 | PrependTest | ModuleDeclaration | PrependTest | +| modules.rb:97:3:98:5 | Y | ModuleDeclaration | Y | modulesWithScopeExprs | modules.rb:48:1:57:3 | Bar | modules.rb:48:8:48:10 | Foo | +| modules.rb:85:3:86:5 | Y | modules.rb:85:10:85:13 | Foo1 | +| modules.rb:91:3:92:5 | Z | modules.rb:91:10:91:13 | Foo1 | +| modules.rb:97:3:98:5 | Y | modules.rb:97:10:97:13 | Foo2 | modulesWithGlobalNameScopeExprs | modules.rb:60:1:61:3 | MyModuleInGlobalScope | exprsInModules -| modules.rb:4:1:24:3 | Foo | 0 | modules.rb:5:3:14:5 | Bar | Module | +| modules.rb:4:1:24:3 | Foo | 0 | modules.rb:5:3:14:5 | Bar | ModuleDeclaration | | modules.rb:4:1:24:3 | Foo | 1 | modules.rb:16:3:17:5 | method_in_foo | Method | -| modules.rb:4:1:24:3 | Foo | 2 | modules.rb:19:3:20:5 | ClassInFoo | Class | +| modules.rb:4:1:24:3 | Foo | 2 | modules.rb:19:3:20:5 | ClassInFoo | ClassDeclaration | | modules.rb:4:1:24:3 | Foo | 3 | modules.rb:22:3:22:19 | call to puts | MethodCall | | modules.rb:4:1:24:3 | Foo | 4 | modules.rb:23:3:23:17 | ... = ... | AssignExpr | -| modules.rb:5:3:14:5 | Bar | 0 | modules.rb:6:5:7:7 | ClassInFooBar | Class | +| modules.rb:5:3:14:5 | Bar | 0 | modules.rb:6:5:7:7 | ClassInFooBar | ClassDeclaration | | modules.rb:5:3:14:5 | Bar | 1 | modules.rb:9:5:10:7 | method_in_foo_bar | Method | | modules.rb:5:3:14:5 | Bar | 2 | modules.rb:12:5:12:26 | call to puts | MethodCall | | modules.rb:5:3:14:5 | Bar | 3 | modules.rb:13:5:13:19 | ... = ... | AssignExpr | | modules.rb:26:1:35:3 | Foo | 0 | modules.rb:27:3:28:5 | method_in_another_definition_of_foo | Method | -| modules.rb:26:1:35:3 | Foo | 1 | modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | Class | +| modules.rb:26:1:35:3 | Foo | 1 | modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | ClassDeclaration | | modules.rb:26:1:35:3 | Foo | 2 | modules.rb:33:3:33:25 | call to puts | MethodCall | | modules.rb:26:1:35:3 | Foo | 3 | modules.rb:34:3:34:17 | ... = ... | AssignExpr | | modules.rb:37:1:46:3 | Bar | 0 | modules.rb:38:3:39:5 | method_a | Method | | modules.rb:37:1:46:3 | Bar | 1 | modules.rb:41:3:42:5 | method_b | Method | | modules.rb:37:1:46:3 | Bar | 2 | modules.rb:44:3:44:19 | call to puts | MethodCall | | modules.rb:37:1:46:3 | Bar | 3 | modules.rb:45:3:45:17 | ... = ... | AssignExpr | -| modules.rb:48:1:57:3 | Bar | 0 | modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | Class | +| modules.rb:48:1:57:3 | Bar | 0 | modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | ClassDeclaration | | modules.rb:48:1:57:3 | Bar | 1 | modules.rb:52:3:53:5 | method_in_another_definition_of_foo_bar | Method | | modules.rb:48:1:57:3 | Bar | 2 | modules.rb:55:3:55:30 | call to puts | MethodCall | | modules.rb:48:1:57:3 | Bar | 3 | modules.rb:56:3:56:17 | ... = ... | AssignExpr | +| modules.rb:63:1:81:3 | Test | 0 | modules.rb:65:3:68:5 | Foo1 | ModuleDeclaration | +| modules.rb:63:1:81:3 | Test | 1 | modules.rb:70:3:74:5 | Foo2 | ModuleDeclaration | +| modules.rb:63:1:81:3 | Test | 2 | modules.rb:76:3:80:5 | Foo3 | ModuleDeclaration | +| modules.rb:65:3:68:5 | Foo1 | 0 | modules.rb:66:5:67:7 | Bar | ClassDeclaration | +| modules.rb:70:3:74:5 | Foo2 | 0 | modules.rb:71:5:71:19 | Foo2 | ModuleDeclaration | +| modules.rb:70:3:74:5 | Foo2 | 1 | modules.rb:72:5:73:7 | Bar | ClassDeclaration | +| modules.rb:76:3:80:5 | Foo3 | 0 | modules.rb:77:5:77:17 | ... = ... | AssignExpr | +| modules.rb:76:3:80:5 | Foo3 | 1 | modules.rb:78:5:79:7 | Bar | ClassDeclaration | +| modules.rb:83:1:87:3 | IncludeTest | 0 | modules.rb:84:3:84:16 | call to include | MethodCall | +| modules.rb:83:1:87:3 | IncludeTest | 1 | modules.rb:85:3:86:5 | Y | ModuleDeclaration | +| modules.rb:89:1:93:3 | IncludeTest2 | 0 | modules.rb:90:3:90:14 | call to include | MethodCall | +| modules.rb:89:1:93:3 | IncludeTest2 | 1 | modules.rb:91:3:92:5 | Z | ModuleDeclaration | +| modules.rb:95:1:99:3 | PrependTest | 0 | modules.rb:96:3:96:16 | call to prepend | MethodCall | +| modules.rb:95:1:99:3 | PrependTest | 1 | modules.rb:97:3:98:5 | Y | ModuleDeclaration | methodsInModules | modules.rb:4:1:24:3 | Foo | modules.rb:16:3:17:5 | method_in_foo | method_in_foo | | modules.rb:5:3:14:5 | Bar | modules.rb:9:5:10:7 | method_in_foo_bar | method_in_foo_bar | @@ -46,5 +74,53 @@ classesInModules | modules.rb:5:3:14:5 | Bar | modules.rb:6:5:7:7 | ClassInFooBar | ClassInFooBar | | modules.rb:26:1:35:3 | Foo | modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | ClassInAnotherDefinitionOfFoo | | modules.rb:48:1:57:3 | Bar | modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | ClassInAnotherDefinitionOfFooBar | +| modules.rb:65:3:68:5 | Foo1 | modules.rb:66:5:67:7 | Bar | Bar | +| modules.rb:70:3:74:5 | Foo2 | modules.rb:72:5:73:7 | Bar | Bar | +| modules.rb:76:3:80:5 | Foo3 | modules.rb:78:5:79:7 | Bar | Bar | modulesInModules | modules.rb:4:1:24:3 | Foo | modules.rb:5:3:14:5 | Bar | Bar | +| modules.rb:63:1:81:3 | Test | modules.rb:65:3:68:5 | Foo1 | Foo1 | +| modules.rb:63:1:81:3 | Test | modules.rb:70:3:74:5 | Foo2 | Foo2 | +| modules.rb:63:1:81:3 | Test | modules.rb:76:3:80:5 | Foo3 | Foo3 | +| modules.rb:70:3:74:5 | Foo2 | modules.rb:71:5:71:19 | Foo2 | Foo2 | +| modules.rb:83:1:87:3 | IncludeTest | modules.rb:85:3:86:5 | Y | Y | +| modules.rb:89:1:93:3 | IncludeTest2 | modules.rb:91:3:92:5 | Z | Z | +| modules.rb:95:1:99:3 | PrependTest | modules.rb:97:3:98:5 | Y | Y | +moduleTypes +| classes.rb:2:1:56:3 | classes.rb | file://:0:0:0:0 | Object | +| classes.rb:3:1:4:3 | Foo | modules.rb:4:1:24:3 | Foo | +| classes.rb:7:1:8:3 | Bar | modules.rb:37:1:46:3 | Bar | +| classes.rb:11:1:12:3 | Baz | classes.rb:11:1:12:3 | Baz | +| classes.rb:15:1:15:20 | MyModule | classes.rb:15:1:15:20 | MyModule | +| classes.rb:16:1:17:3 | MyClass | classes.rb:16:1:17:3 | MyModule::MyClass | +| classes.rb:20:1:37:3 | Wibble | classes.rb:20:1:37:3 | Wibble | +| classes.rb:32:3:33:5 | ClassInWibble | classes.rb:32:3:33:5 | Wibble::ClassInWibble | +| classes.rb:35:3:36:5 | ModuleInWibble | classes.rb:35:3:36:5 | Wibble::ModuleInWibble | +| classes.rb:55:1:56:3 | MyClassInGlobalScope | classes.rb:55:1:56:3 | MyClassInGlobalScope | +| modules.rb:1:1:2:3 | Empty | modules.rb:1:1:2:3 | Empty | +| modules.rb:1:1:99:3 | modules.rb | file://:0:0:0:0 | Object | +| modules.rb:4:1:24:3 | Foo | modules.rb:4:1:24:3 | Foo | +| modules.rb:5:3:14:5 | Bar | modules.rb:5:3:14:5 | Foo::Bar | +| modules.rb:6:5:7:7 | ClassInFooBar | modules.rb:6:5:7:7 | Foo::Bar::ClassInFooBar | +| modules.rb:19:3:20:5 | ClassInFoo | modules.rb:19:3:20:5 | Foo::ClassInFoo | +| modules.rb:26:1:35:3 | Foo | modules.rb:4:1:24:3 | Foo | +| modules.rb:30:3:31:5 | ClassInAnotherDefinitionOfFoo | modules.rb:30:3:31:5 | Foo::ClassInAnotherDefinitionOfFoo | +| modules.rb:37:1:46:3 | Bar | modules.rb:37:1:46:3 | Bar | +| modules.rb:48:1:57:3 | Bar | modules.rb:5:3:14:5 | Foo::Bar | +| modules.rb:49:3:50:5 | ClassInAnotherDefinitionOfFooBar | modules.rb:49:3:50:5 | Foo::Bar::ClassInAnotherDefinitionOfFooBar | +| modules.rb:60:1:61:3 | MyModuleInGlobalScope | modules.rb:60:1:61:3 | MyModuleInGlobalScope | +| modules.rb:63:1:81:3 | Test | modules.rb:63:1:81:3 | Test | +| modules.rb:65:3:68:5 | Foo1 | modules.rb:65:3:68:5 | Test::Foo1 | +| modules.rb:66:5:67:7 | Bar | modules.rb:66:5:67:7 | Test::Foo1::Bar | +| modules.rb:70:3:74:5 | Foo2 | modules.rb:70:3:74:5 | Test::Foo2 | +| modules.rb:71:5:71:19 | Foo2 | modules.rb:71:5:71:19 | Test::Foo2::Foo2 | +| modules.rb:72:5:73:7 | Bar | modules.rb:72:5:73:7 | Test::Foo2::Foo2::Bar | +| modules.rb:76:3:80:5 | Foo3 | modules.rb:76:3:80:5 | Test::Foo3 | +| modules.rb:78:5:79:7 | Bar | modules.rb:37:1:46:3 | Bar | +| modules.rb:83:1:87:3 | IncludeTest | modules.rb:83:1:87:3 | IncludeTest | +| modules.rb:85:3:86:5 | Y | modules.rb:85:3:86:5 | Test::Foo1::Y | +| modules.rb:89:1:93:3 | IncludeTest2 | modules.rb:89:1:93:3 | IncludeTest2 | +| modules.rb:91:3:92:5 | Z | modules.rb:91:3:92:5 | Test::Foo1::Z | +| modules.rb:95:1:99:3 | PrependTest | modules.rb:95:1:99:3 | PrependTest | +| modules.rb:97:3:98:5 | Y | modules.rb:97:3:98:5 | Test::Foo2::Y | +| toplevel.rb:1:1:5:23 | toplevel.rb | file://:0:0:0:0 | Object | diff --git a/ql/test/library-tests/ast/modules/modules.ql b/ql/test/library-tests/ast/modules/modules.ql index cce336c8b5c..21adb23e633 100644 --- a/ql/test/library-tests/ast/modules/modules.ql +++ b/ql/test/library-tests/ast/modules/modules.ql @@ -1,25 +1,27 @@ import ruby -query predicate modules(Module m, string pClass, string name) { +query predicate modules(ModuleDeclaration m, string pClass, string name) { pClass = m.getAPrimaryQlClass() and name = m.getName() } -query predicate modulesWithScopeExprs(Module m, Expr se) { se = m.getScopeExpr() } +query predicate modulesWithScopeExprs(ModuleDeclaration m, Expr se) { se = m.getScopeExpr() } -query predicate modulesWithGlobalNameScopeExprs(Module m) { m.hasGlobalScope() } +query predicate modulesWithGlobalNameScopeExprs(ModuleDeclaration m) { m.hasGlobalScope() } -query predicate exprsInModules(Module m, int i, Expr e, string eClass) { +query predicate exprsInModules(ModuleDeclaration m, int i, Expr e, string eClass) { e = m.getStmt(i) and eClass = e.getAPrimaryQlClass() } -query predicate methodsInModules(Module mod, Method method, string name) { +query predicate methodsInModules(ModuleDeclaration mod, Method method, string name) { method = mod.getMethod(name) } -query predicate classesInModules(Module mod, Class klass, string name) { +query predicate classesInModules(ModuleDeclaration mod, ClassDeclaration klass, string name) { klass = mod.getClass(name) } -query predicate modulesInModules(Module mod, Module child, string name) { +query predicate modulesInModules(ModuleDeclaration mod, ModuleDeclaration child, string name) { child = mod.getModule(name) } + +query predicate moduleTypes(ModuleBase def, Module type) { type = def.getModule() } diff --git a/ql/test/library-tests/ast/modules/modules.rb b/ql/test/library-tests/ast/modules/modules.rb index dfba11f8d6e..f1e08d1bf47 100644 --- a/ql/test/library-tests/ast/modules/modules.rb +++ b/ql/test/library-tests/ast/modules/modules.rb @@ -58,4 +58,42 @@ end # a module where the name is a scope resolution using the global scope module ::MyModuleInGlobalScope +end + +module Test + + module Foo1 + class Foo1::Bar + end + end + + module Foo2 + module Foo2 end + class Foo2::Bar + end + end + + module Foo3 + Foo3 = Object + class Foo3::Bar + end + end +end + +module IncludeTest + include ::Test + module Foo1::Y + end +end + +module IncludeTest2 + include Test + module Foo1::Z + end +end + +module PrependTest + prepend ::Test + module Foo2::Y + end end \ No newline at end of file diff --git a/ql/test/library-tests/ast/modules/singleton_classes.expected b/ql/test/library-tests/ast/modules/singleton_classes.expected index 845afe551e7..f1c13b476d6 100644 --- a/ql/test/library-tests/ast/modules/singleton_classes.expected +++ b/ql/test/library-tests/ast/modules/singleton_classes.expected @@ -1,5 +1,5 @@ singletonClasses -| classes.rb:41:1:52:3 | class << ... | Class | classes.rb:41:10:41:10 | x | +| classes.rb:41:1:52:3 | class << ... | ClassDeclaration | classes.rb:41:10:41:10 | x | exprsInSingletonClasses | classes.rb:41:1:52:3 | class << ... | 0 | classes.rb:42:3:44:5 | length | Method | | classes.rb:41:1:52:3 | class << ... | 1 | classes.rb:46:3:48:5 | wibble | Method | diff --git a/ql/test/library-tests/ast/modules/toplevel.expected b/ql/test/library-tests/ast/modules/toplevel.expected index 9ea0f83b3df..e189e08db1b 100644 --- a/ql/test/library-tests/ast/modules/toplevel.expected +++ b/ql/test/library-tests/ast/modules/toplevel.expected @@ -1,6 +1,6 @@ toplevel | classes.rb:2:1:56:3 | classes.rb | Toplevel | -| modules.rb:1:1:61:3 | modules.rb | Toplevel | +| modules.rb:1:1:99:3 | modules.rb | Toplevel | | toplevel.rb:1:1:5:23 | toplevel.rb | Toplevel | beginBlocks | toplevel.rb:1:1:5:23 | toplevel.rb | 0 | toplevel.rb:5:1:5:22 | BEGIN { ... } |