From 452a343e86a53ff4a39fbda5f1ae12a2a9367519 Mon Sep 17 00:00:00 2001 From: Nick Rolfe Date: Wed, 10 Feb 2021 17:53:13 +0000 Subject: [PATCH] Remove ScopeResolution from AST Now we handle it specially in calls and class/module names, so they have predicate to get the scope expr. --- ql/src/codeql_ruby/ast/Call.qll | 35 +- ql/src/codeql_ruby/ast/Expr.qll | 33 -- ql/src/codeql_ruby/ast/Module.qll | 62 +++- ql/src/codeql_ruby/ast/internal/Call.qll | 57 ++- ql/src/codeql_ruby/ast/internal/Expr.qll | 12 - ql/src/codeql_ruby/ast/internal/Module.qll | 28 +- ql/src/codeql_ruby/ast/internal/Variable.qll | 4 +- .../ast/calls/arguments.expected | 15 +- .../library-tests/ast/calls/calls.expected | 341 +++++++++++------- ql/test/library-tests/ast/calls/calls.ql | 6 +- ql/test/library-tests/ast/calls/calls.rb | 91 ++++- .../ast/modules/classes.expected | 6 +- ql/test/library-tests/ast/modules/classes.ql | 6 +- ql/test/library-tests/ast/modules/classes.rb | 4 + .../ast/modules/module_base.expected | 2 + .../ast/modules/modules.expected | 6 +- ql/test/library-tests/ast/modules/modules.ql | 6 +- ql/test/library-tests/ast/modules/modules.rb | 4 + 18 files changed, 473 insertions(+), 245 deletions(-) diff --git a/ql/src/codeql_ruby/ast/Call.qll b/ql/src/codeql_ruby/ast/Call.qll index 2f75be0b1f0..acc77bf2012 100644 --- a/ql/src/codeql_ruby/ast/Call.qll +++ b/ql/src/codeql_ruby/ast/Call.qll @@ -22,14 +22,16 @@ class Call extends Expr { /** * Gets the name of the method being called. For example, in: + * * ```rb * foo.bar x, y * ``` * the result is `"bar"`. * - * N.B. in the following example, where the method name is a scope - * resolution, the result is the name being resolved, i.e. `"bar"`. Use - * `getMethodScopeResolution` to get the complete `ScopeResolution`. + * N.B. in the following example, where the method name uses the scope + * resolution operator, the result is the name being resolved, i.e. `"bar"`. + * Use `getMethodNameScopeExpr` to get the expression for `Foo`. + * * ```rb * Foo::bar x, y * ``` @@ -37,14 +39,33 @@ class Call extends Expr { final string getMethodName() { result = range.getMethodName() } /** - * Gets the scope resolution of this call, if any. In the following example, - * the result is the `ScopeResolution` for `Foo::bar`, while - * `getMethodName()` returns `"bar"`. + * Gets the scope expression used in the method name's scope resolution + * operation, if any. + * + * In the following example, the result is the `Expr` for `Foo`. + * * ```rb * Foo::bar() * ``` + * + * However, there is no result for the following example, since there is no + * scope resolution operation. + * + * ```rb + * baz() + * ``` */ - final ScopeResolution getMethodScopeResolution() { result = range.getMethodScopeResolution() } + final Expr getMethodNameScopeExpr() { result = range.getMethodNameScopeExpr() } + + /** + * Holds if the method name uses the scope resolution operator to access the + * global scope, as in this example: + * + * ```rb + * ::foo + * ``` + */ + final predicate methodNameHasGlobalScope() { range.methodNameHasGlobalScope() } /** * Gets the `n`th argument of this method call. In the following example, the diff --git a/ql/src/codeql_ruby/ast/Expr.qll b/ql/src/codeql_ruby/ast/Expr.qll index 4cfcd2ce836..5307b7b8db1 100644 --- a/ql/src/codeql_ruby/ast/Expr.qll +++ b/ql/src/codeql_ruby/ast/Expr.qll @@ -168,39 +168,6 @@ class ParenthesizedExpr extends ExprSequence, @parenthesized_statements { final override string getAPrimaryQlClass() { result = "ParenthesizedExpr" } } -/** - * A scope resolution, typically used to access constants defined in a class or - * module. - * ```rb - * Foo::Bar - * ``` - */ -class ScopeResolution extends Expr, @scope_resolution { - final override ScopeResolution::Range range; - - final override string getAPrimaryQlClass() { result = "ScopeResolution" } - - /** - * Gets the expression representing the scope, if any. In the following - * example, the scope is the `Expr` for `Foo`: - * ```rb - * Foo::Bar - * ``` - * However, in the following example, accessing the `Bar` constant in the - * `Object` class, there is no result: - * ```rb - * ::Bar - * ``` - */ - final Expr getScope() { result = range.getScope() } - - /** - * Gets the name being resolved. For example, in `Foo::Bar`, the result is - * `"Bar"`. - */ - final string getName() { result = range.getName() } -} - /** * A pair expression. For example, in a hash: * ```rb diff --git a/ql/src/codeql_ruby/ast/Module.qll b/ql/src/codeql_ruby/ast/Module.qll index 1c5e404c431..46d47868c69 100644 --- a/ql/src/codeql_ruby/ast/Module.qll +++ b/ql/src/codeql_ruby/ast/Module.qll @@ -49,9 +49,8 @@ class Class extends ModuleBase { * end * ``` * - * N.B. in the following example, where the class name is a scope resolution, - * the result is the name being resolved, i.e. `"Bar"`. Use - * `getScopeResolutionName` to get the complete `ScopeResolution`. + * N.B. in the following example, where the class name uses the scope + * resolution operator, the result is the name being resolved, i.e. `"Bar"`. Use `getNameScopeExpr` to get the `Foo` for `Foo`. * ```rb * class Foo::Bar * end @@ -60,22 +59,36 @@ class Class extends ModuleBase { final string getName() { result = range.getName() } /** - * Gets the scope resolution used to define the class name, if any. In the - * following example, the result is the `ScopeResolution` for `Foo::Bar`, - * while `getName()` returns `"Bar"`. + * Gets the scope expression used in the class name's scope resolution + * operation, if any. + * + * In the following example, the result is the `Expr` for `Foo`. + * * ```rb * class Foo::Bar * end * ``` * - * In the following example, the name is not a scope resolution, so there is - * no result. + * However, there is no result for the following example, since there is no + * scope resolution operation. + * * ```rb * class Baz * end * ``` */ - final ScopeResolution getNameScopeResolution() { result = range.getNameScopeResolution() } + final Expr getNameScopeExpr() { result = range.getNameScopeExpr() } + + /** + * Holds if the class name uses the scope resolution operator to access the + * global scope, as in this example: + * + * ```rb + * class ::Foo + * end + * ``` + */ + final predicate nameHasGlobalScope() { range.nameHasGlobalScope() } /** * Gets the `Expr` used as the superclass in the class definition, if any. @@ -158,9 +171,8 @@ class Module extends ModuleBase, @module { * end * ``` * - * N.B. in the following example, where the module name is a scope - * resolution, the result is the name being resolved, i.e. `"Bar"`. Use - * `getScopeResolutionName` to get the complete `ScopeResolution`. + * N.B. in the following example, where the module name uses the scope + * resolution operator, the result is the name being resolved, i.e. `"Bar"`. Use `getNameScopeExpr` to get the `Expr` for `Foo`. * ```rb * module Foo::Bar * end @@ -169,20 +181,34 @@ class Module extends ModuleBase, @module { final string getName() { result = range.getName() } /** - * Gets the scope resolution used to define the module name, if any. In the - * following example, the result is the `ScopeResolution` for `Foo::Bar`, - * while `getName()` returns `"bar"`. + * Gets the scope expression used in the module name's scope resolution + * operation, if any. + * + * In the following example, the result is the `Expr` for `Foo`. + * * ```rb * module Foo::Bar * end * ``` * - * In the following example, the name is not a scope resolution, so this - * predicate has no result: + * However, there is no result for the following example, since there is no + * scope resolution operation. + * * ```rb * module Baz * end * ``` */ - final ScopeResolution getNameScopeResolution() { result = range.getNameScopeResolution() } + final Expr getNameScopeExpr() { result = range.getNameScopeExpr() } + + /** + * Holds if the module name uses the scope resolution operator to access the + * global scope, as in this example: + * + * ```rb + * class ::Foo + * end + * ``` + */ + final predicate nameHasGlobalScope() { range.nameHasGlobalScope() } } diff --git a/ql/src/codeql_ruby/ast/internal/Call.qll b/ql/src/codeql_ruby/ast/internal/Call.qll index 88b68831021..e2da0f0792b 100644 --- a/ql/src/codeql_ruby/ast/internal/Call.qll +++ b/ql/src/codeql_ruby/ast/internal/Call.qll @@ -9,7 +9,9 @@ module Call { abstract string getMethodName(); - abstract ScopeResolution getMethodScopeResolution(); + abstract Expr getMethodNameScopeExpr(); + + abstract predicate methodNameHasGlobalScope(); abstract Expr getArgument(int n); @@ -27,7 +29,32 @@ module Call { final override string getMethodName() { result = generated.getValue() } - final override ScopeResolution getMethodScopeResolution() { none() } + final override Expr getMethodNameScopeExpr() { none() } + + final override predicate methodNameHasGlobalScope() { none() } + + final override Expr getArgument(int n) { none() } + + final override Block getBlock() { none() } + } + + private class ScopeResolutionIdentifierCallRange extends Call::Range, @scope_resolution { + final override Generated::ScopeResolution generated; + Generated::Identifier identifier; + + ScopeResolutionIdentifierCallRange() { + identifier = generated.getName() and + vcall(this) and + not access(identifier, _) + } + + final override Expr getReceiver() { none() } + + final override string getMethodName() { result = identifier.getValue() } + + final override Expr getMethodNameScopeExpr() { result = generated.getScope() } + + final override predicate methodNameHasGlobalScope() { not exists(generated.getScope()) } final override Expr getArgument(int n) { none() } @@ -41,10 +68,20 @@ module Call { final override string getMethodName() { result = generated.getMethod().(Generated::Token).getValue() or - result = this.getMethodScopeResolution().getName() + result = + generated.getMethod().(Generated::ScopeResolution).getName().(Generated::Token).getValue() } - final override ScopeResolution getMethodScopeResolution() { result = generated.getMethod() } + final override Expr getMethodNameScopeExpr() { + result = generated.getMethod().(Generated::ScopeResolution).getScope() + } + + final override predicate methodNameHasGlobalScope() { + exists(Generated::ScopeResolution sr | + sr = generated.getMethod() and + not exists(sr.getScope()) + ) + } final override Expr getArgument(int n) { result = generated.getArguments().getChild(n) } @@ -60,7 +97,9 @@ module YieldCall { final override string getMethodName() { result = "yield" } - final override ScopeResolution getMethodScopeResolution() { none() } + final override Expr getMethodNameScopeExpr() { none() } + + final override predicate methodNameHasGlobalScope() { none() } final override Expr getArgument(int n) { result = generated.getChild().getChild(n) } @@ -82,7 +121,9 @@ module SuperCall { final override string getMethodName() { result = generated.getValue() } - final override ScopeResolution getMethodScopeResolution() { none() } + final override Expr getMethodNameScopeExpr() { none() } + + final override predicate methodNameHasGlobalScope() { none() } final override Expr getArgument(int n) { none() } @@ -100,7 +141,9 @@ module SuperCall { result = generated.getMethod().(Generated::Super).getValue() } - final override ScopeResolution getMethodScopeResolution() { none() } + final override Expr getMethodNameScopeExpr() { none() } + + final override predicate methodNameHasGlobalScope() { none() } final override Expr getArgument(int n) { result = generated.getArguments().getChild(n) } diff --git a/ql/src/codeql_ruby/ast/internal/Expr.qll b/ql/src/codeql_ruby/ast/internal/Expr.qll index 4b93421ce7f..1349b8f84cd 100644 --- a/ql/src/codeql_ruby/ast/internal/Expr.qll +++ b/ql/src/codeql_ruby/ast/internal/Expr.qll @@ -227,18 +227,6 @@ module DoExpr { } } -module ScopeResolution { - class Range extends Expr::Range, @scope_resolution { - final override Generated::ScopeResolution generated; - - final Expr getScope() { result = generated.getScope() } - - final string getName() { result = generated.getName().(Generated::Token).getValue() } - - final override string toString() { result = "...::" + this.getName() } - } -} - module Pair { class Range extends Expr::Range, @pair { final override Generated::Pair generated; diff --git a/ql/src/codeql_ruby/ast/internal/Module.qll b/ql/src/codeql_ruby/ast/internal/Module.qll index e0a4a3d65ab..675dfc52a00 100644 --- a/ql/src/codeql_ruby/ast/internal/Module.qll +++ b/ql/src/codeql_ruby/ast/internal/Module.qll @@ -14,10 +14,20 @@ module Class { final string getName() { result = generated.getName().(Generated::Token).getValue() or - result = this.getNameScopeResolution().getName() + result = + generated.getName().(Generated::ScopeResolution).getName().(Generated::Token).getValue() } - final ScopeResolution getNameScopeResolution() { result = generated.getName() } + final Expr getNameScopeExpr() { + result = generated.getName().(Generated::ScopeResolution).getScope() + } + + final predicate nameHasGlobalScope() { + exists(Generated::ScopeResolution sr | + sr = generated.getName() and + not exists(sr.getScope()) + ) + } final Expr getSuperclassExpr() { result = generated.getSuperclass().getChild() } @@ -45,10 +55,20 @@ module Module { final string getName() { result = generated.getName().(Generated::Token).getValue() or - result = this.getNameScopeResolution().getName() + result = + generated.getName().(Generated::ScopeResolution).getName().(Generated::Token).getValue() } - final ScopeResolution getNameScopeResolution() { result = generated.getName() } + final Expr getNameScopeExpr() { + result = generated.getName().(Generated::ScopeResolution).getScope() + } + + final predicate nameHasGlobalScope() { + exists(Generated::ScopeResolution sr | + sr = generated.getName() and + not exists(sr.getScope()) + ) + } final override string toString() { result = this.getName() } } diff --git a/ql/src/codeql_ruby/ast/internal/Variable.qll b/ql/src/codeql_ruby/ast/internal/Variable.qll index 1deed56915e..687a0b2e6b6 100644 --- a/ql/src/codeql_ruby/ast/internal/Variable.qll +++ b/ql/src/codeql_ruby/ast/internal/Variable.qll @@ -165,8 +165,8 @@ private module Cached { not scope.inherits(name, _) } - // Token types that can be vcalls - private class VcallToken = @token_identifier or @token_super; + // Db types that can be vcalls + private class VcallToken = @scope_resolution or @token_identifier or @token_super; /** * Holds if `i` is an `identifier` node occurring in the context where it diff --git a/ql/test/library-tests/ast/calls/arguments.expected b/ql/test/library-tests/ast/calls/arguments.expected index 39c53ae071d..0836c1ed810 100644 --- a/ql/test/library-tests/ast/calls/arguments.expected +++ b/ql/test/library-tests/ast/calls/arguments.expected @@ -1,10 +1,15 @@ blockArguments -| calls.rb:201:5:201:8 | &... | calls.rb:201:6:201:8 | call to bar | +| calls.rb:268:5:268:8 | &... | calls.rb:268:6:268:8 | call to bar | +| calls.rb:269:5:269:11 | &... | calls.rb:269:6:269:11 | call to bar | splatArguments -| calls.rb:204:5:204:8 | *... | calls.rb:204:6:204:8 | call to bar | +| calls.rb:272:5:272:8 | *... | calls.rb:272:6:272:8 | call to bar | +| calls.rb:273:5:273:11 | *... | calls.rb:273:6:273:11 | call to bar | hashSplatArguments -| calls.rb:207:5:207:9 | **... | calls.rb:207:7:207:9 | call to bar | +| calls.rb:276:5:276:9 | **... | calls.rb:276:7:276:9 | call to bar | +| calls.rb:277:5:277:12 | **... | calls.rb:277:7:277:12 | call to bar | keywordArguments -| calls.rb:210:5:210:13 | Pair | calls.rb:210:5:210:8 | :blah | calls.rb:210:11:210:13 | call to bar | +| calls.rb:280:5:280:13 | Pair | calls.rb:280:5:280:8 | :blah | calls.rb:280:11:280:13 | call to bar | +| calls.rb:281:5:281:16 | Pair | calls.rb:281:5:281:8 | :blah | calls.rb:281:11:281:16 | call to bar | keywordArgumentsByKeyword -| calls.rb:210:1:210:14 | call to foo | blah | calls.rb:210:11:210:13 | call to bar | +| calls.rb:280:1:280:14 | call to foo | blah | calls.rb:280:11:280:13 | call to bar | +| calls.rb:281:1:281:17 | call to foo | blah | calls.rb:281:11:281:16 | call to bar | diff --git a/ql/test/library-tests/ast/calls/calls.expected b/ql/test/library-tests/ast/calls/calls.expected index 72591f575a8..1d5eb7990ea 100644 --- a/ql/test/library-tests/ast/calls/calls.expected +++ b/ql/test/library-tests/ast/calls/calls.expected @@ -1,144 +1,217 @@ callsWithNoReceiverArgumentsOrBlock | calls.rb:2:1:2:5 | call to foo | foo | | calls.rb:5:1:5:10 | call to bar | bar | -| calls.rb:28:3:28:7 | call to yield | yield | -| calls.rb:42:1:42:3 | call to foo | foo | -| calls.rb:45:2:45:4 | call to foo | foo | -| calls.rb:48:11:48:13 | call to foo | foo | -| calls.rb:51:2:51:4 | call to foo | foo | -| calls.rb:54:8:54:10 | call to foo | foo | -| calls.rb:57:9:57:11 | call to bar | bar | -| calls.rb:60:8:60:10 | call to foo | foo | -| calls.rb:60:13:60:15 | call to bar | bar | -| calls.rb:64:3:64:5 | call to foo | foo | -| calls.rb:68:9:68:11 | call to foo | foo | -| calls.rb:71:7:71:9 | call to foo | foo | -| calls.rb:74:1:74:3 | call to foo | foo | -| calls.rb:74:7:74:9 | call to bar | bar | -| calls.rb:77:2:77:4 | call to foo | foo | -| calls.rb:80:9:80:11 | call to bar | bar | -| calls.rb:83:10:83:12 | call to bar | bar | -| calls.rb:86:1:86:3 | call to foo | foo | -| calls.rb:90:6:90:8 | call to foo | foo | -| calls.rb:91:6:91:8 | call to bar | bar | -| calls.rb:92:3:92:5 | call to baz | baz | -| calls.rb:97:3:97:5 | call to foo | foo | -| calls.rb:101:17:101:19 | call to foo | foo | -| calls.rb:105:10:105:12 | call to foo | foo | -| calls.rb:106:3:106:5 | call to bar | bar | -| calls.rb:111:3:111:5 | call to foo | foo | -| calls.rb:115:5:115:7 | call to foo | foo | -| calls.rb:116:3:116:5 | call to bar | bar | -| calls.rb:120:40:120:42 | call to foo | foo | -| calls.rb:124:40:124:42 | call to foo | foo | -| calls.rb:129:3:129:5 | call to foo | foo | -| calls.rb:133:1:133:3 | call to foo | foo | -| calls.rb:133:7:133:9 | call to bar | bar | -| calls.rb:133:13:133:15 | call to baz | baz | -| calls.rb:136:4:136:6 | call to foo | foo | -| calls.rb:137:3:137:8 | call to wibble | wibble | -| calls.rb:138:7:138:9 | call to bar | bar | -| calls.rb:139:3:139:8 | call to wobble | wobble | -| calls.rb:141:3:141:8 | call to wabble | wabble | -| calls.rb:145:1:145:3 | call to bar | bar | -| calls.rb:145:8:145:10 | call to foo | foo | -| calls.rb:148:8:148:10 | call to foo | foo | -| calls.rb:149:3:149:5 | call to bar | bar | -| calls.rb:153:1:153:3 | call to bar | bar | -| calls.rb:153:12:153:14 | call to foo | foo | -| calls.rb:156:7:156:9 | call to foo | foo | -| calls.rb:157:3:157:5 | call to bar | bar | -| calls.rb:161:1:161:3 | call to bar | bar | -| calls.rb:161:11:161:13 | call to foo | foo | -| calls.rb:164:7:164:9 | call to foo | foo | -| calls.rb:165:3:165:5 | call to bar | bar | -| calls.rb:169:1:169:3 | call to bar | bar | -| calls.rb:169:11:169:13 | call to foo | foo | -| calls.rb:172:10:172:12 | call to bar | bar | -| calls.rb:173:3:173:5 | call to baz | baz | -| calls.rb:177:1:177:3 | call to foo | foo | -| calls.rb:177:5:177:7 | call to bar | bar | -| calls.rb:180:8:180:10 | call to bar | bar | -| calls.rb:183:1:183:3 | call to foo | foo | -| calls.rb:186:1:186:3 | call to foo | foo | -| calls.rb:186:6:186:8 | call to bar | bar | -| calls.rb:189:3:189:5 | call to foo | foo | -| calls.rb:189:10:189:12 | call to bar | bar | -| calls.rb:193:8:193:10 | call to foo | foo | -| calls.rb:194:8:194:10 | call to bar | bar | -| calls.rb:198:1:198:3 | call to foo | foo | -| calls.rb:198:12:198:14 | call to bar | bar | -| calls.rb:201:6:201:8 | call to bar | bar | -| calls.rb:204:6:204:8 | call to bar | bar | -| calls.rb:207:7:207:9 | call to bar | bar | -| calls.rb:210:11:210:13 | call to bar | bar | -| calls.rb:217:5:217:9 | call to super | super | -| calls.rb:218:5:218:11 | call to super | super | -| calls.rb:234:5:234:7 | call to foo | foo | -| calls.rb:235:5:235:14 | call to super | super | -| calls.rb:236:5:236:9 | call to super | super | -callsWithScopeResolutionName -| calls.rb:5:1:5:10 | call to bar | calls.rb:5:1:5:8 | ...::bar | +| calls.rb:8:1:8:7 | call to bar | bar | +| calls.rb:31:3:31:7 | call to yield | yield | +| calls.rb:46:1:46:3 | call to foo | foo | +| calls.rb:47:1:47:6 | call to foo | foo | +| calls.rb:50:2:50:4 | call to foo | foo | +| calls.rb:51:2:51:7 | call to foo | foo | +| calls.rb:54:11:54:13 | call to foo | foo | +| calls.rb:55:11:55:16 | call to foo | foo | +| calls.rb:58:2:58:4 | call to foo | foo | +| calls.rb:59:2:59:7 | call to foo | foo | +| calls.rb:62:8:62:10 | call to foo | foo | +| calls.rb:63:8:63:13 | call to foo | foo | +| calls.rb:66:9:66:11 | call to bar | bar | +| calls.rb:67:9:67:14 | call to bar | bar | +| calls.rb:70:8:70:10 | call to foo | foo | +| calls.rb:70:13:70:18 | call to bar | bar | +| calls.rb:74:3:74:5 | call to foo | foo | +| calls.rb:75:3:75:8 | call to foo | foo | +| calls.rb:79:9:79:11 | call to foo | foo | +| calls.rb:79:14:79:19 | call to bar | bar | +| calls.rb:82:7:82:9 | call to foo | foo | +| calls.rb:82:12:82:17 | call to bar | bar | +| calls.rb:85:1:85:3 | call to foo | foo | +| calls.rb:85:7:85:12 | call to bar | bar | +| calls.rb:88:2:88:4 | call to foo | foo | +| calls.rb:89:2:89:7 | call to bar | bar | +| calls.rb:92:9:92:11 | call to bar | bar | +| calls.rb:92:14:92:19 | call to baz | baz | +| calls.rb:96:3:96:5 | call to bar | bar | +| calls.rb:97:3:97:8 | call to baz | baz | +| calls.rb:101:1:101:3 | call to foo | foo | +| calls.rb:102:1:102:3 | call to bar | bar | +| calls.rb:106:6:106:8 | call to foo | foo | +| calls.rb:107:6:107:8 | call to bar | bar | +| calls.rb:108:3:108:5 | call to baz | baz | +| calls.rb:110:6:110:11 | call to foo | foo | +| calls.rb:111:6:111:11 | call to bar | bar | +| calls.rb:112:3:112:8 | call to baz | baz | +| calls.rb:117:3:117:5 | call to foo | foo | +| calls.rb:118:3:118:8 | call to bar | bar | +| calls.rb:122:17:122:19 | call to foo | foo | +| calls.rb:124:18:124:23 | call to foo | foo | +| calls.rb:128:10:128:12 | call to foo | foo | +| calls.rb:129:3:129:5 | call to bar | bar | +| calls.rb:131:10:131:15 | call to foo | foo | +| calls.rb:132:3:132:8 | call to bar | bar | +| calls.rb:137:3:137:5 | call to foo | foo | +| calls.rb:138:3:138:8 | call to bar | bar | +| calls.rb:142:5:142:7 | call to foo | foo | +| calls.rb:143:3:143:5 | call to bar | bar | +| calls.rb:146:3:146:8 | call to bar | bar | +| calls.rb:150:40:150:42 | call to foo | foo | +| calls.rb:152:41:152:46 | call to foo | foo | +| calls.rb:156:40:156:42 | call to foo | foo | +| calls.rb:158:41:158:46 | call to foo | foo | +| calls.rb:163:3:163:5 | call to foo | foo | +| calls.rb:164:3:164:8 | call to bar | bar | +| calls.rb:168:1:168:3 | call to foo | foo | +| calls.rb:168:7:168:9 | call to bar | bar | +| calls.rb:168:13:168:15 | call to baz | baz | +| calls.rb:169:1:169:6 | call to foo | foo | +| calls.rb:169:10:169:15 | call to bar | bar | +| calls.rb:169:19:169:24 | call to baz | baz | +| calls.rb:172:4:172:6 | call to foo | foo | +| calls.rb:173:3:173:8 | call to wibble | wibble | +| calls.rb:174:7:174:9 | call to bar | bar | +| calls.rb:175:3:175:8 | call to wobble | wobble | +| calls.rb:177:3:177:8 | call to wabble | wabble | +| calls.rb:179:4:179:9 | call to foo | foo | +| calls.rb:180:3:180:11 | call to wibble | wibble | +| calls.rb:181:7:181:12 | call to bar | bar | +| calls.rb:182:3:182:11 | call to wobble | wobble | +| calls.rb:184:3:184:11 | call to wabble | wabble | +| calls.rb:188:1:188:3 | call to bar | bar | +| calls.rb:188:8:188:10 | call to foo | foo | +| calls.rb:189:1:189:6 | call to bar | bar | +| calls.rb:189:11:189:16 | call to foo | foo | +| calls.rb:192:8:192:10 | call to foo | foo | +| calls.rb:193:3:193:5 | call to bar | bar | +| calls.rb:195:8:195:13 | call to foo | foo | +| calls.rb:196:3:196:8 | call to bar | bar | +| calls.rb:200:1:200:3 | call to bar | bar | +| calls.rb:200:12:200:14 | call to foo | foo | +| calls.rb:201:1:201:6 | call to bar | bar | +| calls.rb:201:15:201:20 | call to foo | foo | +| calls.rb:204:7:204:9 | call to foo | foo | +| calls.rb:205:3:205:5 | call to bar | bar | +| calls.rb:207:7:207:12 | call to foo | foo | +| calls.rb:208:3:208:8 | call to bar | bar | +| calls.rb:212:1:212:3 | call to bar | bar | +| calls.rb:212:11:212:13 | call to foo | foo | +| calls.rb:213:1:213:6 | call to bar | bar | +| calls.rb:213:14:213:19 | call to foo | foo | +| calls.rb:216:7:216:9 | call to foo | foo | +| calls.rb:217:3:217:5 | call to bar | bar | +| calls.rb:219:7:219:12 | call to foo | foo | +| calls.rb:220:3:220:8 | call to bar | bar | +| calls.rb:224:1:224:3 | call to bar | bar | +| calls.rb:224:11:224:13 | call to foo | foo | +| calls.rb:225:1:225:6 | call to bar | bar | +| calls.rb:225:14:225:19 | call to foo | foo | +| calls.rb:228:10:228:12 | call to bar | bar | +| calls.rb:229:3:229:5 | call to baz | baz | +| calls.rb:231:10:231:15 | call to bar | bar | +| calls.rb:232:3:232:8 | call to baz | baz | +| calls.rb:236:1:236:3 | call to foo | foo | +| calls.rb:236:5:236:7 | call to bar | bar | +| calls.rb:237:1:237:6 | call to foo | foo | +| calls.rb:237:8:237:13 | call to bar | bar | +| calls.rb:240:8:240:10 | call to bar | bar | +| calls.rb:240:15:240:20 | call to baz | baz | +| calls.rb:243:1:243:3 | call to foo | foo | +| calls.rb:244:1:244:6 | call to foo | foo | +| calls.rb:247:1:247:3 | call to foo | foo | +| calls.rb:247:6:247:8 | call to bar | bar | +| calls.rb:248:1:248:6 | call to foo | foo | +| calls.rb:248:9:248:14 | call to bar | bar | +| calls.rb:251:3:251:5 | call to foo | foo | +| calls.rb:251:10:251:12 | call to bar | bar | +| calls.rb:251:15:251:20 | call to foo | foo | +| calls.rb:251:25:251:30 | call to bar | bar | +| calls.rb:255:8:255:10 | call to foo | foo | +| calls.rb:256:8:256:10 | call to bar | bar | +| calls.rb:259:8:259:13 | call to foo | foo | +| calls.rb:260:8:260:13 | call to bar | bar | +| calls.rb:264:1:264:3 | call to foo | foo | +| calls.rb:264:12:264:14 | call to bar | bar | +| calls.rb:265:1:265:6 | call to foo | foo | +| calls.rb:265:15:265:20 | call to bar | bar | +| calls.rb:268:6:268:8 | call to bar | bar | +| calls.rb:269:6:269:11 | call to bar | bar | +| calls.rb:272:6:272:8 | call to bar | bar | +| calls.rb:273:6:273:11 | call to bar | bar | +| calls.rb:276:7:276:9 | call to bar | bar | +| calls.rb:277:7:277:12 | call to bar | bar | +| calls.rb:280:11:280:13 | call to bar | bar | +| calls.rb:281:11:281:16 | call to bar | bar | +| calls.rb:288:5:288:9 | call to super | super | +| calls.rb:289:5:289:11 | call to super | super | +| calls.rb:305:5:305:7 | call to foo | foo | +| calls.rb:306:5:306:14 | call to super | super | +| calls.rb:307:5:307:9 | call to super | super | +callsWithNameScopeExpr +callsWithGlobalNameScopeExpr +| calls.rb:8:1:8:7 | call to bar | callsWithArguments -| calls.rb:11:1:11:11 | call to foo | foo | 0 | calls.rb:11:5:11:5 | 0 | -| calls.rb:11:1:11:11 | call to foo | foo | 1 | calls.rb:11:8:11:8 | 1 | -| calls.rb:11:1:11:11 | call to foo | foo | 2 | calls.rb:11:11:11:11 | 2 | -| calls.rb:22:1:24:3 | call to bar | bar | 0 | calls.rb:22:9:22:13 | foo | -| calls.rb:33:3:33:16 | call to yield | yield | 0 | calls.rb:33:9:33:11 | 100 | -| calls.rb:33:3:33:16 | call to yield | yield | 1 | calls.rb:33:14:33:16 | 200 | -| calls.rb:48:1:48:14 | call to some_func | some_func | 0 | calls.rb:48:11:48:13 | call to foo | -| calls.rb:201:1:201:9 | call to foo | foo | 0 | calls.rb:201:5:201:8 | &... | -| calls.rb:204:1:204:9 | call to foo | foo | 0 | calls.rb:204:5:204:8 | *... | -| calls.rb:207:1:207:10 | call to foo | foo | 0 | calls.rb:207:5:207:9 | **... | -| calls.rb:210:1:210:14 | call to foo | foo | 0 | calls.rb:210:5:210:13 | Pair | -| calls.rb:219:5:219:16 | call to super | super | 0 | calls.rb:219:11:219:16 | blah | -| calls.rb:220:5:220:17 | call to super | super | 0 | calls.rb:220:11:220:11 | 1 | -| calls.rb:220:5:220:17 | call to super | super | 1 | calls.rb:220:14:220:14 | 2 | -| calls.rb:220:5:220:17 | call to super | super | 2 | calls.rb:220:17:220:17 | 3 | -| calls.rb:223:5:223:30 | call to super | super | 0 | calls.rb:223:11:223:11 | 4 | -| calls.rb:223:5:223:30 | call to super | super | 1 | calls.rb:223:14:223:14 | 5 | -| calls.rb:224:5:224:33 | call to super | super | 0 | calls.rb:224:11:224:11 | 6 | -| calls.rb:224:5:224:33 | call to super | super | 1 | calls.rb:224:14:224:14 | 7 | +| calls.rb:14:1:14:11 | call to foo | foo | 0 | calls.rb:14:5:14:5 | 0 | +| calls.rb:14:1:14:11 | call to foo | foo | 1 | calls.rb:14:8:14:8 | 1 | +| calls.rb:14:1:14:11 | call to foo | foo | 2 | calls.rb:14:11:14:11 | 2 | +| calls.rb:25:1:27:3 | call to bar | bar | 0 | calls.rb:25:9:25:13 | foo | +| calls.rb:36:3:36:16 | call to yield | yield | 0 | calls.rb:36:9:36:11 | 100 | +| calls.rb:36:3:36:16 | call to yield | yield | 1 | calls.rb:36:14:36:16 | 200 | +| calls.rb:54:1:54:14 | call to some_func | some_func | 0 | calls.rb:54:11:54:13 | call to foo | +| calls.rb:55:1:55:17 | call to some_func | some_func | 0 | calls.rb:55:11:55:16 | call to foo | +| calls.rb:268:1:268:9 | call to foo | foo | 0 | calls.rb:268:5:268:8 | &... | +| calls.rb:269:1:269:12 | call to foo | foo | 0 | calls.rb:269:5:269:11 | &... | +| calls.rb:272:1:272:9 | call to foo | foo | 0 | calls.rb:272:5:272:8 | *... | +| calls.rb:273:1:273:12 | call to foo | foo | 0 | calls.rb:273:5:273:11 | *... | +| calls.rb:276:1:276:10 | call to foo | foo | 0 | calls.rb:276:5:276:9 | **... | +| calls.rb:277:1:277:13 | call to foo | foo | 0 | calls.rb:277:5:277:12 | **... | +| calls.rb:280:1:280:14 | call to foo | foo | 0 | calls.rb:280:5:280:13 | Pair | +| calls.rb:281:1:281:17 | call to foo | foo | 0 | calls.rb:281:5:281:16 | Pair | +| calls.rb:290:5:290:16 | call to super | super | 0 | calls.rb:290:11:290:16 | blah | +| calls.rb:291:5:291:17 | call to super | super | 0 | calls.rb:291:11:291:11 | 1 | +| calls.rb:291:5:291:17 | call to super | super | 1 | calls.rb:291:14:291:14 | 2 | +| calls.rb:291:5:291:17 | call to super | super | 2 | calls.rb:291:17:291:17 | 3 | +| calls.rb:294:5:294:30 | call to super | super | 0 | calls.rb:294:11:294:11 | 4 | +| calls.rb:294:5:294:30 | call to super | super | 1 | calls.rb:294:14:294:14 | 5 | +| calls.rb:295:5:295:33 | call to super | super | 0 | calls.rb:295:11:295:11 | 6 | +| calls.rb:295:5:295:33 | call to super | super | 1 | calls.rb:295:14:295:14 | 7 | callsWithReceiver -| calls.rb:8:1:8:7 | call to bar | calls.rb:8:1:8:3 | 123 | -| calls.rb:22:1:24:3 | call to bar | calls.rb:22:1:22:3 | 123 | -| calls.rb:86:1:86:9 | call to bar | calls.rb:86:1:86:3 | call to foo | -| calls.rb:234:5:234:13 | call to super | calls.rb:234:5:234:7 | call to foo | -| calls.rb:236:5:236:15 | call to super | calls.rb:236:5:236:9 | call to super | +| calls.rb:11:1:11:7 | call to bar | calls.rb:11:1:11:3 | 123 | +| calls.rb:25:1:27:3 | call to bar | calls.rb:25:1:25:3 | 123 | +| calls.rb:101:1:101:9 | call to bar | calls.rb:101:1:101:3 | call to foo | +| calls.rb:102:1:102:9 | call to baz | calls.rb:102:1:102:3 | call to bar | +| calls.rb:305:5:305:13 | call to super | calls.rb:305:5:305:7 | call to foo | +| calls.rb:307:5:307:15 | call to super | calls.rb:307:5:307:9 | call to super | callsWithBlock -| calls.rb:14:1:14:17 | call to foo | calls.rb:14:5:14:17 | { ... } | -| calls.rb:17:1:19:3 | call to foo | calls.rb:17:5:19:3 | do ... end | -| calls.rb:22:1:24:3 | call to bar | calls.rb:22:16:24:3 | do ... end | -| calls.rb:80:1:80:13 | call to foo | calls.rb:80:7:80:13 | { ... } | -| calls.rb:83:1:83:16 | call to foo | calls.rb:83:7:83:16 | do ... end | -| calls.rb:221:5:221:23 | call to super | calls.rb:221:11:221:23 | { ... } | -| calls.rb:222:5:222:26 | call to super | calls.rb:222:11:222:26 | do ... end | -| calls.rb:223:5:223:30 | call to super | calls.rb:223:16:223:30 | { ... } | -| calls.rb:224:5:224:33 | call to super | calls.rb:224:16:224:33 | do ... end | +| calls.rb:17:1:17:17 | call to foo | calls.rb:17:5:17:17 | { ... } | +| calls.rb:20:1:22:3 | call to foo | calls.rb:20:5:22:3 | do ... end | +| calls.rb:25:1:27:3 | call to bar | calls.rb:25:16:27:3 | do ... end | +| calls.rb:92:1:92:21 | call to foo | calls.rb:92:7:92:21 | { ... } | +| calls.rb:95:1:98:3 | call to foo | calls.rb:95:7:98:3 | do ... end | +| calls.rb:292:5:292:23 | call to super | calls.rb:292:11:292:23 | { ... } | +| calls.rb:293:5:293:26 | call to super | calls.rb:293:11:293:26 | do ... end | +| calls.rb:294:5:294:30 | call to super | calls.rb:294:16:294:30 | { ... } | +| calls.rb:295:5:295:33 | call to super | calls.rb:295:16:295:33 | do ... end | yieldCalls -| calls.rb:28:3:28:7 | call to yield | -| calls.rb:33:3:33:16 | call to yield | +| calls.rb:31:3:31:7 | call to yield | +| calls.rb:36:3:36:16 | call to yield | superCalls -| calls.rb:217:5:217:9 | call to super | -| calls.rb:218:5:218:11 | call to super | -| calls.rb:219:5:219:16 | call to super | -| calls.rb:220:5:220:17 | call to super | -| calls.rb:221:5:221:23 | call to super | -| calls.rb:222:5:222:26 | call to super | -| calls.rb:223:5:223:30 | call to super | -| calls.rb:224:5:224:33 | call to super | -| calls.rb:236:5:236:9 | call to super | +| calls.rb:288:5:288:9 | call to super | +| calls.rb:289:5:289:11 | call to super | +| calls.rb:290:5:290:16 | call to super | +| calls.rb:291:5:291:17 | call to super | +| calls.rb:292:5:292:23 | call to super | +| calls.rb:293:5:293:26 | call to super | +| calls.rb:294:5:294:30 | call to super | +| calls.rb:295:5:295:33 | call to super | +| calls.rb:307:5:307:9 | call to super | superCallsWithArguments -| calls.rb:219:5:219:16 | call to super | 0 | calls.rb:219:11:219:16 | blah | -| calls.rb:220:5:220:17 | call to super | 0 | calls.rb:220:11:220:11 | 1 | -| calls.rb:220:5:220:17 | call to super | 1 | calls.rb:220:14:220:14 | 2 | -| calls.rb:220:5:220:17 | call to super | 2 | calls.rb:220:17:220:17 | 3 | -| calls.rb:223:5:223:30 | call to super | 0 | calls.rb:223:11:223:11 | 4 | -| calls.rb:223:5:223:30 | call to super | 1 | calls.rb:223:14:223:14 | 5 | -| calls.rb:224:5:224:33 | call to super | 0 | calls.rb:224:11:224:11 | 6 | -| calls.rb:224:5:224:33 | call to super | 1 | calls.rb:224:14:224:14 | 7 | +| calls.rb:290:5:290:16 | call to super | 0 | calls.rb:290:11:290:16 | blah | +| calls.rb:291:5:291:17 | call to super | 0 | calls.rb:291:11:291:11 | 1 | +| calls.rb:291:5:291:17 | call to super | 1 | calls.rb:291:14:291:14 | 2 | +| calls.rb:291:5:291:17 | call to super | 2 | calls.rb:291:17:291:17 | 3 | +| calls.rb:294:5:294:30 | call to super | 0 | calls.rb:294:11:294:11 | 4 | +| calls.rb:294:5:294:30 | call to super | 1 | calls.rb:294:14:294:14 | 5 | +| calls.rb:295:5:295:33 | call to super | 0 | calls.rb:295:11:295:11 | 6 | +| calls.rb:295:5:295:33 | call to super | 1 | calls.rb:295:14:295:14 | 7 | superCallsWithBlock -| calls.rb:221:5:221:23 | call to super | calls.rb:221:11:221:23 | { ... } | -| calls.rb:222:5:222:26 | call to super | calls.rb:222:11:222:26 | do ... end | -| calls.rb:223:5:223:30 | call to super | calls.rb:223:16:223:30 | { ... } | -| calls.rb:224:5:224:33 | call to super | calls.rb:224:16:224:33 | do ... end | +| calls.rb:292:5:292:23 | call to super | calls.rb:292:11:292:23 | { ... } | +| calls.rb:293:5:293:26 | call to super | calls.rb:293:11:293:26 | do ... end | +| calls.rb:294:5:294:30 | call to super | calls.rb:294:16:294:30 | { ... } | +| calls.rb:295:5:295:33 | call to super | calls.rb:295:16:295:33 | do ... end | diff --git a/ql/test/library-tests/ast/calls/calls.ql b/ql/test/library-tests/ast/calls/calls.ql index bc6c244356e..fb88970d3eb 100644 --- a/ql/test/library-tests/ast/calls/calls.ql +++ b/ql/test/library-tests/ast/calls/calls.ql @@ -8,9 +8,9 @@ query predicate callsWithNoReceiverArgumentsOrBlock(Call c, string name) { not exists(c.getBlock()) } -query predicate callsWithScopeResolutionName(Call c, ScopeResolution sr) { - sr = c.getMethodScopeResolution() -} +query predicate callsWithNameScopeExpr(Call c, Expr se) { se = c.getMethodNameScopeExpr() } + +query predicate callsWithGlobalNameScopeExpr(Call c) { c.methodNameHasGlobalScope() } query predicate callsWithArguments(Call c, string name, int n, Expr argN) { name = c.getMethodName() and diff --git a/ql/test/library-tests/ast/calls/calls.rb b/ql/test/library-tests/ast/calls/calls.rb index c60cf682001..47821c6a932 100644 --- a/ql/test/library-tests/ast/calls/calls.rb +++ b/ql/test/library-tests/ast/calls/calls.rb @@ -4,6 +4,9 @@ foo() # call whose name is a scope resolution Foo::bar() +# call whose name is a global scope resolution +::bar() + # call with a receiver, no arguments or block 123.bar @@ -35,55 +38,68 @@ end # ------------------------------------------------------------------------------ # Calls without parentheses or arguments are parsed by tree-sitter simply as -# `identifier` nodes, so here we test that our AST library correctly represents -# them as calls in all the following contexts. +# `identifier` nodes (or `scope_resolution` nodes whose `name` field is an +# `identifier), so here we test that our AST library correctly represents them +# as calls in all the following contexts. # root level (child of program) foo +X::foo # in a parenthesized statement (foo) +(X::foo) # in an argument list some_func(foo) +some_func(X::foo) # in an array [foo] +[X::foo] # RHS of an assignment var1 = foo +var1 = X::foo # RHS an operator assignment var1 += bar +var1 += X::bar # RHS assignment list -var1 = foo, bar +var1 = foo, X::bar # in a begin-end block begin foo + X::foo end # in a BEGIN block -BEGIN { foo } +BEGIN { foo; X::bar } # in an END block -END { foo } +END { foo; X::bar } # both operands of a binary operation -foo + bar +foo + X::bar # unary operand !foo +~X::bar # in a curly brace block -foo() { bar } +foo() { bar; X::baz } # in a do-end block -foo() do bar end +foo() do + bar + X::baz +end # the receiver in a call can itself be a call foo.bar() +bar.baz() # the value for a case expr # and the when pattern and body @@ -91,46 +107,66 @@ case foo when bar baz end +case X::foo +when X::bar + X::baz +end # in a class definition class MyClass foo + X::bar end # in a superclass class MyClass < foo end +class MyClass2 < X::foo +end # in a singleton class value or body class << foo bar end +class << X::foo + X::bar +end # in a method body def some_method foo + X::bar end # in a singleton method object or body def foo.some_method bar end +def X::foo.some_method + X::bar +end # in the default value for a keyword parameter def method_with_keyword_param(keyword: foo) end +def method_with_keyword_param2(keyword: X::foo) +end # in the default value for an optional parameter def method_with_optional_param(param = foo) end +def method_with_optional_param2(param = X::foo) +end # in a module module SomeModule foo + X::bar end # ternary if: condition, consequence, and alternative can all be calls foo ? bar : baz +X::foo ? X::bar : X::baz # if/elsif/else conditions and bodies if foo @@ -140,74 +176,109 @@ elsif bar else wabble end +if X::foo + X::wibble +elsif X::bar + X::wobble +else + X::wabble +end # if-modifier condition/body bar if foo +X::bar if X::foo # unless condition/body unless foo bar end +unless X::foo + X::bar +end # unless-modifier condition/body bar unless foo +X::bar unless X::foo # while loop condition/body while foo do bar end +while X::foo do + X::bar +end # while-modifier loop condition/body bar while foo +X::bar while X::foo # until loop condition/body until foo do bar end +until X::foo do + X::bar +end # until-modifier loop condition/body bar until foo +X::bar until X::foo # the collection being iterated over in a for loop, and the body for x in bar baz end +for x in X::bar + X::baz +end # in an array indexing operation, both the object and the index can be calls foo[bar] +X::foo[X::bar] # interpolation -"foo-#{bar}" +"foo-#{bar}-#{X::baz}" # the scope in a scope resolution foo::Bar +X::foo::Bar # in a range foo..bar +X::foo..X::bar # the key/value in a hash pair -{ foo => bar } +{ foo => bar, X::foo => X::bar } # rescue exceptions and ensure begin rescue foo ensure bar end +begin +rescue X::foo +ensure X::bar +end # rescue-modifier body and handler foo rescue bar +X::foo rescue X::bar # block argument foo(&bar) +foo(&X::bar) # splat argument foo(*bar) +foo(*X::bar) # hash-splat argument foo(**bar) +foo(**X::bar) # the value in a keyword argument foo(blah: bar) +foo(blah: X::bar) # ------------------------------------------------------------------------------ # calls to `super` diff --git a/ql/test/library-tests/ast/modules/classes.expected b/ql/test/library-tests/ast/modules/classes.expected index 11091f6135e..e8d1434979e 100644 --- a/ql/test/library-tests/ast/modules/classes.expected +++ b/ql/test/library-tests/ast/modules/classes.expected @@ -5,12 +5,14 @@ classes | 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 | -classesWithScopeResolutionNames -| classes.rb:16:1:17:3 | MyClass | classes.rb:16:7:16:23 | ...::MyClass | +classesWithNameScopeExprs +classesWithGlobalNameScopeExprs +| classes.rb:55:1:56:3 | MyClassInGlobalScope | exprsInClasses | classes.rb:20:1:37:3 | Wibble | 0 | classes.rb:21:3:23:5 | method_a | Method | | classes.rb:20:1:37:3 | Wibble | 1 | classes.rb:25:3:27:5 | method_b | Method | diff --git a/ql/test/library-tests/ast/modules/classes.ql b/ql/test/library-tests/ast/modules/classes.ql index f88d785581d..95876070c77 100644 --- a/ql/test/library-tests/ast/modules/classes.ql +++ b/ql/test/library-tests/ast/modules/classes.ql @@ -4,9 +4,9 @@ query predicate classes(Class c, string pClass, string name) { pClass = c.getAPrimaryQlClass() and name = c.getName() } -query predicate classesWithScopeResolutionNames(Class c, ScopeResolution name) { - name = c.getNameScopeResolution() -} +query predicate classesWithNameScopeExprs(Class c, Expr se) { se = c.getNameScopeExpr() } + +query predicate classesWithGlobalNameScopeExprs(Class c) { c.nameHasGlobalScope() } query predicate exprsInClasses(Class c, int i, Expr e, string eClass) { e = c.getExpr(i) and eClass = e.getAPrimaryQlClass() diff --git a/ql/test/library-tests/ast/modules/classes.rb b/ql/test/library-tests/ast/modules/classes.rb index a6bc21f799c..ce05212ada1 100644 --- a/ql/test/library-tests/ast/modules/classes.rb +++ b/ql/test/library-tests/ast/modules/classes.rb @@ -49,4 +49,8 @@ class << x another_method_call $global_var2 = 456 +end + +# a class where the name is a scope resolution using the global scope +class ::MyClassInGlobalScope end \ No newline at end of file diff --git a/ql/test/library-tests/ast/modules/module_base.expected b/ql/test/library-tests/ast/modules/module_base.expected index 1755384327e..11a2769c39c 100644 --- a/ql/test/library-tests/ast/modules/module_base.expected +++ b/ql/test/library-tests/ast/modules/module_base.expected @@ -8,6 +8,7 @@ moduleBases | 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:4:1:24:3 | Foo | Module | | modules.rb:5:3:14:5 | Bar | Module | @@ -18,6 +19,7 @@ moduleBases | 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 | moduleBaseClasses | classes.rb:20:1:37:3 | Wibble | classes.rb:32:3:33:5 | ClassInWibble | | modules.rb:4:1:24:3 | Foo | modules.rb:19:3:20:5 | ClassInFoo | diff --git a/ql/test/library-tests/ast/modules/modules.expected b/ql/test/library-tests/ast/modules/modules.expected index 9d650a05cbb..36f95f4c2a2 100644 --- a/ql/test/library-tests/ast/modules/modules.expected +++ b/ql/test/library-tests/ast/modules/modules.expected @@ -7,8 +7,10 @@ modules | 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 | -modulesWithScopeResolutionNames -| modules.rb:48:1:57:3 | Bar | modules.rb:48:8:48:15 | ...::Bar | +| modules.rb:60:1:61:3 | MyModuleInGlobalScope | Module | MyModuleInGlobalScope | +modulesWithScopeExprs +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 | 1 | modules.rb:16:3:17:5 | method_in_foo | Method | diff --git a/ql/test/library-tests/ast/modules/modules.ql b/ql/test/library-tests/ast/modules/modules.ql index 5fb00a77868..e33fa3095e2 100644 --- a/ql/test/library-tests/ast/modules/modules.ql +++ b/ql/test/library-tests/ast/modules/modules.ql @@ -4,9 +4,9 @@ query predicate modules(Module m, string pClass, string name) { pClass = m.getAPrimaryQlClass() and name = m.getName() } -query predicate modulesWithScopeResolutionNames(Module m, ScopeResolution name) { - name = m.getNameScopeResolution() -} +query predicate modulesWithScopeExprs(Module m, Expr se) { se = m.getNameScopeExpr() } + +query predicate modulesWithGlobalNameScopeExprs(Module m) { m.nameHasGlobalScope() } query predicate exprsInModules(Module m, int i, Expr e, string eClass) { e = m.getExpr(i) and eClass = e.getAPrimaryQlClass() diff --git a/ql/test/library-tests/ast/modules/modules.rb b/ql/test/library-tests/ast/modules/modules.rb index f34ddcec27a..dfba11f8d6e 100644 --- a/ql/test/library-tests/ast/modules/modules.rb +++ b/ql/test/library-tests/ast/modules/modules.rb @@ -54,4 +54,8 @@ module Foo::Bar puts 'module Foo::Bar again' $global_var = 4 +end + +# a module where the name is a scope resolution using the global scope +module ::MyModuleInGlobalScope end \ No newline at end of file