mirror of
https://github.com/github/codeql.git
synced 2026-02-20 08:53:49 +01:00
Remove ScopeResolution from AST
Now we handle it specially in calls and class/module names, so they have predicate to get the scope expr.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user