mirror of
https://github.com/github/codeql.git
synced 2026-02-19 16:33:40 +01:00
Merge pull request #156 from github/hvitved/ipa-ast
Make external `AstNode` an IPA type
This commit is contained in:
@@ -18,11 +18,7 @@ private import ast.internal.AST
|
||||
* A node in the abstract syntax tree. This class is the base class for all Ruby
|
||||
* program elements.
|
||||
*/
|
||||
class AstNode extends @ast_node {
|
||||
AstNode::Range range;
|
||||
|
||||
AstNode() { range = this }
|
||||
|
||||
class AstNode extends TAstNode {
|
||||
/**
|
||||
* Gets the name of a primary CodeQL class to which this node belongs.
|
||||
*
|
||||
@@ -33,14 +29,22 @@ class AstNode extends @ast_node {
|
||||
string getAPrimaryQlClass() { result = "???" }
|
||||
|
||||
/** Gets a textual representation of this node. */
|
||||
final string toString() { result = range.toString() }
|
||||
cached
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the location of this node. */
|
||||
final Location getLocation() { result = range.getLocation() }
|
||||
Location getLocation() { result = toGenerated(this).getLocation() }
|
||||
|
||||
/** Gets a child node of this `AstNode`. */
|
||||
final AstNode getAChild() { range.child(_, result) }
|
||||
final AstNode getAChild() { result = this.getAChild(_) }
|
||||
|
||||
/** Gets the parent of this `AstNode`, if this node is not a root node. */
|
||||
final AstNode getParent() { result.getAChild() = this }
|
||||
|
||||
/**
|
||||
* Gets a child of this node, which can also be retrieved using a predicate
|
||||
* named `pred`.
|
||||
*/
|
||||
cached
|
||||
AstNode getAChild(string pred) { none() }
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Call
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/**
|
||||
* A call.
|
||||
*/
|
||||
class Call extends Expr {
|
||||
override Call::Range range;
|
||||
|
||||
class Call extends Expr, TCall {
|
||||
override string getAPrimaryQlClass() { result = "Call" }
|
||||
|
||||
/**
|
||||
@@ -21,7 +20,7 @@ class Call extends Expr {
|
||||
* yield 0, bar: 1
|
||||
* ```
|
||||
*/
|
||||
final Expr getArgument(int n) { result = range.getArgument(n) }
|
||||
Expr getArgument(int n) { none() }
|
||||
|
||||
/**
|
||||
* Gets an argument of this method call.
|
||||
@@ -48,14 +47,27 @@ class Call extends Expr {
|
||||
* Gets the number of arguments of this method call.
|
||||
*/
|
||||
final int getNumberOfArguments() { result = count(this.getAnArgument()) }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getArgument" and result = this.getArgument(_) }
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
private string getMethodName(MethodCall mc, string s) {
|
||||
(
|
||||
not mc instanceof LhsExpr
|
||||
or
|
||||
mc.getParent() instanceof AssignOperation
|
||||
) and
|
||||
result = s
|
||||
or
|
||||
mc instanceof LhsExpr and
|
||||
result = s + "="
|
||||
}
|
||||
|
||||
/**
|
||||
* A method call.
|
||||
*/
|
||||
class MethodCall extends Call {
|
||||
override MethodCall::Range range;
|
||||
|
||||
class MethodCall extends Call, TMethodCall {
|
||||
override string getAPrimaryQlClass() { result = "MethodCall" }
|
||||
|
||||
/**
|
||||
@@ -71,7 +83,7 @@ class MethodCall extends Call {
|
||||
* the call to `qux` is the `Expr` for `Baz`; for the call to `corge` there
|
||||
* is no result.
|
||||
*/
|
||||
final Expr getReceiver() { result = range.getReceiver() }
|
||||
Expr getReceiver() { none() }
|
||||
|
||||
/**
|
||||
* Gets the name of the method being called. For example, in:
|
||||
@@ -82,7 +94,7 @@ class MethodCall extends Call {
|
||||
*
|
||||
* the result is `"bar"`.
|
||||
*/
|
||||
final string getMethodName() { result = range.getMethodName() }
|
||||
string getMethodName() { none() }
|
||||
|
||||
/**
|
||||
* Gets the block of this method call, if any.
|
||||
@@ -90,7 +102,67 @@ class MethodCall extends Call {
|
||||
* foo.each { |x| puts x }
|
||||
* ```
|
||||
*/
|
||||
final Block getBlock() { result = range.getBlock() }
|
||||
Block getBlock() { none() }
|
||||
|
||||
override string toString() { result = "call to " + concat(this.getMethodName(), "/") }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = Call.super.getAChild(pred)
|
||||
or
|
||||
pred = "getReceiver" and result = this.getReceiver()
|
||||
or
|
||||
pred = "getBlock" and result = this.getBlock()
|
||||
}
|
||||
}
|
||||
|
||||
private class IdentifierMethodCall extends MethodCall, TIdentifierMethodCall {
|
||||
private Generated::Identifier g;
|
||||
|
||||
IdentifierMethodCall() { this = TIdentifierMethodCall(g) }
|
||||
|
||||
final override string getMethodName() { result = getMethodName(this, g.getValue()) }
|
||||
}
|
||||
|
||||
private class ScopeResolutionMethodCall extends MethodCall, TScopeResolutionMethodCall {
|
||||
private Generated::ScopeResolution g;
|
||||
private Generated::Identifier i;
|
||||
|
||||
ScopeResolutionMethodCall() { this = TScopeResolutionMethodCall(g, i) }
|
||||
|
||||
final override Expr getReceiver() { toGenerated(result) = g.getScope() }
|
||||
|
||||
final override string getMethodName() { result = getMethodName(this, i.getValue()) }
|
||||
}
|
||||
|
||||
private class RegularMethodCall extends MethodCall, TRegularMethodCall {
|
||||
private Generated::Call g;
|
||||
|
||||
RegularMethodCall() { this = TRegularMethodCall(g) }
|
||||
|
||||
final override Expr getReceiver() {
|
||||
toGenerated(result) = g.getReceiver()
|
||||
or
|
||||
not exists(g.getReceiver()) and
|
||||
toGenerated(result) = g.getMethod().(Generated::ScopeResolution).getScope()
|
||||
}
|
||||
|
||||
final override string getMethodName() {
|
||||
exists(string res | result = getMethodName(this, res) |
|
||||
res = "call" and g.getMethod() instanceof Generated::ArgumentList
|
||||
or
|
||||
res = g.getMethod().(Generated::Token).getValue()
|
||||
or
|
||||
res = g.getMethod().(Generated::ScopeResolution).getName().(Generated::Token).getValue()
|
||||
)
|
||||
}
|
||||
|
||||
final override Expr getArgument(int n) {
|
||||
toGenerated(result) = g.getArguments().getChild(n)
|
||||
or
|
||||
toGenerated(result) = g.getMethod().(Generated::ArgumentList).getChild(n)
|
||||
}
|
||||
|
||||
final override Block getBlock() { toGenerated(result) = g.getBlock() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,8 +173,6 @@ class MethodCall extends Call {
|
||||
* ```
|
||||
*/
|
||||
class SetterMethodCall extends MethodCall, LhsExpr {
|
||||
final override SetterMethodCall::Range range;
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SetterMethodCall" }
|
||||
}
|
||||
|
||||
@@ -112,10 +182,20 @@ class SetterMethodCall extends MethodCall, LhsExpr {
|
||||
* a[0]
|
||||
* ```
|
||||
*/
|
||||
class ElementReference extends MethodCall, @element_reference {
|
||||
final override ElementReference::Range range;
|
||||
class ElementReference extends MethodCall, TElementReference {
|
||||
private Generated::ElementReference g;
|
||||
|
||||
ElementReference() { this = TElementReference(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ElementReference" }
|
||||
|
||||
final override Expr getReceiver() { toGenerated(result) = g.getObject() }
|
||||
|
||||
final override string getMethodName() { result = getMethodName(this, "[]") }
|
||||
|
||||
final override Expr getArgument(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
final override string toString() { result = "...[...]" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,10 +204,16 @@ class ElementReference extends MethodCall, @element_reference {
|
||||
* yield x, y
|
||||
* ```
|
||||
*/
|
||||
class YieldCall extends Call, @yield {
|
||||
final override YieldCall::Range range;
|
||||
class YieldCall extends Call, TYieldCall {
|
||||
private Generated::Yield g;
|
||||
|
||||
YieldCall() { this = TYieldCall(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "YieldCall" }
|
||||
|
||||
final override Expr getArgument(int n) { toGenerated(result) = g.getChild().getChild(n) }
|
||||
|
||||
final override string toString() { result = "yield ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,20 +226,42 @@ class YieldCall extends Call, @yield {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class SuperCall extends MethodCall {
|
||||
final override SuperCall::Range range;
|
||||
|
||||
class SuperCall extends MethodCall, TSuperCall {
|
||||
final override string getAPrimaryQlClass() { result = "SuperCall" }
|
||||
}
|
||||
|
||||
private class TokenSuperCall extends SuperCall, TTokenSuperCall {
|
||||
private Generated::Super g;
|
||||
|
||||
TokenSuperCall() { this = TTokenSuperCall(g) }
|
||||
|
||||
final override string getMethodName() { result = getMethodName(this, g.getValue()) }
|
||||
}
|
||||
|
||||
private class RegularSuperCall extends SuperCall, TRegularSuperCall {
|
||||
private Generated::Call g;
|
||||
|
||||
RegularSuperCall() { this = TRegularSuperCall(g) }
|
||||
|
||||
final override string getMethodName() {
|
||||
result = getMethodName(this, g.getMethod().(Generated::Super).getValue())
|
||||
}
|
||||
|
||||
final override Expr getArgument(int n) { toGenerated(result) = g.getArguments().getChild(n) }
|
||||
|
||||
final override Block getBlock() { toGenerated(result) = g.getBlock() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A block argument in a method call.
|
||||
* ```rb
|
||||
* foo(&block)
|
||||
* ```
|
||||
*/
|
||||
class BlockArgument extends Expr, @block_argument {
|
||||
final override BlockArgument::Range range;
|
||||
class BlockArgument extends Expr, TBlockArgument {
|
||||
private Generated::BlockArgument g;
|
||||
|
||||
BlockArgument() { this = TBlockArgument(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "BlockArgument" }
|
||||
|
||||
@@ -164,7 +272,11 @@ class BlockArgument extends Expr, @block_argument {
|
||||
* foo(&bar)
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getChild() }
|
||||
|
||||
final override string toString() { result = "&..." }
|
||||
|
||||
final override AstNode getAChild(string pred) { pred = "getValue" and result = this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,8 +285,10 @@ class BlockArgument extends Expr, @block_argument {
|
||||
* foo(*args)
|
||||
* ```
|
||||
*/
|
||||
class SplatArgument extends Expr, @splat_argument {
|
||||
final override SplatArgument::Range range;
|
||||
class SplatArgument extends Expr, TSplatArgument {
|
||||
private Generated::SplatArgument g;
|
||||
|
||||
SplatArgument() { this = TSplatArgument(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SplatArgument" }
|
||||
|
||||
@@ -185,7 +299,11 @@ class SplatArgument extends Expr, @splat_argument {
|
||||
* foo(*bar)
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getChild() }
|
||||
|
||||
final override string toString() { result = "*..." }
|
||||
|
||||
final override AstNode getAChild(string pred) { pred = "getValue" and result = this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -194,8 +312,10 @@ class SplatArgument extends Expr, @splat_argument {
|
||||
* foo(**options)
|
||||
* ```
|
||||
*/
|
||||
class HashSplatArgument extends Expr, @hash_splat_argument {
|
||||
final override HashSplatArgument::Range range;
|
||||
class HashSplatArgument extends Expr, THashSplatArgument {
|
||||
private Generated::HashSplatArgument g;
|
||||
|
||||
HashSplatArgument() { this = THashSplatArgument(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "HashSplatArgument" }
|
||||
|
||||
@@ -206,5 +326,9 @@ class HashSplatArgument extends Expr, @hash_splat_argument {
|
||||
* foo(**bar)
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getChild() }
|
||||
|
||||
final override string toString() { result = "**..." }
|
||||
|
||||
final override AstNode getAChild(string pred) { pred = "getValue" and result = this.getValue() }
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Constant
|
||||
private import internal.AST
|
||||
private import internal.Variable
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** An access to a constant. */
|
||||
class ConstantAccess extends Expr {
|
||||
override ConstantAccess::Range range;
|
||||
|
||||
class ConstantAccess extends Expr, TConstantAccess {
|
||||
/** Gets the name of the constant being accessed. */
|
||||
string getName() { result = range.getName() }
|
||||
string getName() { none() }
|
||||
|
||||
/**
|
||||
* Gets the expression used in the access's scope resolution operation, if
|
||||
@@ -24,7 +24,7 @@ class ConstantAccess extends Expr {
|
||||
* MESSAGE
|
||||
* ```
|
||||
*/
|
||||
Expr getScopeExpr() { result = range.getScopeExpr() }
|
||||
Expr getScopeExpr() { none() }
|
||||
|
||||
/**
|
||||
* Holds if the access uses the scope resolution operator to refer to the
|
||||
@@ -34,7 +34,32 @@ class ConstantAccess extends Expr {
|
||||
* ::MESSAGE
|
||||
* ```
|
||||
*/
|
||||
predicate hasGlobalScope() { range.hasGlobalScope() }
|
||||
predicate hasGlobalScope() { none() }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getScopeExpr" and result = this.getScopeExpr() }
|
||||
}
|
||||
|
||||
private class TokenConstantAccess extends ConstantAccess, TTokenConstantAccess {
|
||||
private Generated::Constant g;
|
||||
|
||||
TokenConstantAccess() { this = TTokenConstantAccess(g) }
|
||||
|
||||
final override string getName() { result = g.getValue() }
|
||||
}
|
||||
|
||||
private class ScopeResolutionConstantAccess extends ConstantAccess, TScopeResolutionConstantAccess {
|
||||
private Generated::ScopeResolution g;
|
||||
private Generated::Constant constant;
|
||||
|
||||
ScopeResolutionConstantAccess() { this = TScopeResolutionConstantAccess(g, constant) }
|
||||
|
||||
final override string getName() { result = constant.getValue() }
|
||||
|
||||
final override Expr getScopeExpr() { toGenerated(result) = g.getScope() }
|
||||
|
||||
final override predicate hasGlobalScope() { not exists(g.getScope()) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +79,12 @@ class ConstantAccess extends Expr {
|
||||
* ```
|
||||
*/
|
||||
class ConstantReadAccess extends ConstantAccess {
|
||||
final override ConstantReadAccess::Range range;
|
||||
ConstantReadAccess() {
|
||||
not this instanceof ConstantWriteAccess
|
||||
or
|
||||
// `X` in `X ||= 10` is considered both a read and a write
|
||||
this = any(AssignOperation a).getLeftOperand()
|
||||
}
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ConstantReadAccess" }
|
||||
}
|
||||
@@ -76,7 +106,9 @@ class ConstantReadAccess extends ConstantAccess {
|
||||
* ```
|
||||
*/
|
||||
class ConstantWriteAccess extends ConstantAccess {
|
||||
override ConstantWriteAccess::Range range;
|
||||
ConstantWriteAccess() {
|
||||
explicitAssignmentNode(toGenerated(this), _) or this instanceof TNamespace
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConstantWriteAccess" }
|
||||
}
|
||||
@@ -89,8 +121,6 @@ class ConstantWriteAccess extends ConstantAccess {
|
||||
* MAX_SIZE = 100
|
||||
* ```
|
||||
*/
|
||||
class ConstantAssignment extends ConstantWriteAccess {
|
||||
override ConstantAssignment::Range range;
|
||||
|
||||
class ConstantAssignment extends ConstantWriteAccess, LhsExpr {
|
||||
override string getAPrimaryQlClass() { result = "ConstantAssignment" }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Control
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/**
|
||||
* A control expression that can be any of the following:
|
||||
@@ -9,17 +10,13 @@ private import internal.Control
|
||||
* - `while`/`until` (including expression-modifier variants)
|
||||
* - `for`
|
||||
*/
|
||||
class ControlExpr extends Expr {
|
||||
override ControlExpr::Range range;
|
||||
}
|
||||
class ControlExpr extends Expr, TControlExpr { }
|
||||
|
||||
/**
|
||||
* A conditional expression: `if`/`unless` (including expression-modifier
|
||||
* variants), and ternary-if (`?:`) expressions.
|
||||
*/
|
||||
class ConditionalExpr extends ControlExpr {
|
||||
override ConditionalExpr::Range range;
|
||||
|
||||
class ConditionalExpr extends ControlExpr, TConditionalExpr {
|
||||
/**
|
||||
* Gets the condition expression. For example, the result is `foo` in the
|
||||
* following:
|
||||
@@ -29,13 +26,19 @@ class ConditionalExpr extends ControlExpr {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getCondition() { result = range.getCondition() }
|
||||
Expr getCondition() { none() }
|
||||
|
||||
/**
|
||||
* Gets the branch of this conditional expression that is taken when the
|
||||
* condition evaluates to `cond`, if any.
|
||||
*/
|
||||
Stmt getBranch(boolean cond) { result = range.getBranch(cond) }
|
||||
Stmt getBranch(boolean cond) { none() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getCondition" and result = this.getCondition()
|
||||
or
|
||||
pred = "getBranch" and result = this.getBranch(_)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,16 +51,14 @@ class ConditionalExpr extends ControlExpr {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class IfExpr extends ConditionalExpr {
|
||||
override IfExpr::Range range;
|
||||
|
||||
class IfExpr extends ConditionalExpr, TIfExpr {
|
||||
final override string getAPrimaryQlClass() { result = "IfExpr" }
|
||||
|
||||
/** Holds if this is an `elsif` expression. */
|
||||
final predicate isElsif() { this instanceof @elsif }
|
||||
predicate isElsif() { none() }
|
||||
|
||||
/** Gets the 'then' branch of this `if`/`elsif` expression. */
|
||||
final Stmt getThen() { result = range.getThen() }
|
||||
Stmt getThen() { none() }
|
||||
|
||||
/**
|
||||
* Gets the `elsif`/`else` branch of this `if`/`elsif` expression, if any. In
|
||||
@@ -90,7 +91,51 @@ class IfExpr extends ConditionalExpr {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Stmt getElse() { result = range.getElse() }
|
||||
Stmt getElse() { none() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) {
|
||||
cond = true and result = this.getThen()
|
||||
or
|
||||
cond = false and result = this.getElse()
|
||||
}
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = ConditionalExpr.super.getAChild(pred)
|
||||
or
|
||||
pred = "getThen" and result = this.getThen()
|
||||
or
|
||||
pred = "getElse" and result = this.getElse()
|
||||
}
|
||||
}
|
||||
|
||||
private class If extends IfExpr, TIf {
|
||||
private Generated::If g;
|
||||
|
||||
If() { this = TIf(g) }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override Stmt getThen() { toGenerated(result) = g.getConsequence() }
|
||||
|
||||
final override Stmt getElse() { toGenerated(result) = g.getAlternative() }
|
||||
|
||||
final override string toString() { result = "if ..." }
|
||||
}
|
||||
|
||||
private class Elsif extends IfExpr, TElsif {
|
||||
private Generated::Elsif g;
|
||||
|
||||
Elsif() { this = TElsif(g) }
|
||||
|
||||
final override predicate isElsif() { any() }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override Stmt getThen() { toGenerated(result) = g.getConsequence() }
|
||||
|
||||
final override Stmt getElse() { toGenerated(result) = g.getAlternative() }
|
||||
|
||||
final override string toString() { result = "elsif ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,11 +146,15 @@ class IfExpr extends ConditionalExpr {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class UnlessExpr extends ConditionalExpr, @unless {
|
||||
final override UnlessExpr::Range range;
|
||||
class UnlessExpr extends ConditionalExpr, TUnlessExpr {
|
||||
private Generated::Unless g;
|
||||
|
||||
UnlessExpr() { this = TUnlessExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "UnlessExpr" }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
/**
|
||||
* Gets the 'then' branch of this `unless` expression. In the following
|
||||
* example, the result is the `StmtSequence` containing `foo`.
|
||||
@@ -117,7 +166,7 @@ class UnlessExpr extends ConditionalExpr, @unless {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Stmt getThen() { result = range.getThen() }
|
||||
final Stmt getThen() { toGenerated(result) = g.getConsequence() }
|
||||
|
||||
/**
|
||||
* Gets the 'else' branch of this `unless` expression. In the following
|
||||
@@ -130,7 +179,23 @@ class UnlessExpr extends ConditionalExpr, @unless {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Stmt getElse() { result = range.getElse() }
|
||||
final Stmt getElse() { toGenerated(result) = g.getAlternative() }
|
||||
|
||||
final override Expr getBranch(boolean cond) {
|
||||
cond = false and result = getThen()
|
||||
or
|
||||
cond = true and result = getElse()
|
||||
}
|
||||
|
||||
final override string toString() { result = "unless ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = ConditionalExpr.super.getAChild(pred)
|
||||
or
|
||||
pred = "getThen" and result = this.getThen()
|
||||
or
|
||||
pred = "getElse" and result = this.getElse()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,11 +204,17 @@ class UnlessExpr extends ConditionalExpr, @unless {
|
||||
* foo if bar
|
||||
* ```
|
||||
*/
|
||||
class IfModifierExpr extends ConditionalExpr, @if_modifier {
|
||||
final override IfModifierExpr::Range range;
|
||||
class IfModifierExpr extends ConditionalExpr, TIfModifierExpr {
|
||||
private Generated::IfModifier g;
|
||||
|
||||
IfModifierExpr() { this = TIfModifierExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "IfModifierExpr" }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) { cond = true and result = this.getBody() }
|
||||
|
||||
/**
|
||||
* Gets the statement that is conditionally evaluated. In the following
|
||||
* example, the result is the `Expr` for `foo`.
|
||||
@@ -151,7 +222,15 @@ class IfModifierExpr extends ConditionalExpr, @if_modifier {
|
||||
* foo if bar
|
||||
* ```
|
||||
*/
|
||||
final Stmt getBody() { result = range.getBody() }
|
||||
final Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override string toString() { result = "... if ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = ConditionalExpr.super.getAChild(pred)
|
||||
or
|
||||
pred = "getBody" and result = this.getBody()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -160,11 +239,17 @@ class IfModifierExpr extends ConditionalExpr, @if_modifier {
|
||||
* y /= x unless x == 0
|
||||
* ```
|
||||
*/
|
||||
class UnlessModifierExpr extends ConditionalExpr, @unless_modifier {
|
||||
final override UnlessModifierExpr::Range range;
|
||||
class UnlessModifierExpr extends ConditionalExpr, TUnlessModifierExpr {
|
||||
private Generated::UnlessModifier g;
|
||||
|
||||
UnlessModifierExpr() { this = TUnlessModifierExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "UnlessModifierExpr" }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) { cond = false and result = this.getBody() }
|
||||
|
||||
/**
|
||||
* Gets the statement that is conditionally evaluated. In the following
|
||||
* example, the result is the `Expr` for `foo`.
|
||||
@@ -172,7 +257,15 @@ class UnlessModifierExpr extends ConditionalExpr, @unless_modifier {
|
||||
* foo unless bar
|
||||
* ```
|
||||
*/
|
||||
final Stmt getBody() { result = range.getBody() }
|
||||
final Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override string toString() { result = "... unless ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = ConditionalExpr.super.getAChild(pred)
|
||||
or
|
||||
pred = "getBody" and result = this.getBody()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,20 +274,42 @@ class UnlessModifierExpr extends ConditionalExpr, @unless_modifier {
|
||||
* (a > b) ? a : b
|
||||
* ```
|
||||
*/
|
||||
class TernaryIfExpr extends ConditionalExpr, @conditional {
|
||||
final override TernaryIfExpr::Range range;
|
||||
class TernaryIfExpr extends ConditionalExpr, TTernaryIfExpr {
|
||||
private Generated::Conditional g;
|
||||
|
||||
TernaryIfExpr() { this = TTernaryIfExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "TernaryIfExpr" }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
/** Gets the 'then' branch of this ternary if expression. */
|
||||
final Stmt getThen() { result = range.getThen() }
|
||||
final Stmt getThen() { toGenerated(result) = g.getConsequence() }
|
||||
|
||||
/** Gets the 'else' branch of this ternary if expression. */
|
||||
final Stmt getElse() { result = range.getElse() }
|
||||
final Stmt getElse() { toGenerated(result) = g.getAlternative() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) {
|
||||
cond = true and result = getThen()
|
||||
or
|
||||
cond = false and result = getElse()
|
||||
}
|
||||
|
||||
final override string toString() { result = "... ? ... : ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = ConditionalExpr.super.getAChild(pred)
|
||||
or
|
||||
pred = "getThen" and result = this.getThen()
|
||||
or
|
||||
pred = "getElse" and result = this.getElse()
|
||||
}
|
||||
}
|
||||
|
||||
class CaseExpr extends ControlExpr, @case__ {
|
||||
final override CaseExpr::Range range;
|
||||
class CaseExpr extends ControlExpr, TCaseExpr {
|
||||
private Generated::Case g;
|
||||
|
||||
CaseExpr() { this = TCaseExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "CaseExpr" }
|
||||
|
||||
@@ -217,13 +332,13 @@ class CaseExpr extends ControlExpr, @case__ {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getValue() }
|
||||
|
||||
/**
|
||||
* Gets the `n`th branch of this case expression, either a `WhenExpr` or a
|
||||
* `StmtSequence`.
|
||||
*/
|
||||
final Expr getBranch(int n) { result = range.getBranch(n) }
|
||||
final Expr getBranch(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
/**
|
||||
* Gets a branch of this case expression, either a `WhenExpr` or an
|
||||
@@ -241,6 +356,14 @@ class CaseExpr extends ControlExpr, @case__ {
|
||||
* Gets the number of branches of this case expression.
|
||||
*/
|
||||
final int getNumberOfBranches() { result = count(this.getBranch(_)) }
|
||||
|
||||
final override string toString() { result = "case ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getValue" and result = this.getValue()
|
||||
or
|
||||
pred = "getBranch" and result = this.getBranch(_)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,13 +374,15 @@ class CaseExpr extends ControlExpr, @case__ {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class WhenExpr extends Expr, @when {
|
||||
final override WhenExpr::Range range;
|
||||
class WhenExpr extends Expr, TWhenExpr {
|
||||
private Generated::When g;
|
||||
|
||||
WhenExpr() { this = TWhenExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "WhenExpr" }
|
||||
|
||||
/** Gets the body of this case-when expression. */
|
||||
final Stmt getBody() { result = range.getBody() }
|
||||
final Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
/**
|
||||
* Gets the `n`th pattern (or condition) in this case-when expression. In the
|
||||
@@ -270,7 +395,7 @@ class WhenExpr extends Expr, @when {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getPattern(int n) { result = range.getPattern(n) }
|
||||
final Expr getPattern(int n) { toGenerated(result) = g.getPattern(n).getChild() }
|
||||
|
||||
/**
|
||||
* Gets a pattern (or condition) in this case-when expression.
|
||||
@@ -281,28 +406,40 @@ class WhenExpr extends Expr, @when {
|
||||
* Gets the number of patterns in this case-when expression.
|
||||
*/
|
||||
final int getNumberOfPatterns() { result = count(this.getPattern(_)) }
|
||||
|
||||
final override string toString() { result = "when ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getBody" and result = this.getBody()
|
||||
or
|
||||
pred = "getPattern" and result = this.getPattern(_)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A loop. That is, a `for` loop, a `while` or `until` loop, or their
|
||||
* expression-modifier variants.
|
||||
*/
|
||||
class Loop extends ControlExpr {
|
||||
override Loop::Range range;
|
||||
|
||||
class Loop extends ControlExpr, TLoop {
|
||||
/** Gets the body of this loop. */
|
||||
Stmt getBody() { result = range.getBody() }
|
||||
Stmt getBody() { none() }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getBody" and result = this.getBody() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A loop using a condition expression. That is, a `while` or `until` loop, or
|
||||
* their expression-modifier variants.
|
||||
*/
|
||||
class ConditionalLoop extends Loop {
|
||||
override ConditionalLoop::Range range;
|
||||
|
||||
class ConditionalLoop extends Loop, TConditionalLoop {
|
||||
/** Gets the condition expression of this loop. */
|
||||
final Expr getCondition() { result = range.getCondition() }
|
||||
Expr getCondition() { none() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Loop.super.getAChild(pred)
|
||||
or
|
||||
pred = "getCondition" and result = this.getCondition()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -314,13 +451,19 @@ class ConditionalLoop extends Loop {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class WhileExpr extends ConditionalLoop, @while {
|
||||
final override WhileExpr::Range range;
|
||||
class WhileExpr extends ConditionalLoop, TWhileExpr {
|
||||
private Generated::While g;
|
||||
|
||||
WhileExpr() { this = TWhileExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "WhileExpr" }
|
||||
|
||||
/** Gets the body of this `while` loop. */
|
||||
final override Stmt getBody() { result = range.getBody() }
|
||||
final override Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override string toString() { result = "while ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,13 +475,19 @@ class WhileExpr extends ConditionalLoop, @while {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class UntilExpr extends ConditionalLoop, @until {
|
||||
final override UntilExpr::Range range;
|
||||
class UntilExpr extends ConditionalLoop, TUntilExpr {
|
||||
private Generated::Until g;
|
||||
|
||||
UntilExpr() { this = TUntilExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "UntilExpr" }
|
||||
|
||||
/** Gets the body of this `until` loop. */
|
||||
final override Stmt getBody() { result = range.getBody() }
|
||||
final override Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override string toString() { result = "until ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,10 +496,18 @@ class UntilExpr extends ConditionalLoop, @until {
|
||||
* foo while bar
|
||||
* ```
|
||||
*/
|
||||
class WhileModifierExpr extends ConditionalLoop, @while_modifier {
|
||||
final override WhileModifierExpr::Range range;
|
||||
class WhileModifierExpr extends ConditionalLoop, TWhileModifierExpr {
|
||||
private Generated::WhileModifier g;
|
||||
|
||||
WhileModifierExpr() { this = TWhileModifierExpr(g) }
|
||||
|
||||
final override Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "WhileModifierExpr" }
|
||||
|
||||
final override string toString() { result = "... while ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,10 +516,18 @@ class WhileModifierExpr extends ConditionalLoop, @while_modifier {
|
||||
* foo until bar
|
||||
* ```
|
||||
*/
|
||||
class UntilModifierExpr extends ConditionalLoop, @until_modifier {
|
||||
final override UntilModifierExpr::Range range;
|
||||
class UntilModifierExpr extends ConditionalLoop, TUntilModifierExpr {
|
||||
private Generated::UntilModifier g;
|
||||
|
||||
UntilModifierExpr() { this = TUntilModifierExpr(g) }
|
||||
|
||||
final override Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override Expr getCondition() { toGenerated(result) = g.getCondition() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "UntilModifierExpr" }
|
||||
|
||||
final override string toString() { result = "... until ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,16 +538,18 @@ class UntilModifierExpr extends ConditionalLoop, @until_modifier {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class ForExpr extends Loop, @for {
|
||||
final override ForExpr::Range range;
|
||||
class ForExpr extends Loop, TForExpr {
|
||||
private Generated::For g;
|
||||
|
||||
ForExpr() { this = TForExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ForExpr" }
|
||||
|
||||
/** Gets the body of this `for` loop. */
|
||||
final override Stmt getBody() { result = range.getBody() }
|
||||
final override Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
/** Gets the pattern representing the iteration argument. */
|
||||
final Pattern getPattern() { result = range.getPattern() }
|
||||
final Pattern getPattern() { toGenerated(result) = g.getPattern() }
|
||||
|
||||
/**
|
||||
* Gets the value being iterated over. In the following example, the result
|
||||
@@ -393,5 +560,15 @@ class ForExpr extends Loop, @for {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getValue().getChild() }
|
||||
|
||||
final override string toString() { result = "for ... in ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Loop.super.getAChild(pred)
|
||||
or
|
||||
pred = "getPattern" and result = this.getPattern()
|
||||
or
|
||||
pred = "getValue" and result = this.getValue()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Expr
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/**
|
||||
* An expression.
|
||||
*
|
||||
* This is the root QL class for all expressions.
|
||||
*/
|
||||
class Expr extends Stmt {
|
||||
override Expr::Range range;
|
||||
|
||||
Expr() { this = range }
|
||||
}
|
||||
class Expr extends Stmt, TExpr { }
|
||||
|
||||
/**
|
||||
* A reference to the current object. For example:
|
||||
@@ -18,10 +15,10 @@ class Expr extends Stmt {
|
||||
* - `self.method_name`
|
||||
* - `def self.method_name ... end`
|
||||
*/
|
||||
class Self extends Expr, @token_self {
|
||||
override Self::Range range;
|
||||
|
||||
class Self extends Expr, TSelf {
|
||||
final override string getAPrimaryQlClass() { result = "Self" }
|
||||
|
||||
final override string toString() { result = "self" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,20 +32,43 @@ class Self extends Expr, @token_self {
|
||||
* return 1, 2, *items, k: 5, **map
|
||||
* ```
|
||||
*/
|
||||
class ArgumentList extends Expr {
|
||||
override ArgumentList::Range range;
|
||||
class ArgumentList extends Expr, TArgumentList {
|
||||
private Generated::AstNode g;
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ArgumentList" }
|
||||
ArgumentList() { this = TArgumentList(g) }
|
||||
|
||||
/** Gets the `i`th element in this argument list. */
|
||||
Expr getElement(int i) {
|
||||
toGenerated(result) in [
|
||||
g.(Generated::ArgumentList).getChild(i), g.(Generated::RightAssignmentList).getChild(i)
|
||||
]
|
||||
}
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ArgumentList" }
|
||||
|
||||
final override string toString() { result = "..., ..." }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getElement" and result = this.getElement(_)
|
||||
}
|
||||
}
|
||||
|
||||
/** A sequence of expressions. */
|
||||
class StmtSequence extends Expr {
|
||||
override StmtSequence::Range range;
|
||||
|
||||
class StmtSequence extends Expr, TStmtSequence {
|
||||
override string getAPrimaryQlClass() { result = "StmtSequence" }
|
||||
|
||||
override string toString() {
|
||||
exists(int c | c = this.getNumberOfStatements() |
|
||||
c = 0 and result = ";"
|
||||
or
|
||||
c = 1 and result = this.getStmt(0).toString()
|
||||
or
|
||||
c > 1 and result = "...; ..."
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the `n`th statement in this sequence. */
|
||||
final Stmt getStmt(int n) { result = range.getStmt(n) }
|
||||
Stmt getStmt(int n) { none() }
|
||||
|
||||
/** Gets a statement in this sequence. */
|
||||
final Stmt getAStmt() { result = this.getStmt(_) }
|
||||
@@ -61,6 +81,42 @@ class StmtSequence extends Expr {
|
||||
|
||||
/** Holds if this sequence has no statements. */
|
||||
final predicate isEmpty() { this.getNumberOfStatements() = 0 }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getStmt" and result = this.getStmt(_) }
|
||||
}
|
||||
|
||||
private class Then extends StmtSequence, TThen {
|
||||
private Generated::Then g;
|
||||
|
||||
Then() { this = TThen(g) }
|
||||
|
||||
override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
private class Else extends StmtSequence, TElse {
|
||||
private Generated::Else g;
|
||||
|
||||
Else() { this = TElse(g) }
|
||||
|
||||
override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
private class Do extends StmtSequence, TDo {
|
||||
private Generated::Do g;
|
||||
|
||||
Do() { this = TDo(g) }
|
||||
|
||||
override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
private class Ensure extends StmtSequence, TEnsure {
|
||||
private Generated::Ensure g;
|
||||
|
||||
Ensure() { this = TEnsure(g) }
|
||||
|
||||
override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
final override string toString() { result = "ensure ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,22 +124,70 @@ class StmtSequence extends Expr {
|
||||
* or do-block. That is, any body that may also include rescue/ensure/else
|
||||
* statements.
|
||||
*/
|
||||
class BodyStatement extends StmtSequence {
|
||||
override BodyStatement::Range range;
|
||||
class BodyStmt extends StmtSequence, TBodyStmt {
|
||||
// Not defined by dispatch, as it should not be exposed
|
||||
private Generated::AstNode getChild(int i) {
|
||||
result = any(Generated::Method g | this = TMethod(g)).getChild(i)
|
||||
or
|
||||
result = any(Generated::SingletonMethod g | this = TSingletonMethod(g)).getChild(i)
|
||||
or
|
||||
exists(Generated::Lambda g | this = TLambda(g) |
|
||||
result = g.getBody().(Generated::DoBlock).getChild(i) or
|
||||
result = g.getBody().(Generated::Block).getChild(i)
|
||||
)
|
||||
or
|
||||
result = any(Generated::DoBlock g | this = TDoBlock(g)).getChild(i)
|
||||
or
|
||||
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)
|
||||
or
|
||||
result = any(Generated::SingletonClass g | this = TSingletonClass(g)).getChild(i)
|
||||
or
|
||||
result = any(Generated::Module g | this = TModule(g)).getChild(i)
|
||||
or
|
||||
result = any(Generated::Begin g | this = TBeginExpr(g)).getChild(i)
|
||||
}
|
||||
|
||||
final override Stmt getStmt(int n) {
|
||||
result =
|
||||
rank[n + 1](AstNode node, int i |
|
||||
toGenerated(node) = this.getChild(i) and
|
||||
not node instanceof Else and
|
||||
not node instanceof RescueClause and
|
||||
not node instanceof Ensure
|
||||
|
|
||||
node order by i
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the `n`th rescue clause in this block. */
|
||||
final RescueClause getRescue(int n) { result = range.getRescue(n) }
|
||||
final RescueClause getRescue(int n) {
|
||||
result =
|
||||
rank[n + 1](RescueClause node, int i | toGenerated(node) = getChild(i) | node order by i)
|
||||
}
|
||||
|
||||
/** Gets a rescue clause in this block. */
|
||||
final RescueClause getARescue() { result = this.getRescue(_) }
|
||||
|
||||
/** Gets the `else` clause in this block, if any. */
|
||||
final StmtSequence getElse() { result = range.getElse() }
|
||||
final StmtSequence getElse() { result = unique(Else s | toGenerated(s) = getChild(_)) }
|
||||
|
||||
/** Gets the `ensure` clause in this block, if any. */
|
||||
final StmtSequence getEnsure() { result = range.getEnsure() }
|
||||
final StmtSequence getEnsure() { result = unique(Ensure s | toGenerated(s) = getChild(_)) }
|
||||
|
||||
final predicate hasEnsure() { exists(this.getEnsure()) }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = StmtSequence.super.getAChild(pred)
|
||||
or
|
||||
pred = "getRescue" and result = this.getRescue(_)
|
||||
or
|
||||
pred = "getElse" and result = this.getElse()
|
||||
or
|
||||
pred = "getEnsure" and result = this.getEnsure()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,10 +205,22 @@ class BodyStatement extends StmtSequence {
|
||||
* ()
|
||||
* ```
|
||||
*/
|
||||
class ParenthesizedExpr extends StmtSequence, @parenthesized_statements {
|
||||
final override ParenthesizedExpr::Range range;
|
||||
class ParenthesizedExpr extends StmtSequence, TParenthesizedExpr {
|
||||
private Generated::ParenthesizedStatements g;
|
||||
|
||||
ParenthesizedExpr() { this = TParenthesizedExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ParenthesizedExpr" }
|
||||
|
||||
final override string toString() {
|
||||
exists(int c | c = this.getNumberOfStatements() |
|
||||
c = 0 and result = "()"
|
||||
or
|
||||
c > 0 and result = "(" + StmtSequence.super.toString() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,8 +233,10 @@ class ParenthesizedExpr extends StmtSequence, @parenthesized_statements {
|
||||
* baz(qux: 1)
|
||||
* ```
|
||||
*/
|
||||
class Pair extends Expr, @pair {
|
||||
final override Pair::Range range;
|
||||
class Pair extends Expr, TPair {
|
||||
private Generated::Pair g;
|
||||
|
||||
Pair() { this = TPair(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Pair" }
|
||||
|
||||
@@ -133,7 +251,7 @@ class Pair extends Expr, @pair {
|
||||
* { 'foo' => 123 }
|
||||
* ```
|
||||
*/
|
||||
final Expr getKey() { result = range.getKey() }
|
||||
final Expr getKey() { toGenerated(result) = g.getKey() }
|
||||
|
||||
/**
|
||||
* Gets the value expression of this pair. For example, the `InteralLiteral`
|
||||
@@ -142,7 +260,15 @@ class Pair extends Expr, @pair {
|
||||
* { 'foo' => 123 }
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getValue() }
|
||||
|
||||
final override string toString() { result = "Pair" }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getKey" and result = this.getKey()
|
||||
or
|
||||
pred = "getValue" and result = this.getValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,8 +280,10 @@ class Pair extends Expr, @pair {
|
||||
* puts msg
|
||||
* end
|
||||
*/
|
||||
class RescueClause extends Expr, @rescue {
|
||||
final override RescueClause::Range range;
|
||||
class RescueClause extends Expr, TRescueClause {
|
||||
private Generated::Rescue g;
|
||||
|
||||
RescueClause() { this = TRescueClause(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "RescueClause" }
|
||||
|
||||
@@ -169,7 +297,7 @@ class RescueClause extends Expr, @rescue {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getException(int n) { result = range.getException(n) }
|
||||
final Expr getException(int n) { toGenerated(result) = g.getExceptions().getChild(n) }
|
||||
|
||||
/**
|
||||
* Gets an exception to match, if any. For example `FirstError` or `SecondError` in:
|
||||
@@ -181,7 +309,7 @@ class RescueClause extends Expr, @rescue {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getAnException() { result = getException(_) }
|
||||
final Expr getAnException() { result = this.getException(_) }
|
||||
|
||||
/**
|
||||
* Gets the variable to which to assign the matched exception, if any.
|
||||
@@ -194,12 +322,22 @@ class RescueClause extends Expr, @rescue {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final LhsExpr getVariableExpr() { result = range.getVariableExpr() }
|
||||
final LhsExpr getVariableExpr() { toGenerated(result) = g.getVariable().getChild() }
|
||||
|
||||
/**
|
||||
* Gets the exception handler body.
|
||||
*/
|
||||
final StmtSequence getBody() { result = range.getBody() }
|
||||
final StmtSequence getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
final override string toString() { result = "rescue ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getException" and result = this.getException(_)
|
||||
or
|
||||
pred = "getVariableExpr" and result = this.getVariableExpr()
|
||||
or
|
||||
pred = "getBody" and result = this.getBody()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,8 +346,10 @@ class RescueClause extends Expr, @rescue {
|
||||
* contents = read_file rescue ""
|
||||
* ```
|
||||
*/
|
||||
class RescueModifierExpr extends Expr, @rescue_modifier {
|
||||
final override RescueModifierExpr::Range range;
|
||||
class RescueModifierExpr extends Expr, TRescueModifierExpr {
|
||||
private Generated::RescueModifier g;
|
||||
|
||||
RescueModifierExpr() { this = TRescueModifierExpr(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "RescueModifierExpr" }
|
||||
|
||||
@@ -219,7 +359,7 @@ class RescueModifierExpr extends Expr, @rescue_modifier {
|
||||
* body rescue handler
|
||||
* ```
|
||||
*/
|
||||
final Stmt getBody() { result = range.getBody() }
|
||||
final Stmt getBody() { toGenerated(result) = g.getBody() }
|
||||
|
||||
/**
|
||||
* Gets the exception handler of this `RescueModifierExpr`.
|
||||
@@ -227,7 +367,15 @@ class RescueModifierExpr extends Expr, @rescue_modifier {
|
||||
* body rescue handler
|
||||
* ```
|
||||
*/
|
||||
final Stmt getHandler() { result = range.getHandler() }
|
||||
final Stmt getHandler() { toGenerated(result) = g.getHandler() }
|
||||
|
||||
final override string toString() { result = "... rescue ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getBody" and result = this.getBody()
|
||||
or
|
||||
pred = "getHandler" and result = this.getHandler()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,13 +385,15 @@ class RescueModifierExpr extends Expr, @rescue_modifier {
|
||||
* "foo" "bar" "baz"
|
||||
* ```
|
||||
*/
|
||||
class StringConcatenation extends Expr, @chained_string {
|
||||
final override StringConcatenation::Range range;
|
||||
class StringConcatenation extends Expr, TStringConcatenation {
|
||||
private Generated::ChainedString g;
|
||||
|
||||
StringConcatenation() { this = TStringConcatenation(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "StringConcatenation" }
|
||||
|
||||
/** Gets the `n`th string literal in this concatenation. */
|
||||
final StringLiteral getString(int n) { result = range.getString(n) }
|
||||
final StringLiteral getString(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
/** Gets a string literal in this concatenation. */
|
||||
final StringLiteral getAString() { result = this.getString(_) }
|
||||
@@ -277,4 +427,8 @@ class StringConcatenation extends Expr, @chained_string {
|
||||
valueText order by i
|
||||
)
|
||||
}
|
||||
|
||||
final override string toString() { result = "\"...\" \"...\"" }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getString" and result = this.getString(_) }
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Literal
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/**
|
||||
* A literal.
|
||||
*
|
||||
* This is the QL root class for all literals.
|
||||
*/
|
||||
class Literal extends Expr {
|
||||
override Literal::Range range;
|
||||
|
||||
class Literal extends Expr, TLiteral {
|
||||
/**
|
||||
* Gets the source text for this literal, if this is a simple literal.
|
||||
*
|
||||
* For complex literals, such as arrays, hashes, and strings with
|
||||
* interpolations, this predicate has no result.
|
||||
*/
|
||||
final string getValueText() { result = range.getValueText() }
|
||||
string getValueText() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,9 +30,7 @@ class Literal extends Expr {
|
||||
* 1i
|
||||
* ```
|
||||
*/
|
||||
class NumericLiteral extends Literal {
|
||||
override NumericLiteral::Range range;
|
||||
}
|
||||
class NumericLiteral extends Literal, TNumericLiteral { }
|
||||
|
||||
/**
|
||||
* An integer literal.
|
||||
@@ -43,8 +40,14 @@ class NumericLiteral extends Literal {
|
||||
* 0xff
|
||||
* ```
|
||||
*/
|
||||
class IntegerLiteral extends NumericLiteral, @token_integer {
|
||||
final override IntegerLiteral::Range range;
|
||||
class IntegerLiteral extends NumericLiteral, TIntegerLiteral {
|
||||
private Generated::Integer g;
|
||||
|
||||
IntegerLiteral() { this = TIntegerLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "IntegerLiteral" }
|
||||
}
|
||||
@@ -57,8 +60,14 @@ class IntegerLiteral extends NumericLiteral, @token_integer {
|
||||
* 2.7e+5
|
||||
* ```
|
||||
*/
|
||||
class FloatLiteral extends NumericLiteral, @token_float {
|
||||
final override FloatLiteral::Range range;
|
||||
class FloatLiteral extends NumericLiteral, TFloatLiteral {
|
||||
private Generated::Float g;
|
||||
|
||||
FloatLiteral() { this = TFloatLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "FloatLiteral" }
|
||||
}
|
||||
@@ -70,8 +79,14 @@ class FloatLiteral extends NumericLiteral, @token_float {
|
||||
* 123r
|
||||
* ```
|
||||
*/
|
||||
class RationalLiteral extends NumericLiteral, @rational {
|
||||
final override RationalLiteral::Range range;
|
||||
class RationalLiteral extends NumericLiteral, TRationalLiteral {
|
||||
private Generated::Rational g;
|
||||
|
||||
RationalLiteral() { this = TRationalLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getChild().(Generated::Token).getValue() + "r" }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "RationalLiteral" }
|
||||
}
|
||||
@@ -83,15 +98,27 @@ class RationalLiteral extends NumericLiteral, @rational {
|
||||
* 1i
|
||||
* ```
|
||||
*/
|
||||
class ComplexLiteral extends NumericLiteral, @token_complex {
|
||||
final override ComplexLiteral::Range range;
|
||||
class ComplexLiteral extends NumericLiteral, TComplexLiteral {
|
||||
private Generated::Complex g;
|
||||
|
||||
ComplexLiteral() { this = TComplexLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ComplexLiteral" }
|
||||
}
|
||||
|
||||
/** A `nil` literal. */
|
||||
class NilLiteral extends Literal, @token_nil {
|
||||
final override NilLiteral::Range range;
|
||||
class NilLiteral extends Literal, TNilLiteral {
|
||||
private Generated::Nil g;
|
||||
|
||||
NilLiteral() { this = TNilLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "NilLiteral" }
|
||||
}
|
||||
@@ -105,30 +132,48 @@ class NilLiteral extends Literal, @token_nil {
|
||||
* FALSE
|
||||
* ```
|
||||
*/
|
||||
class BooleanLiteral extends Literal, BooleanLiteral::DbUnion {
|
||||
final override BooleanLiteral::Range range;
|
||||
|
||||
class BooleanLiteral extends Literal, TBooleanLiteral {
|
||||
final override string getAPrimaryQlClass() { result = "BooleanLiteral" }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
/** Holds if the Boolean literal is `true` or `TRUE`. */
|
||||
predicate isTrue() { range.isTrue() }
|
||||
predicate isTrue() { none() }
|
||||
|
||||
/** Holds if the Boolean literal is `false` or `FALSE`. */
|
||||
predicate isFalse() { range.isFalse() }
|
||||
predicate isFalse() { none() }
|
||||
}
|
||||
|
||||
private class TrueLiteral extends BooleanLiteral, TTrueLiteral {
|
||||
private Generated::True g;
|
||||
|
||||
TrueLiteral() { this = TTrueLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override predicate isTrue() { any() }
|
||||
}
|
||||
|
||||
private class FalseLiteral extends BooleanLiteral, TFalseLiteral {
|
||||
private Generated::False g;
|
||||
|
||||
FalseLiteral() { this = TFalseLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override predicate isFalse() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The base class for a component of a string: `StringTextComponent`,
|
||||
* `StringEscapeSequenceComponent`, or `StringInterpolationComponent`.
|
||||
*/
|
||||
class StringComponent extends AstNode {
|
||||
override StringComponent::Range range;
|
||||
|
||||
class StringComponent extends AstNode, TStringComponent {
|
||||
/**
|
||||
* Gets the source text for this string component. Has no result if this is
|
||||
* a `StringInterpolationComponent`.
|
||||
*/
|
||||
final string getValueText() { result = range.getValueText() }
|
||||
string getValueText() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -143,8 +188,14 @@ class StringComponent extends AstNode {
|
||||
* "foo#{ bar() } baz"
|
||||
* ```
|
||||
*/
|
||||
class StringTextComponent extends StringComponent, StringTextComponent::StringContentToken {
|
||||
final override StringTextComponent::Range range;
|
||||
class StringTextComponent extends StringComponent, TStringTextComponent {
|
||||
private Generated::Token g;
|
||||
|
||||
StringTextComponent() { this = TStringTextComponent(g) }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "StringTextComponent" }
|
||||
}
|
||||
@@ -152,8 +203,14 @@ class StringTextComponent extends StringComponent, StringTextComponent::StringCo
|
||||
/**
|
||||
* An escape sequence component of a string or string-like literal.
|
||||
*/
|
||||
class StringEscapeSequenceComponent extends StringComponent, @token_escape_sequence {
|
||||
final override StringEscapeSequenceComponent::Range range;
|
||||
class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponent {
|
||||
private Generated::EscapeSequence g;
|
||||
|
||||
StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "StringEscapeSequenceComponent" }
|
||||
}
|
||||
@@ -161,8 +218,17 @@ class StringEscapeSequenceComponent extends StringComponent, @token_escape_seque
|
||||
/**
|
||||
* An interpolation expression component of a string or string-like literal.
|
||||
*/
|
||||
class StringInterpolationComponent extends StringComponent, StmtSequence, @interpolation {
|
||||
final override StringInterpolationComponent::Range range;
|
||||
class StringInterpolationComponent extends StringComponent, StmtSequence,
|
||||
TStringInterpolationComponent {
|
||||
private Generated::Interpolation g;
|
||||
|
||||
StringInterpolationComponent() { this = TStringInterpolationComponent(g) }
|
||||
|
||||
final override string toString() { result = "#{...}" }
|
||||
|
||||
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
final override string getValueText() { none() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
|
||||
}
|
||||
@@ -170,9 +236,7 @@ class StringInterpolationComponent extends StringComponent, StmtSequence, @inter
|
||||
/**
|
||||
* A string, symbol, regex, or subshell literal.
|
||||
*/
|
||||
class StringlikeLiteral extends Literal {
|
||||
override StringlikeLiteral::Range range;
|
||||
|
||||
class StringlikeLiteral extends Literal, TStringlikeLiteral {
|
||||
/**
|
||||
* Gets the `n`th component of this string or string-like literal. The result
|
||||
* will be one of `StringTextComponent`, `StringInterpolationComponent`, and
|
||||
@@ -186,7 +250,7 @@ class StringlikeLiteral extends Literal {
|
||||
* "foo_#{ Time.now }"
|
||||
* ```
|
||||
*/
|
||||
final StringComponent getComponent(int n) { result = range.getComponent(n) }
|
||||
StringComponent getComponent(int n) { none() }
|
||||
|
||||
/**
|
||||
* Gets the number of components in this string or string-like literal.
|
||||
@@ -206,6 +270,91 @@ class StringlikeLiteral extends Literal {
|
||||
* ```
|
||||
*/
|
||||
final int getNumberOfComponents() { result = count(this.getComponent(_)) }
|
||||
|
||||
private string getStartDelimiter() {
|
||||
this instanceof TStringLiteral and
|
||||
result = "\""
|
||||
or
|
||||
this instanceof TRegexLiteral and
|
||||
result = "/"
|
||||
or
|
||||
this instanceof TSimpleSymbolLiteral and
|
||||
result = ":"
|
||||
or
|
||||
this instanceof TComplexSymbolLiteral and
|
||||
result = ":\""
|
||||
or
|
||||
this instanceof THashKeySymbolLiteral and
|
||||
result = ""
|
||||
or
|
||||
this instanceof TSubshellLiteral and
|
||||
result = "`"
|
||||
or
|
||||
this instanceof THereDoc and
|
||||
result = ""
|
||||
}
|
||||
|
||||
private string getEndDelimiter() {
|
||||
this instanceof TStringLiteral and
|
||||
result = "\""
|
||||
or
|
||||
this instanceof TRegexLiteral and
|
||||
result = "/"
|
||||
or
|
||||
this instanceof TSimpleSymbolLiteral and
|
||||
result = ""
|
||||
or
|
||||
this instanceof TComplexSymbolLiteral and
|
||||
result = "\""
|
||||
or
|
||||
this instanceof THashKeySymbolLiteral and
|
||||
result = ""
|
||||
or
|
||||
this instanceof TSubshellLiteral and
|
||||
result = "`"
|
||||
or
|
||||
this instanceof THereDoc and
|
||||
result = ""
|
||||
}
|
||||
|
||||
override string getValueText() {
|
||||
// 0 components should result in the empty string
|
||||
// if there are any interpolations, there should be no result
|
||||
// otherwise, concatenate all the components
|
||||
forall(StringComponent c | c = this.getComponent(_) |
|
||||
not c instanceof StringInterpolationComponent
|
||||
) and
|
||||
result =
|
||||
concat(StringComponent c, int i | c = this.getComponent(i) | c.getValueText() order by i)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(string full, string summary |
|
||||
full =
|
||||
concat(StringComponent c, int i, string s |
|
||||
c = this.getComponent(i) and
|
||||
(
|
||||
s = toGenerated(c).(Generated::Token).getValue()
|
||||
or
|
||||
not toGenerated(c) instanceof Generated::Token and
|
||||
s = "#{...}"
|
||||
)
|
||||
|
|
||||
s order by i
|
||||
) and
|
||||
(
|
||||
// summary should be 32 chars max (incl. ellipsis)
|
||||
full.length() > 32 and summary = full.substring(0, 29) + "..."
|
||||
or
|
||||
full.length() <= 32 and summary = full
|
||||
) and
|
||||
result = this.getStartDelimiter() + summary + this.getEndDelimiter()
|
||||
)
|
||||
}
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getComponent" and result = this.getComponent(_)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,12 +365,26 @@ class StringlikeLiteral extends Literal {
|
||||
* "hello, #{name}"
|
||||
* ```
|
||||
*/
|
||||
class StringLiteral extends StringlikeLiteral {
|
||||
final override StringLiteral::Range range;
|
||||
|
||||
class StringLiteral extends StringlikeLiteral, TStringLiteral {
|
||||
final override string getAPrimaryQlClass() { result = "StringLiteral" }
|
||||
}
|
||||
|
||||
private class RegularStringLiteral extends StringLiteral, TRegularStringLiteral {
|
||||
private Generated::String g;
|
||||
|
||||
RegularStringLiteral() { this = TRegularStringLiteral(g) }
|
||||
|
||||
final override StringComponent getComponent(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
private class BareStringLiteral extends StringLiteral, TBareStringLiteral {
|
||||
private Generated::BareString g;
|
||||
|
||||
BareStringLiteral() { this = TBareStringLiteral(g) }
|
||||
|
||||
final override StringComponent getComponent(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A regular expression literal.
|
||||
*
|
||||
@@ -229,11 +392,15 @@ class StringLiteral extends StringlikeLiteral {
|
||||
* /[a-z]+/
|
||||
* ```
|
||||
*/
|
||||
class RegexLiteral extends StringlikeLiteral, @regex {
|
||||
final override RegexLiteral::Range range;
|
||||
class RegexLiteral extends StringlikeLiteral, TRegexLiteral {
|
||||
private Generated::Regex g;
|
||||
|
||||
RegexLiteral() { this = TRegexLiteral(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "RegexLiteral" }
|
||||
|
||||
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
|
||||
|
||||
/**
|
||||
* Gets the regex flags as a string.
|
||||
*
|
||||
@@ -242,7 +409,16 @@ class RegexLiteral extends StringlikeLiteral, @regex {
|
||||
* /foo/i # => "i"
|
||||
* /foo/imxo # => "imxo"
|
||||
*/
|
||||
final string getFlagString() { result = range.getFlagString() }
|
||||
final string getFlagString() {
|
||||
// For `/foo/i`, there should be an `/i` token in the database with `this`
|
||||
// as its parents. Strip the delimiter, which can vary.
|
||||
result =
|
||||
max(Generated::Token t |
|
||||
t.getParent() = g
|
||||
|
|
||||
t.getValue().suffix(1) order by t.getParentIndex()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the regex was specified using the `i` flag to indicate case
|
||||
@@ -264,16 +440,49 @@ class RegexLiteral extends StringlikeLiteral, @regex {
|
||||
* :"foo bar #{baz}"
|
||||
* ```
|
||||
*/
|
||||
class SymbolLiteral extends StringlikeLiteral {
|
||||
final override SymbolLiteral::Range range;
|
||||
|
||||
SymbolLiteral() {
|
||||
not any(UndefStmt u).getAMethodName() = this and
|
||||
not any(AliasStmt a).getNewName() = this and
|
||||
not any(AliasStmt a).getOldName() = this
|
||||
class SymbolLiteral extends StringlikeLiteral, TSymbolLiteral {
|
||||
final override string getAPrimaryQlClass() {
|
||||
not this instanceof MethodName and result = "SymbolLiteral"
|
||||
}
|
||||
}
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SymbolLiteral" }
|
||||
private class SimpleSymbolLiteral extends SymbolLiteral, TSimpleSymbolLiteral {
|
||||
private Generated::SimpleSymbol g;
|
||||
|
||||
SimpleSymbolLiteral() { this = TSimpleSymbolLiteral(g) }
|
||||
|
||||
// Tree-sitter gives us value text including the colon, which we skip.
|
||||
final override string getValueText() { result = g.getValue().suffix(1) }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
private class ComplexSymbolLiteral extends SymbolLiteral, TComplexSymbolLiteral { }
|
||||
|
||||
private class DelimitedSymbolLiteral extends ComplexSymbolLiteral, TDelimitedSymbolLiteral {
|
||||
private Generated::DelimitedSymbol g;
|
||||
|
||||
DelimitedSymbolLiteral() { this = TDelimitedSymbolLiteral(g) }
|
||||
|
||||
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
|
||||
}
|
||||
|
||||
private class BareSymbolLiteral extends ComplexSymbolLiteral, TBareSymbolLiteral {
|
||||
private Generated::BareSymbol g;
|
||||
|
||||
BareSymbolLiteral() { this = TBareSymbolLiteral(g) }
|
||||
|
||||
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
|
||||
}
|
||||
|
||||
private class HashKeySymbolLiteral extends SymbolLiteral, THashKeySymbolLiteral {
|
||||
private Generated::HashKeySymbol g;
|
||||
|
||||
HashKeySymbolLiteral() { this = THashKeySymbolLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string toString() { result = ":" + this.getValueText() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,10 +493,14 @@ class SymbolLiteral extends StringlikeLiteral {
|
||||
* %x(/bin/sh foo.sh)
|
||||
* ```
|
||||
*/
|
||||
class SubshellLiteral extends StringlikeLiteral, @subshell {
|
||||
final override SubshellLiteral::Range range;
|
||||
class SubshellLiteral extends StringlikeLiteral, TSubshellLiteral {
|
||||
private Generated::Subshell g;
|
||||
|
||||
SubshellLiteral() { this = TSubshellLiteral(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SubshellLiteral" }
|
||||
|
||||
final override StringComponent getComponent(int i) { toGenerated(result) = g.getChild(i) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -298,8 +511,14 @@ class SubshellLiteral extends StringlikeLiteral, @subshell {
|
||||
* ?\u{61}
|
||||
* ```
|
||||
*/
|
||||
class CharacterLiteral extends Literal, @token_character {
|
||||
final override CharacterLiteral::Range range;
|
||||
class CharacterLiteral extends Literal, TCharacterLiteral {
|
||||
private Generated::Character g;
|
||||
|
||||
CharacterLiteral() { this = TCharacterLiteral(g) }
|
||||
|
||||
final override string getValueText() { result = g.getValue() }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "CharacterLiteral" }
|
||||
}
|
||||
@@ -313,8 +532,10 @@ class CharacterLiteral extends Literal, @token_character {
|
||||
* SQL
|
||||
* ```
|
||||
*/
|
||||
class HereDoc extends StringlikeLiteral {
|
||||
final override HereDoc::Range range;
|
||||
class HereDoc extends StringlikeLiteral, THereDoc {
|
||||
private Generated::HeredocBeginning g;
|
||||
|
||||
HereDoc() { this = THereDoc(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "HereDoc" }
|
||||
|
||||
@@ -336,7 +557,13 @@ class HereDoc extends StringlikeLiteral {
|
||||
* <<`IDENTIFIER`
|
||||
* ```
|
||||
*/
|
||||
final string getQuoteStyle() { result = range.getQuoteStyle() }
|
||||
final string getQuoteStyle() {
|
||||
exists(string s |
|
||||
s = g.getValue() and
|
||||
s.charAt(s.length() - 1) = result and
|
||||
result = ["'", "`", "\""]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the indentation modifier (`-` or `~`) of the here document identifier, if any.
|
||||
@@ -346,7 +573,36 @@ class HereDoc extends StringlikeLiteral {
|
||||
* <<IDENTIFIER
|
||||
* ```
|
||||
*/
|
||||
final string getIndentationModifier() { result = range.getIndentationModifier() }
|
||||
final string getIndentationModifier() {
|
||||
exists(string s |
|
||||
s = g.getValue() and
|
||||
s.charAt(2) = result and
|
||||
result = ["-", "~"]
|
||||
)
|
||||
}
|
||||
|
||||
private Generated::HeredocBody getBody() {
|
||||
exists(int i, File f |
|
||||
g =
|
||||
rank[i](Generated::HeredocBeginning b |
|
||||
f = b.getLocation().getFile()
|
||||
|
|
||||
b order by b.getLocation().getStartLine(), b.getLocation().getStartColumn()
|
||||
) and
|
||||
result =
|
||||
rank[i](Generated::HeredocBody b |
|
||||
f = b.getLocation().getFile()
|
||||
|
|
||||
b order by b.getLocation().getStartLine(), b.getLocation().getStartColumn()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override StringComponent getComponent(int n) {
|
||||
toGenerated(result) = this.getBody().getChild(n)
|
||||
}
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,19 +614,51 @@ class HereDoc extends StringlikeLiteral {
|
||||
* %i(foo bar)
|
||||
* ```
|
||||
*/
|
||||
class ArrayLiteral extends Literal {
|
||||
final override ArrayLiteral::Range range;
|
||||
|
||||
class ArrayLiteral extends Literal, TArrayLiteral {
|
||||
final override string getAPrimaryQlClass() { result = "ArrayLiteral" }
|
||||
|
||||
/** Gets the `n`th element in this array literal. */
|
||||
final Expr getElement(int n) { result = range.getElement(n) }
|
||||
Expr getElement(int n) { none() }
|
||||
|
||||
/** Gets an element in this array literal. */
|
||||
final Expr getAnElement() { result = range.getElement(_) }
|
||||
final Expr getAnElement() { result = this.getElement(_) }
|
||||
|
||||
/** Gets the number of elements in this array literal. */
|
||||
final int getNumberOfElements() { result = count(range.getElement(_)) }
|
||||
final int getNumberOfElements() { result = count(this.getAnElement()) }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getElement" and result = this.getElement(_)
|
||||
}
|
||||
}
|
||||
|
||||
private class RegularArrayLiteral extends ArrayLiteral, TRegularArrayLiteral {
|
||||
private Generated::Array g;
|
||||
|
||||
RegularArrayLiteral() { this = TRegularArrayLiteral(g) }
|
||||
|
||||
final override Expr getElement(int i) { toGenerated(result) = g.getChild(i) }
|
||||
|
||||
final override string toString() { result = "[...]" }
|
||||
}
|
||||
|
||||
private class StringArrayLiteral extends ArrayLiteral, TStringArrayLiteral {
|
||||
private Generated::StringArray g;
|
||||
|
||||
StringArrayLiteral() { this = TStringArrayLiteral(g) }
|
||||
|
||||
final override Expr getElement(int i) { toGenerated(result) = g.getChild(i) }
|
||||
|
||||
final override string toString() { result = "%w(...)" }
|
||||
}
|
||||
|
||||
private class SymbolArrayLiteral extends ArrayLiteral, TSymbolArrayLiteral {
|
||||
private Generated::SymbolArray g;
|
||||
|
||||
SymbolArrayLiteral() { this = TSymbolArrayLiteral(g) }
|
||||
|
||||
final override Expr getElement(int i) { toGenerated(result) = g.getChild(i) }
|
||||
|
||||
final override string toString() { result = "%i(...)" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,8 +668,10 @@ class ArrayLiteral extends Literal {
|
||||
* { foo: 123, bar: 456 }
|
||||
* ```
|
||||
*/
|
||||
class HashLiteral extends Literal, @hash {
|
||||
final override HashLiteral::Range range;
|
||||
class HashLiteral extends Literal, THashLiteral {
|
||||
private Generated::Hash g;
|
||||
|
||||
HashLiteral() { this = THashLiteral(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "HashLiteral" }
|
||||
|
||||
@@ -395,16 +685,22 @@ class HashLiteral extends Literal, @hash {
|
||||
* { foo: 123, **bar }
|
||||
* ```
|
||||
*/
|
||||
final Expr getElement(int n) { result = range.getElement(n) }
|
||||
final Expr getElement(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
/** Gets an element in this array literal. */
|
||||
final Expr getAnElement() { result = range.getElement(_) }
|
||||
final Expr getAnElement() { result = this.getElement(_) }
|
||||
|
||||
/** Gets a key-value `Pair` in this hash literal. */
|
||||
final Pair getAKeyValuePair() { result = this.getAnElement() }
|
||||
|
||||
/** Gets the number of elements in this hash literal. */
|
||||
final int getNumberOfElements() { result = count(range.getElement(_)) }
|
||||
final int getNumberOfElements() { result = count(this.getAnElement()) }
|
||||
|
||||
final override string toString() { result = "{...}" }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getElement" and result = this.getElement(_)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -415,28 +711,38 @@ class HashLiteral extends Literal, @hash {
|
||||
* (1024...2048)
|
||||
* ```
|
||||
*/
|
||||
class RangeLiteral extends Literal, @range {
|
||||
final override RangeLiteral::Range range;
|
||||
class RangeLiteral extends Literal, TRangeLiteral {
|
||||
private Generated::Range g;
|
||||
|
||||
RangeLiteral() { this = TRangeLiteral(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "RangeLiteral" }
|
||||
|
||||
/** Gets the begin expression of this range, if any. */
|
||||
final Expr getBegin() { result = range.getBegin() }
|
||||
final Expr getBegin() { toGenerated(result) = g.getBegin() }
|
||||
|
||||
/** Gets the end expression of this range, if any. */
|
||||
final Expr getEnd() { result = range.getEnd() }
|
||||
final Expr getEnd() { toGenerated(result) = g.getEnd() }
|
||||
|
||||
/**
|
||||
* Holds if the range is inclusive of the end value, i.e. uses the `..`
|
||||
* operator.
|
||||
*/
|
||||
final predicate isInclusive() { range.isInclusive() }
|
||||
final predicate isInclusive() { g instanceof @range_dotdot }
|
||||
|
||||
/**
|
||||
* Holds if the range is exclusive of the end value, i.e. uses the `...`
|
||||
* operator.
|
||||
*/
|
||||
final predicate isExclusive() { range.isExclusive() }
|
||||
final predicate isExclusive() { g instanceof @range_dotdotdot }
|
||||
|
||||
final override string toString() { result = "_ " + g.getOperator() + " _" }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getBegin" and result = this.getBegin()
|
||||
or
|
||||
pred = "getEnd" and result = this.getEnd()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -449,7 +755,21 @@ class RangeLiteral extends Literal, @range {
|
||||
* ```
|
||||
*/
|
||||
class MethodName extends Literal {
|
||||
final override MethodName::Range range;
|
||||
MethodName() { MethodName::range(toGenerated(this)) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "MethodName" }
|
||||
}
|
||||
|
||||
private class TokenMethodName extends MethodName, TTokenMethodName {
|
||||
private MethodName::Token g;
|
||||
|
||||
TokenMethodName() { this = TTokenMethodName(g) }
|
||||
|
||||
final override string getValueText() {
|
||||
result = g.(Generated::Token).getValue()
|
||||
or
|
||||
result = g.(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
}
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.controlflow.ControlFlowGraph
|
||||
private import internal.AST
|
||||
private import internal.Method
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A callable. */
|
||||
class Callable extends Expr, CfgScope {
|
||||
override Callable::Range range;
|
||||
|
||||
class Callable extends Expr, CfgScope, TCallable {
|
||||
/** Gets the number of parameters of this callable. */
|
||||
final int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
@@ -14,23 +12,38 @@ class Callable extends Expr, CfgScope {
|
||||
final Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the `n`th parameter of this callable. */
|
||||
final Parameter getParameter(int n) { result = range.getParameter(n) }
|
||||
Parameter getParameter(int n) { none() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
pred = "getParameter" and result = this.getParameter(_)
|
||||
}
|
||||
}
|
||||
|
||||
/** A method. */
|
||||
class MethodBase extends Callable, BodyStatement, Scope {
|
||||
override MethodBase::Range range;
|
||||
|
||||
class MethodBase extends Callable, BodyStmt, Scope, TMethodBase {
|
||||
/** Gets the name of this method. */
|
||||
final string getName() { result = range.getName() }
|
||||
string getName() { none() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Callable.super.getAChild(pred)
|
||||
or
|
||||
result = BodyStmt.super.getAChild(pred)
|
||||
}
|
||||
}
|
||||
|
||||
/** A normal method. */
|
||||
class Method extends MethodBase, @method {
|
||||
final override Method::Range range;
|
||||
class Method extends MethodBase, TMethod {
|
||||
private Generated::Method g;
|
||||
|
||||
Method() { this = TMethod(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Method" }
|
||||
|
||||
final override string getName() {
|
||||
result = g.getName().(Generated::Token).getValue() or
|
||||
result = g.getName().(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a setter method, as in the following example:
|
||||
* ```rb
|
||||
@@ -41,17 +54,43 @@ class Method extends MethodBase, @method {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final predicate isSetter() { range.isSetter() }
|
||||
final predicate isSetter() { g.getName() instanceof Generated::Setter }
|
||||
|
||||
final override Parameter getParameter(int n) {
|
||||
toGenerated(result) = g.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/** A singleton method. */
|
||||
class SingletonMethod extends MethodBase, @singleton_method {
|
||||
final override SingletonMethod::Range range;
|
||||
class SingletonMethod extends MethodBase, TSingletonMethod {
|
||||
private Generated::SingletonMethod g;
|
||||
|
||||
SingletonMethod() { this = TSingletonMethod(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SingletonMethod" }
|
||||
|
||||
/** Gets the object of this singleton method. */
|
||||
final Expr getObject() { result = range.getObject() }
|
||||
final Expr getObject() { toGenerated(result) = g.getObject() }
|
||||
|
||||
final override string getName() {
|
||||
result = g.getName().(Generated::Token).getValue()
|
||||
or
|
||||
result = g.getName().(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
|
||||
final override Parameter getParameter(int n) {
|
||||
toGenerated(result) = g.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = MethodBase.super.getAChild(pred)
|
||||
or
|
||||
pred = "getObject" and result = this.getObject()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,20 +99,52 @@ class SingletonMethod extends MethodBase, @singleton_method {
|
||||
* -> (x) { x + 1 }
|
||||
* ```
|
||||
*/
|
||||
class Lambda extends Callable, BodyStatement, @lambda {
|
||||
final override Lambda::Range range;
|
||||
class Lambda extends Callable, BodyStmt, TLambda {
|
||||
private Generated::Lambda g;
|
||||
|
||||
Lambda() { this = TLambda(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Lambda" }
|
||||
|
||||
final override Parameter getParameter(int n) {
|
||||
toGenerated(result) = g.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override string toString() { result = "-> { ... }" }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = Callable.super.getAChild(pred)
|
||||
or
|
||||
result = BodyStmt.super.getAChild(pred)
|
||||
}
|
||||
}
|
||||
|
||||
/** A block. */
|
||||
class Block extends Callable, StmtSequence, Scope {
|
||||
override Block::Range range;
|
||||
class Block extends Callable, StmtSequence, Scope, TBlock {
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Callable.super.getAChild(pred)
|
||||
or
|
||||
result = StmtSequence.super.getAChild(pred)
|
||||
}
|
||||
}
|
||||
|
||||
/** A block enclosed within `do` and `end`. */
|
||||
class DoBlock extends Block, BodyStatement, @do_block {
|
||||
final override DoBlock::Range range;
|
||||
class DoBlock extends Block, BodyStmt, TDoBlock {
|
||||
private Generated::DoBlock g;
|
||||
|
||||
DoBlock() { this = TDoBlock(g) }
|
||||
|
||||
final override Parameter getParameter(int n) {
|
||||
toGenerated(result) = g.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override string toString() { result = "do ... end" }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = Block.super.getAChild(pred)
|
||||
or
|
||||
result = BodyStmt.super.getAChild(pred)
|
||||
}
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "DoBlock" }
|
||||
}
|
||||
@@ -84,8 +155,18 @@ class DoBlock extends Block, BodyStatement, @do_block {
|
||||
* names.each { |name| puts name }
|
||||
* ```
|
||||
*/
|
||||
class BraceBlock extends Block, @block {
|
||||
final override BraceBlock::Range range;
|
||||
class BraceBlock extends Block, TBraceBlock {
|
||||
private Generated::Block g;
|
||||
|
||||
BraceBlock() { this = TBraceBlock(g) }
|
||||
|
||||
final override Parameter getParameter(int n) {
|
||||
toGenerated(result) = g.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override Stmt getStmt(int i) { toGenerated(result) = g.getChild(i) }
|
||||
|
||||
final override string toString() { result = "{ ... }" }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "BraceBlock" }
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.Constant
|
||||
private import internal.Module
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/**
|
||||
* The base class for classes, singleton classes, and modules.
|
||||
*/
|
||||
class ModuleBase extends BodyStatement, Scope {
|
||||
override ModuleBase::Range range;
|
||||
|
||||
class ModuleBase extends BodyStmt, TModuleBase {
|
||||
/** Gets a method defined in this module/class. */
|
||||
MethodBase getAMethod() { result = this.getAStmt() }
|
||||
|
||||
@@ -37,20 +36,32 @@ class ModuleBase extends BodyStatement, Scope {
|
||||
* main
|
||||
* ```
|
||||
*/
|
||||
class Toplevel extends ModuleBase, @program {
|
||||
final override Toplevel::Range range;
|
||||
class Toplevel extends ModuleBase, TToplevel {
|
||||
private Generated::Program g;
|
||||
|
||||
Toplevel() { this = TToplevel(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Toplevel" }
|
||||
|
||||
/**
|
||||
* Gets the `n`th `BEGIN` block.
|
||||
*/
|
||||
final BeginBlock getBeginBlock(int n) { result = range.getBeginBlock(n) }
|
||||
final BeginBlock getBeginBlock(int n) {
|
||||
toGenerated(result) = rank[n](int i, Generated::BeginBlock b | b = g.getChild(i) | b order by i)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `BEGIN` block.
|
||||
*/
|
||||
final BeginBlock getABeginBlock() { result = getBeginBlock(_) }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = ModuleBase.super.getAChild(pred)
|
||||
or
|
||||
pred = "getBeginBlock" and result = this.getBeginBlock(_)
|
||||
}
|
||||
|
||||
final override string toString() { result = g.getLocation().getFile().getBaseName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,9 +78,7 @@ class Toplevel extends ModuleBase, @program {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class Namespace extends ModuleBase, ConstantWriteAccess {
|
||||
override Namespace::Range range;
|
||||
|
||||
class Namespace extends ModuleBase, ConstantWriteAccess, TNamespace {
|
||||
override string getAPrimaryQlClass() { result = "Namespace" }
|
||||
|
||||
/**
|
||||
@@ -88,7 +97,7 @@ class Namespace extends ModuleBase, ConstantWriteAccess {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
override string getName() { result = range.getName() }
|
||||
override string getName() { none() }
|
||||
|
||||
/**
|
||||
* Gets the scope expression used in the module/class name's scope resolution
|
||||
@@ -109,7 +118,7 @@ class Namespace extends ModuleBase, ConstantWriteAccess {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
override Expr getScopeExpr() { result = range.getScopeExpr() }
|
||||
override Expr getScopeExpr() { none() }
|
||||
|
||||
/**
|
||||
* Holds if the module/class name uses the scope resolution operator to access the
|
||||
@@ -120,7 +129,14 @@ class Namespace extends ModuleBase, ConstantWriteAccess {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
override predicate hasGlobalScope() { range.hasGlobalScope() }
|
||||
override predicate hasGlobalScope() { none() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = ModuleBase.super.getAChild(pred) or
|
||||
result = ConstantWriteAccess.super.getAChild(pred)
|
||||
}
|
||||
|
||||
final override string toString() { result = ConstantWriteAccess.super.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,8 +149,10 @@ class Namespace extends ModuleBase, ConstantWriteAccess {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class Class extends Namespace, @class {
|
||||
final override Class::Range range;
|
||||
class Class extends Namespace, TClass {
|
||||
private Generated::Class g;
|
||||
|
||||
Class() { this = TClass(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Class" }
|
||||
|
||||
@@ -154,7 +172,29 @@ class Class extends Namespace, @class {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getSuperclassExpr() { result = range.getSuperclassExpr() }
|
||||
final Expr getSuperclassExpr() { toGenerated(result) = g.getSuperclass().getChild() }
|
||||
|
||||
final override string getName() {
|
||||
result = g.getName().(Generated::Token).getValue() or
|
||||
result = g.getName().(Generated::ScopeResolution).getName().(Generated::Token).getValue()
|
||||
}
|
||||
|
||||
final override Expr getScopeExpr() {
|
||||
toGenerated(result) = g.getName().(Generated::ScopeResolution).getScope()
|
||||
}
|
||||
|
||||
final override predicate hasGlobalScope() {
|
||||
exists(Generated::ScopeResolution sr |
|
||||
sr = g.getName() and
|
||||
not exists(sr.getScope())
|
||||
)
|
||||
}
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = Namespace.super.getAChild(pred)
|
||||
or
|
||||
pred = "getSuperclassExpr" and result = this.getSuperclassExpr()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,8 +208,10 @@ class Class extends Namespace, @class {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class SingletonClass extends ModuleBase, @singleton_class {
|
||||
final override SingletonClass::Range range;
|
||||
class SingletonClass extends ModuleBase, TSingletonClass {
|
||||
private Generated::SingletonClass g;
|
||||
|
||||
SingletonClass() { this = TSingletonClass(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Class" }
|
||||
|
||||
@@ -182,7 +224,15 @@ class SingletonClass extends ModuleBase, @singleton_class {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() { toGenerated(result) = g.getValue() }
|
||||
|
||||
final override string toString() { result = "class << ..." }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = ModuleBase.super.getAChild(pred)
|
||||
or
|
||||
pred = "getValue" and result = this.getValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,8 +260,26 @@ class SingletonClass extends ModuleBase, @singleton_class {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class Module extends Namespace, @module {
|
||||
final override Module::Range range;
|
||||
class Module extends Namespace, TModule {
|
||||
private Generated::Module g;
|
||||
|
||||
Module() { this = TModule(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "Module" }
|
||||
|
||||
final override string getName() {
|
||||
result = g.getName().(Generated::Token).getValue() or
|
||||
result = g.getName().(Generated::ScopeResolution).getName().(Generated::Token).getValue()
|
||||
}
|
||||
|
||||
final override Expr getScopeExpr() {
|
||||
toGenerated(result) = g.getName().(Generated::ScopeResolution).getScope()
|
||||
}
|
||||
|
||||
final override predicate hasGlobalScope() {
|
||||
exists(Generated::ScopeResolution sr |
|
||||
sr = g.getName() and
|
||||
not exists(sr.getScope())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,46 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Operation
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
|
||||
/**
|
||||
* An operation.
|
||||
*
|
||||
* This is the QL root class for all operations.
|
||||
*/
|
||||
class Operation extends Expr {
|
||||
override Operation::Range range;
|
||||
|
||||
class Operation extends Expr, TOperation {
|
||||
/** Gets the operator of this operation. */
|
||||
final string getOperator() { result = range.getOperator() }
|
||||
string getOperator() { none() }
|
||||
|
||||
/** Gets an operand of this operation. */
|
||||
final Expr getAnOperand() { result = range.getAnOperand() }
|
||||
Expr getAnOperand() { none() }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getAnOperand" and result = this.getAnOperand() }
|
||||
}
|
||||
|
||||
/** A unary operation. */
|
||||
class UnaryOperation extends Operation, @unary {
|
||||
override UnaryOperation::Range range;
|
||||
class UnaryOperation extends Operation, TUnaryOperation {
|
||||
private Generated::Unary g;
|
||||
|
||||
UnaryOperation() { g = toGenerated(this) }
|
||||
|
||||
/** Gets the operand of this unary operation. */
|
||||
final Expr getOperand() { result = range.getOperand() }
|
||||
final Expr getOperand() { toGenerated(result) = g.getOperand() }
|
||||
|
||||
final override string getOperator() { result = g.getOperator() }
|
||||
|
||||
final override Expr getAnOperand() { result = this.getOperand() }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = Operation.super.getAChild(pred)
|
||||
or
|
||||
pred = "getOperand" and result = this.getOperand()
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getOperator() + " ..." }
|
||||
}
|
||||
|
||||
/** A unary logical operation. */
|
||||
class UnaryLogicalOperation extends UnaryOperation {
|
||||
override UnaryLogicalOperation::Range range;
|
||||
}
|
||||
class UnaryLogicalOperation extends UnaryOperation, TUnaryLogicalOperation { }
|
||||
|
||||
/**
|
||||
* A logical NOT operation, using either `!` or `not`.
|
||||
@@ -36,16 +49,12 @@ class UnaryLogicalOperation extends UnaryOperation {
|
||||
* not params.empty?
|
||||
* ```
|
||||
*/
|
||||
class NotExpr extends UnaryLogicalOperation, NotExpr::DbUnion {
|
||||
final override NotExpr::Range range;
|
||||
|
||||
class NotExpr extends UnaryLogicalOperation, TNotExpr {
|
||||
final override string getAPrimaryQlClass() { result = "NotExpr" }
|
||||
}
|
||||
|
||||
/** A unary arithmetic operation. */
|
||||
class UnaryArithmeticOperation extends UnaryOperation {
|
||||
override UnaryArithmeticOperation::Range range;
|
||||
}
|
||||
class UnaryArithmeticOperation extends UnaryOperation, TUnaryArithmeticOperation { }
|
||||
|
||||
/**
|
||||
* A unary plus expression.
|
||||
@@ -53,9 +62,7 @@ class UnaryArithmeticOperation extends UnaryOperation {
|
||||
* + a
|
||||
* ```
|
||||
*/
|
||||
class UnaryPlusExpr extends UnaryArithmeticOperation, @unary_plus {
|
||||
final override UnaryPlusExpr::Range range;
|
||||
|
||||
class UnaryPlusExpr extends UnaryArithmeticOperation, TUnaryPlusExpr {
|
||||
final override string getAPrimaryQlClass() { result = "UnaryPlusExpr" }
|
||||
}
|
||||
|
||||
@@ -65,16 +72,12 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @unary_plus {
|
||||
* - a
|
||||
* ```
|
||||
*/
|
||||
class UnaryMinusExpr extends UnaryArithmeticOperation, @unary_minus {
|
||||
final override UnaryMinusExpr::Range range;
|
||||
|
||||
class UnaryMinusExpr extends UnaryArithmeticOperation, TUnaryMinusExpr {
|
||||
final override string getAPrimaryQlClass() { result = "UnaryMinusExpr" }
|
||||
}
|
||||
|
||||
/** A unary bitwise operation. */
|
||||
class UnaryBitwiseOperation extends UnaryOperation {
|
||||
override UnaryBitwiseOperation::Range range;
|
||||
}
|
||||
class UnaryBitwiseOperation extends UnaryOperation, TUnaryBitwiseOperation { }
|
||||
|
||||
/**
|
||||
* A complement (bitwise NOT) expression.
|
||||
@@ -82,9 +85,7 @@ class UnaryBitwiseOperation extends UnaryOperation {
|
||||
* ~x
|
||||
* ```
|
||||
*/
|
||||
class ComplementExpr extends UnaryBitwiseOperation, @unary_tilde {
|
||||
final override ComplementExpr::Range range;
|
||||
|
||||
class ComplementExpr extends UnaryBitwiseOperation, TComplementExpr {
|
||||
final override string getAPrimaryQlClass() { result = "ComplementExpr" }
|
||||
}
|
||||
|
||||
@@ -94,29 +95,43 @@ class ComplementExpr extends UnaryBitwiseOperation, @unary_tilde {
|
||||
* defined? some_method
|
||||
* ```
|
||||
*/
|
||||
class DefinedExpr extends UnaryOperation, @unary_definedquestion {
|
||||
final override DefinedExpr::Range range;
|
||||
|
||||
class DefinedExpr extends UnaryOperation, TDefinedExpr {
|
||||
final override string getAPrimaryQlClass() { result = "DefinedExpr" }
|
||||
}
|
||||
|
||||
/** A binary operation. */
|
||||
class BinaryOperation extends Operation, @binary {
|
||||
override BinaryOperation::Range range;
|
||||
class BinaryOperation extends Operation, TBinaryOperation {
|
||||
private Generated::Binary g;
|
||||
|
||||
BinaryOperation() { g = toGenerated(this) }
|
||||
|
||||
final override string getOperator() { result = g.getOperator() }
|
||||
|
||||
final override Expr getAnOperand() {
|
||||
result = this.getLeftOperand() or result = this.getRightOperand()
|
||||
}
|
||||
|
||||
final override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Operation.super.getAChild(pred)
|
||||
or
|
||||
pred = "getLeftOperand" and result = this.getLeftOperand()
|
||||
or
|
||||
pred = "getRightOperand" and result = this.getRightOperand()
|
||||
}
|
||||
|
||||
/** Gets the left operand of this binary operation. */
|
||||
final Stmt getLeftOperand() { result = range.getLeftOperand() }
|
||||
final Stmt getLeftOperand() { toGenerated(result) = g.getLeft() }
|
||||
|
||||
/** Gets the right operand of this binary operation. */
|
||||
final Stmt getRightOperand() { result = range.getRightOperand() }
|
||||
final Stmt getRightOperand() { toGenerated(result) = g.getRight() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary arithmetic operation.
|
||||
*/
|
||||
class BinaryArithmeticOperation extends BinaryOperation {
|
||||
override BinaryArithmeticOperation::Range range;
|
||||
}
|
||||
class BinaryArithmeticOperation extends BinaryOperation, TBinaryArithmeticOperation { }
|
||||
|
||||
/**
|
||||
* An add expression.
|
||||
@@ -124,9 +139,7 @@ class BinaryArithmeticOperation extends BinaryOperation {
|
||||
* x + 1
|
||||
* ```
|
||||
*/
|
||||
class AddExpr extends BinaryArithmeticOperation, @binary_plus {
|
||||
final override AddExpr::Range range;
|
||||
|
||||
class AddExpr extends BinaryArithmeticOperation, TAddExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AddExpr" }
|
||||
}
|
||||
|
||||
@@ -136,9 +149,7 @@ class AddExpr extends BinaryArithmeticOperation, @binary_plus {
|
||||
* x - 3
|
||||
* ```
|
||||
*/
|
||||
class SubExpr extends BinaryArithmeticOperation, @binary_minus {
|
||||
final override SubExpr::Range range;
|
||||
|
||||
class SubExpr extends BinaryArithmeticOperation, TSubExpr {
|
||||
final override string getAPrimaryQlClass() { result = "SubExpr" }
|
||||
}
|
||||
|
||||
@@ -148,9 +159,7 @@ class SubExpr extends BinaryArithmeticOperation, @binary_minus {
|
||||
* x * 10
|
||||
* ```
|
||||
*/
|
||||
class MulExpr extends BinaryArithmeticOperation, @binary_star {
|
||||
final override MulExpr::Range range;
|
||||
|
||||
class MulExpr extends BinaryArithmeticOperation, TMulExpr {
|
||||
final override string getAPrimaryQlClass() { result = "MulExpr" }
|
||||
}
|
||||
|
||||
@@ -160,9 +169,7 @@ class MulExpr extends BinaryArithmeticOperation, @binary_star {
|
||||
* x / y
|
||||
* ```
|
||||
*/
|
||||
class DivExpr extends BinaryArithmeticOperation, @binary_slash {
|
||||
final override DivExpr::Range range;
|
||||
|
||||
class DivExpr extends BinaryArithmeticOperation, TDivExpr {
|
||||
final override string getAPrimaryQlClass() { result = "DivExpr" }
|
||||
}
|
||||
|
||||
@@ -172,9 +179,7 @@ class DivExpr extends BinaryArithmeticOperation, @binary_slash {
|
||||
* x % 2
|
||||
* ```
|
||||
*/
|
||||
class ModuloExpr extends BinaryArithmeticOperation, @binary_percent {
|
||||
final override ModuloExpr::Range range;
|
||||
|
||||
class ModuloExpr extends BinaryArithmeticOperation, TModuloExpr {
|
||||
final override string getAPrimaryQlClass() { result = "ModuloExpr" }
|
||||
}
|
||||
|
||||
@@ -184,18 +189,14 @@ class ModuloExpr extends BinaryArithmeticOperation, @binary_percent {
|
||||
* x ** 2
|
||||
* ```
|
||||
*/
|
||||
class ExponentExpr extends BinaryArithmeticOperation, @binary_starstar {
|
||||
final override ExponentExpr::Range range;
|
||||
|
||||
class ExponentExpr extends BinaryArithmeticOperation, TExponentExpr {
|
||||
final override string getAPrimaryQlClass() { result = "ExponentExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary logical operation.
|
||||
*/
|
||||
class BinaryLogicalOperation extends BinaryOperation {
|
||||
override BinaryLogicalOperation::Range range;
|
||||
}
|
||||
class BinaryLogicalOperation extends BinaryOperation, TBinaryLogicalOperation { }
|
||||
|
||||
/**
|
||||
* A logical AND operation, using either `and` or `&&`.
|
||||
@@ -204,9 +205,7 @@ class BinaryLogicalOperation extends BinaryOperation {
|
||||
* a && b
|
||||
* ```
|
||||
*/
|
||||
class LogicalAndExpr extends BinaryLogicalOperation, LogicalAndExpr::DbUnion {
|
||||
final override LogicalAndExpr::Range range;
|
||||
|
||||
class LogicalAndExpr extends BinaryLogicalOperation, TLogicalAndExpr {
|
||||
final override string getAPrimaryQlClass() { result = "LogicalAndExpr" }
|
||||
}
|
||||
|
||||
@@ -217,18 +216,14 @@ class LogicalAndExpr extends BinaryLogicalOperation, LogicalAndExpr::DbUnion {
|
||||
* a || b
|
||||
* ```
|
||||
*/
|
||||
class LogicalOrExpr extends BinaryLogicalOperation, LogicalOrExpr::DbUnion {
|
||||
final override LogicalOrExpr::Range range;
|
||||
|
||||
class LogicalOrExpr extends BinaryLogicalOperation, TLogicalOrExpr {
|
||||
final override string getAPrimaryQlClass() { result = "LogicalOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A binary bitwise operation.
|
||||
*/
|
||||
class BinaryBitwiseOperation extends BinaryOperation {
|
||||
override BinaryBitwiseOperation::Range range;
|
||||
}
|
||||
class BinaryBitwiseOperation extends BinaryOperation, TBinaryBitwiseOperation { }
|
||||
|
||||
/**
|
||||
* A left-shift operation.
|
||||
@@ -236,9 +231,7 @@ class BinaryBitwiseOperation extends BinaryOperation {
|
||||
* x << n
|
||||
* ```
|
||||
*/
|
||||
class LShiftExpr extends BinaryBitwiseOperation, @binary_langlelangle {
|
||||
final override LShiftExpr::Range range;
|
||||
|
||||
class LShiftExpr extends BinaryBitwiseOperation, TLShiftExpr {
|
||||
final override string getAPrimaryQlClass() { result = "LShiftExpr" }
|
||||
}
|
||||
|
||||
@@ -248,9 +241,7 @@ class LShiftExpr extends BinaryBitwiseOperation, @binary_langlelangle {
|
||||
* x >> n
|
||||
* ```
|
||||
*/
|
||||
class RShiftExpr extends BinaryBitwiseOperation, @binary_ranglerangle {
|
||||
final override RShiftExpr::Range range;
|
||||
|
||||
class RShiftExpr extends BinaryBitwiseOperation, TRShiftExpr {
|
||||
final override string getAPrimaryQlClass() { result = "RShiftExpr" }
|
||||
}
|
||||
|
||||
@@ -260,9 +251,7 @@ class RShiftExpr extends BinaryBitwiseOperation, @binary_ranglerangle {
|
||||
* x & 0xff
|
||||
* ```
|
||||
*/
|
||||
class BitwiseAndExpr extends BinaryBitwiseOperation, @binary_ampersand {
|
||||
final override BitwiseAndExpr::Range range;
|
||||
|
||||
class BitwiseAndExpr extends BinaryBitwiseOperation, TBitwiseAndExpr {
|
||||
final override string getAPrimaryQlClass() { result = "BitwiseAndExpr" }
|
||||
}
|
||||
|
||||
@@ -272,9 +261,7 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, @binary_ampersand {
|
||||
* x | 0x01
|
||||
* ```
|
||||
*/
|
||||
class BitwiseOrExpr extends BinaryBitwiseOperation, @binary_pipe {
|
||||
final override BitwiseOrExpr::Range range;
|
||||
|
||||
class BitwiseOrExpr extends BinaryBitwiseOperation, TBitwiseOrExpr {
|
||||
final override string getAPrimaryQlClass() { result = "BitwiseOrExpr" }
|
||||
}
|
||||
|
||||
@@ -284,9 +271,7 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, @binary_pipe {
|
||||
* x ^ y
|
||||
* ```
|
||||
*/
|
||||
class BitwiseXorExpr extends BinaryBitwiseOperation, @binary_caret {
|
||||
final override BitwiseXorExpr::Range range;
|
||||
|
||||
class BitwiseXorExpr extends BinaryBitwiseOperation, TBitwiseXorExpr {
|
||||
final override string getAPrimaryQlClass() { result = "BitwiseXorExpr" }
|
||||
}
|
||||
|
||||
@@ -294,16 +279,12 @@ class BitwiseXorExpr extends BinaryBitwiseOperation, @binary_caret {
|
||||
* A comparison operation. That is, either an equality operation or a
|
||||
* relational operation.
|
||||
*/
|
||||
class ComparisonOperation extends BinaryOperation {
|
||||
override ComparisonOperation::Range range;
|
||||
}
|
||||
class ComparisonOperation extends BinaryOperation, TComparisonOperation { }
|
||||
|
||||
/**
|
||||
* An equality operation.
|
||||
*/
|
||||
class EqualityOperation extends ComparisonOperation {
|
||||
override EqualityOperation::Range range;
|
||||
}
|
||||
class EqualityOperation extends ComparisonOperation, TEqualityOperation { }
|
||||
|
||||
/**
|
||||
* An equals expression.
|
||||
@@ -311,9 +292,7 @@ class EqualityOperation extends ComparisonOperation {
|
||||
* x == y
|
||||
* ```
|
||||
*/
|
||||
class EqExpr extends EqualityOperation, @binary_equalequal {
|
||||
final override EqExpr::Range range;
|
||||
|
||||
class EqExpr extends EqualityOperation, TEqExpr {
|
||||
final override string getAPrimaryQlClass() { result = "EqExpr" }
|
||||
}
|
||||
|
||||
@@ -323,9 +302,7 @@ class EqExpr extends EqualityOperation, @binary_equalequal {
|
||||
* x != y
|
||||
* ```
|
||||
*/
|
||||
class NEExpr extends EqualityOperation, @binary_bangequal {
|
||||
final override NEExpr::Range range;
|
||||
|
||||
class NEExpr extends EqualityOperation, TNEExpr {
|
||||
final override string getAPrimaryQlClass() { result = "NEExpr" }
|
||||
}
|
||||
|
||||
@@ -335,21 +312,27 @@ class NEExpr extends EqualityOperation, @binary_bangequal {
|
||||
* String === "foo"
|
||||
* ```
|
||||
*/
|
||||
class CaseEqExpr extends EqualityOperation, @binary_equalequalequal {
|
||||
final override CaseEqExpr::Range range;
|
||||
|
||||
class CaseEqExpr extends EqualityOperation, TCaseEqExpr {
|
||||
final override string getAPrimaryQlClass() { result = "CaseEqExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A relational operation, that is, one of `<=`, `<`, `>`, or `>=`.
|
||||
*/
|
||||
class RelationalOperation extends ComparisonOperation {
|
||||
override RelationalOperation::Range range;
|
||||
class RelationalOperation extends ComparisonOperation, TRelationalOperation {
|
||||
/** Gets the greater operand. */
|
||||
Expr getGreaterOperand() { none() }
|
||||
|
||||
final Expr getGreaterOperand() { result = range.getGreaterOperand() }
|
||||
/** Gets the lesser operand. */
|
||||
Expr getLesserOperand() { none() }
|
||||
|
||||
final Expr getLesserOperand() { result = range.getLesserOperand() }
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = ComparisonOperation.super.getAChild(pred)
|
||||
or
|
||||
pred = "getGreaterOperand" and result = this.getGreaterOperand()
|
||||
or
|
||||
pred = "getLesserOperand" and result = this.getLesserOperand()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,10 +341,12 @@ class RelationalOperation extends ComparisonOperation {
|
||||
* x > 0
|
||||
* ```
|
||||
*/
|
||||
class GTExpr extends RelationalOperation, @binary_rangle {
|
||||
final override GTExpr::Range range;
|
||||
|
||||
class GTExpr extends RelationalOperation, TGTExpr {
|
||||
final override string getAPrimaryQlClass() { result = "GTExpr" }
|
||||
|
||||
final override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,10 +355,12 @@ class GTExpr extends RelationalOperation, @binary_rangle {
|
||||
* x >= 0
|
||||
* ```
|
||||
*/
|
||||
class GEExpr extends RelationalOperation, @binary_rangleequal {
|
||||
final override GEExpr::Range range;
|
||||
|
||||
class GEExpr extends RelationalOperation, TGEExpr {
|
||||
final override string getAPrimaryQlClass() { result = "GEExpr" }
|
||||
|
||||
final override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,10 +369,12 @@ class GEExpr extends RelationalOperation, @binary_rangleequal {
|
||||
* x < 10
|
||||
* ```
|
||||
*/
|
||||
class LTExpr extends RelationalOperation, @binary_langle {
|
||||
final override LTExpr::Range range;
|
||||
|
||||
class LTExpr extends RelationalOperation, TLTExpr {
|
||||
final override string getAPrimaryQlClass() { result = "LTExpr" }
|
||||
|
||||
final override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,10 +383,12 @@ class LTExpr extends RelationalOperation, @binary_langle {
|
||||
* x <= 10
|
||||
* ```
|
||||
*/
|
||||
class LEExpr extends RelationalOperation, @binary_langleequal {
|
||||
final override LEExpr::Range range;
|
||||
|
||||
class LEExpr extends RelationalOperation, TLEExpr {
|
||||
final override string getAPrimaryQlClass() { result = "LEExpr" }
|
||||
|
||||
final override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,9 +397,7 @@ class LEExpr extends RelationalOperation, @binary_langleequal {
|
||||
* a <=> b
|
||||
* ```
|
||||
*/
|
||||
class SpaceshipExpr extends BinaryOperation, @binary_langleequalrangle {
|
||||
final override SpaceshipExpr::Range range;
|
||||
|
||||
class SpaceshipExpr extends BinaryOperation, TSpaceshipExpr {
|
||||
final override string getAPrimaryQlClass() { result = "SpaceshipExpr" }
|
||||
}
|
||||
|
||||
@@ -418,9 +407,7 @@ class SpaceshipExpr extends BinaryOperation, @binary_langleequalrangle {
|
||||
* input =~ /\d/
|
||||
* ```
|
||||
*/
|
||||
class RegexMatchExpr extends BinaryOperation, @binary_equaltilde {
|
||||
final override RegexMatchExpr::Range range;
|
||||
|
||||
class RegexMatchExpr extends BinaryOperation, TRegexMatchExpr {
|
||||
final override string getAPrimaryQlClass() { result = "RegexMatchExpr" }
|
||||
}
|
||||
|
||||
@@ -430,9 +417,7 @@ class RegexMatchExpr extends BinaryOperation, @binary_equaltilde {
|
||||
* input !~ /\d/
|
||||
* ```
|
||||
*/
|
||||
class NoRegexMatchExpr extends BinaryOperation, @binary_bangtilde {
|
||||
final override NoRegexMatchExpr::Range range;
|
||||
|
||||
class NoRegexMatchExpr extends BinaryOperation, TNoRegexMatchExpr {
|
||||
final override string getAPrimaryQlClass() { result = "NoRegexMatchExpr" }
|
||||
}
|
||||
|
||||
@@ -441,14 +426,26 @@ class NoRegexMatchExpr extends BinaryOperation, @binary_bangtilde {
|
||||
*
|
||||
* This is a QL base class for all assignments.
|
||||
*/
|
||||
class Assignment extends Operation {
|
||||
override Assignment::Range range;
|
||||
|
||||
class Assignment extends Operation, TAssignment {
|
||||
/** Gets the left hand side of this assignment. */
|
||||
Pattern getLeftOperand() { result = range.getLeftOperand() }
|
||||
Pattern getLeftOperand() { none() }
|
||||
|
||||
/** Gets the right hand side of this assignment. */
|
||||
final Expr getRightOperand() { result = range.getRightOperand() }
|
||||
Expr getRightOperand() { none() }
|
||||
|
||||
final override Expr getAnOperand() {
|
||||
result = this.getLeftOperand() or result = this.getRightOperand()
|
||||
}
|
||||
|
||||
final override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Operation.super.getAChild(pred)
|
||||
or
|
||||
pred = "getLeftOperand" and result = getLeftOperand()
|
||||
or
|
||||
pred = "getRightOperand" and result = getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,8 +454,16 @@ class Assignment extends Operation {
|
||||
* x = 123
|
||||
* ```
|
||||
*/
|
||||
class AssignExpr extends Assignment {
|
||||
override AssignExpr::Range range;
|
||||
class AssignExpr extends Assignment, TAssignExpr {
|
||||
private Generated::Assignment g;
|
||||
|
||||
AssignExpr() { this = TAssignExpr(g) }
|
||||
|
||||
final override Pattern getLeftOperand() { toGenerated(result) = g.getLeft() }
|
||||
|
||||
final override Expr getRightOperand() { toGenerated(result) = g.getRight() }
|
||||
|
||||
final override string getOperator() { result = "=" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AssignExpr" }
|
||||
}
|
||||
@@ -466,16 +471,22 @@ class AssignExpr extends Assignment {
|
||||
/**
|
||||
* A binary assignment operation other than `=`.
|
||||
*/
|
||||
class AssignOperation extends Assignment {
|
||||
override AssignOperation::Range range;
|
||||
class AssignOperation extends Assignment, TAssignOperation {
|
||||
private Generated::OperatorAssignment g;
|
||||
|
||||
AssignOperation() { g = toGenerated(this) }
|
||||
|
||||
final override string getOperator() { result = g.getOperator() }
|
||||
|
||||
final override LhsExpr getLeftOperand() { toGenerated(result) = g.getLeft() }
|
||||
|
||||
final override Expr getRightOperand() { toGenerated(result) = g.getRight() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An arithmetic assignment operation: `+=`, `-=`, `*=`, `/=`, `**=`, and `%=`.
|
||||
*/
|
||||
class AssignArithmeticOperation extends AssignOperation {
|
||||
override AssignArithmeticOperation::Range range;
|
||||
}
|
||||
class AssignArithmeticOperation extends AssignOperation, TAssignArithmeticOperation { }
|
||||
|
||||
/**
|
||||
* A `+=` assignment expression.
|
||||
@@ -483,9 +494,7 @@ class AssignArithmeticOperation extends AssignOperation {
|
||||
* x += 1
|
||||
* ```
|
||||
*/
|
||||
class AssignAddExpr extends AssignArithmeticOperation, @operator_assignment_plusequal {
|
||||
final override AssignAddExpr::Range range;
|
||||
|
||||
class AssignAddExpr extends AssignArithmeticOperation, TAssignAddExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignAddExpr" }
|
||||
}
|
||||
|
||||
@@ -495,9 +504,7 @@ class AssignAddExpr extends AssignArithmeticOperation, @operator_assignment_plus
|
||||
* x -= 3
|
||||
* ```
|
||||
*/
|
||||
class AssignSubExpr extends AssignArithmeticOperation, @operator_assignment_minusequal {
|
||||
final override AssignSubExpr::Range range;
|
||||
|
||||
class AssignSubExpr extends AssignArithmeticOperation, TAssignSubExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignSubExpr" }
|
||||
}
|
||||
|
||||
@@ -507,9 +514,7 @@ class AssignSubExpr extends AssignArithmeticOperation, @operator_assignment_minu
|
||||
* x *= 10
|
||||
* ```
|
||||
*/
|
||||
class AssignMulExpr extends AssignArithmeticOperation, @operator_assignment_starequal {
|
||||
final override AssignMulExpr::Range range;
|
||||
|
||||
class AssignMulExpr extends AssignArithmeticOperation, TAssignMulExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignMulExpr" }
|
||||
}
|
||||
|
||||
@@ -519,9 +524,7 @@ class AssignMulExpr extends AssignArithmeticOperation, @operator_assignment_star
|
||||
* x /= y
|
||||
* ```
|
||||
*/
|
||||
class AssignDivExpr extends AssignArithmeticOperation, @operator_assignment_slashequal {
|
||||
final override AssignDivExpr::Range range;
|
||||
|
||||
class AssignDivExpr extends AssignArithmeticOperation, TAssignDivExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignDivExpr" }
|
||||
}
|
||||
|
||||
@@ -531,9 +534,7 @@ class AssignDivExpr extends AssignArithmeticOperation, @operator_assignment_slas
|
||||
* x %= 4
|
||||
* ```
|
||||
*/
|
||||
class AssignModuloExpr extends AssignArithmeticOperation, @operator_assignment_percentequal {
|
||||
final override AssignModuloExpr::Range range;
|
||||
|
||||
class AssignModuloExpr extends AssignArithmeticOperation, TAssignModuloExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignModuloExpr" }
|
||||
}
|
||||
|
||||
@@ -543,20 +544,14 @@ class AssignModuloExpr extends AssignArithmeticOperation, @operator_assignment_p
|
||||
* x **= 2
|
||||
* ```
|
||||
*/
|
||||
class AssignExponentExpr extends AssignArithmeticOperation, @operator_assignment_starstarequal {
|
||||
final override AssignExponentExpr::Range range;
|
||||
|
||||
class AssignExponentExpr extends AssignArithmeticOperation, TAssignExponentExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignExponentExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A logical assignment operation: `&&=` and `||=`.
|
||||
*/
|
||||
class AssignLogicalOperation extends AssignOperation {
|
||||
override AssignLogicalOperation::Range range;
|
||||
|
||||
final override LhsExpr getLeftOperand() { result = super.getLeftOperand() }
|
||||
}
|
||||
class AssignLogicalOperation extends AssignOperation, TAssignLogicalOperation { }
|
||||
|
||||
/**
|
||||
* A logical AND assignment operation.
|
||||
@@ -564,10 +559,7 @@ class AssignLogicalOperation extends AssignOperation {
|
||||
* x &&= y.even?
|
||||
* ```
|
||||
*/
|
||||
class AssignLogicalAndExpr extends AssignLogicalOperation,
|
||||
@operator_assignment_ampersandampersandequal {
|
||||
final override AssignLogicalAndExpr::Range range;
|
||||
|
||||
class AssignLogicalAndExpr extends AssignLogicalOperation, TAssignLogicalAndExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignLogicalAndExpr" }
|
||||
}
|
||||
|
||||
@@ -577,18 +569,14 @@ class AssignLogicalAndExpr extends AssignLogicalOperation,
|
||||
* x ||= y
|
||||
* ```
|
||||
*/
|
||||
class AssignLogicalOrExpr extends AssignLogicalOperation, @operator_assignment_pipepipeequal {
|
||||
final override AssignLogicalOrExpr::Range range;
|
||||
|
||||
class AssignLogicalOrExpr extends AssignLogicalOperation, TAssignLogicalOrExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignLogicalOrExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bitwise assignment operation: `<<=`, `>>=`, `&=`, `|=` and `^=`.
|
||||
*/
|
||||
class AssignBitwiseOperation extends AssignOperation {
|
||||
override AssignBitwiseOperation::Range range;
|
||||
}
|
||||
class AssignBitwiseOperation extends AssignOperation, TAssignBitwiseOperation { }
|
||||
|
||||
/**
|
||||
* A left-shift assignment operation.
|
||||
@@ -596,9 +584,7 @@ class AssignBitwiseOperation extends AssignOperation {
|
||||
* x <<= 3
|
||||
* ```
|
||||
*/
|
||||
class AssignLShiftExpr extends AssignBitwiseOperation, @operator_assignment_langlelangleequal {
|
||||
final override AssignLShiftExpr::Range range;
|
||||
|
||||
class AssignLShiftExpr extends AssignBitwiseOperation, TAssignLShiftExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignLShiftExpr" }
|
||||
}
|
||||
|
||||
@@ -608,9 +594,7 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @operator_assignment_lang
|
||||
* x >>= 3
|
||||
* ```
|
||||
*/
|
||||
class AssignRShiftExpr extends AssignBitwiseOperation, @operator_assignment_ranglerangleequal {
|
||||
final override AssignRShiftExpr::Range range;
|
||||
|
||||
class AssignRShiftExpr extends AssignBitwiseOperation, TAssignRShiftExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignRShiftExpr" }
|
||||
}
|
||||
|
||||
@@ -620,9 +604,7 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @operator_assignment_rang
|
||||
* x &= 0xff
|
||||
* ```
|
||||
*/
|
||||
class AssignBitwiseAndExpr extends AssignBitwiseOperation, @operator_assignment_ampersandequal {
|
||||
final override AssignBitwiseAndExpr::Range range;
|
||||
|
||||
class AssignBitwiseAndExpr extends AssignBitwiseOperation, TAssignBitwiseAndExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignBitwiseAndExpr" }
|
||||
}
|
||||
|
||||
@@ -632,9 +614,7 @@ class AssignBitwiseAndExpr extends AssignBitwiseOperation, @operator_assignment_
|
||||
* x |= 0x01
|
||||
* ```
|
||||
*/
|
||||
class AssignBitwiseOrExpr extends AssignBitwiseOperation, @operator_assignment_pipeequal {
|
||||
final override AssignBitwiseOrExpr::Range range;
|
||||
|
||||
class AssignBitwiseOrExpr extends AssignBitwiseOperation, TAssignBitwiseOrExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignBitwiseOrExpr" }
|
||||
}
|
||||
|
||||
@@ -644,8 +624,6 @@ class AssignBitwiseOrExpr extends AssignBitwiseOperation, @operator_assignment_p
|
||||
* x ^= y
|
||||
* ```
|
||||
*/
|
||||
class AssignBitwiseXorExpr extends AssignBitwiseOperation, @operator_assignment_caretequal {
|
||||
final override AssignBitwiseXorExpr::Range range;
|
||||
|
||||
class AssignBitwiseXorExpr extends AssignBitwiseOperation, TAssignBitwiseXorExpr {
|
||||
final override string getAPrimaryQlClass() { result = "AssignBitwiseXorExpr" }
|
||||
}
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.Pattern
|
||||
private import internal.AST
|
||||
private import internal.Variable
|
||||
private import internal.Parameter
|
||||
private import internal.TreeSitter
|
||||
|
||||
/** A parameter. */
|
||||
class Parameter extends AstNode {
|
||||
override Parameter::Range range;
|
||||
|
||||
class Parameter extends AstNode, TParameter {
|
||||
/** Gets the callable that this parameter belongs to. */
|
||||
final Callable getCallable() { result.getAParameter() = this }
|
||||
|
||||
/** Gets the zero-based position of this parameter. */
|
||||
final int getPosition() { result = range.getPosition() }
|
||||
final int getPosition() { this = any(Callable c).getParameter(result) }
|
||||
|
||||
/** Gets a variable introduced by this parameter. */
|
||||
LocalVariable getAVariable() { result = range.getAVariable() }
|
||||
LocalVariable getAVariable() { none() }
|
||||
|
||||
/** Gets the variable named `name` introduced by this parameter. */
|
||||
final LocalVariable getVariable(string name) {
|
||||
@@ -28,44 +27,61 @@ class Parameter extends AstNode {
|
||||
*
|
||||
* This includes both simple parameters and tuple parameters.
|
||||
*/
|
||||
class PatternParameter extends Parameter, Pattern {
|
||||
override PatternParameter::Range range;
|
||||
|
||||
class PatternParameter extends Parameter, Pattern, TPatternParameter {
|
||||
override LocalVariable getAVariable() { result = Pattern.super.getAVariable() }
|
||||
}
|
||||
|
||||
/** A parameter defined using a tuple pattern. */
|
||||
class TuplePatternParameter extends PatternParameter, TuplePattern {
|
||||
override TuplePatternParameter::Range range;
|
||||
class TuplePatternParameter extends PatternParameter, TuplePattern, TTuplePatternParameter {
|
||||
final override LocalVariable getAVariable() { result = TuplePattern.super.getAVariable() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "TuplePatternParameter" }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = PatternParameter.super.getAChild(pred) or
|
||||
result = TuplePattern.super.getAChild(pred)
|
||||
}
|
||||
}
|
||||
|
||||
/** A named parameter. */
|
||||
class NamedParameter extends Parameter {
|
||||
override NamedParameter::Range range;
|
||||
|
||||
class NamedParameter extends Parameter, TNamedParameter {
|
||||
/** Gets the name of this parameter. */
|
||||
final string getName() { result = range.getName() }
|
||||
string getName() { none() }
|
||||
|
||||
/** Gets the variable introduced by this parameter. */
|
||||
LocalVariable getVariable() { result = range.getVariable() }
|
||||
LocalVariable getVariable() { none() }
|
||||
|
||||
override LocalVariable getAVariable() { result = this.getVariable() }
|
||||
|
||||
/** Gets an access to this parameter. */
|
||||
final VariableAccess getAnAccess() { result = this.getVariable().getAnAccess() }
|
||||
|
||||
/** Gets the access that defines the underlying local variable. */
|
||||
final VariableAccess getDefiningAccess() { result = this.getVariable().getDefiningAccess() }
|
||||
|
||||
override AstNode getAChild(string pred) {
|
||||
result = Parameter.super.getAChild(pred)
|
||||
or
|
||||
pred = "getDefiningAccess" and
|
||||
result = this.getDefiningAccess()
|
||||
}
|
||||
}
|
||||
|
||||
/** A simple (normal) parameter. */
|
||||
class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern {
|
||||
override SimpleParameter::Range range;
|
||||
class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern, TSimpleParameter {
|
||||
private Generated::Identifier g;
|
||||
|
||||
final override LocalVariable getVariable() { result = range.getVariable() }
|
||||
SimpleParameter() { this = TSimpleParameter(g) }
|
||||
|
||||
final override LocalVariable getAVariable() { result = range.getAVariable() }
|
||||
final override string getName() { result = g.getValue() }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, g) }
|
||||
|
||||
final override LocalVariable getAVariable() { result = this.getVariable() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SimpleParameter" }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,10 +92,16 @@ class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class BlockParameter extends @block_parameter, NamedParameter {
|
||||
final override BlockParameter::Range range;
|
||||
class BlockParameter extends NamedParameter, TBlockParameter {
|
||||
private Generated::BlockParameter g;
|
||||
|
||||
final override LocalVariable getVariable() { result = range.getVariable() }
|
||||
BlockParameter() { this = TBlockParameter(g) }
|
||||
|
||||
final override string getName() { result = g.getName().getValue() }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) }
|
||||
|
||||
final override string toString() { result = "&" + this.getName() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "BlockParameter" }
|
||||
}
|
||||
@@ -93,10 +115,18 @@ class BlockParameter extends @block_parameter, NamedParameter {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class HashSplatParameter extends @hash_splat_parameter, NamedParameter {
|
||||
final override HashSplatParameter::Range range;
|
||||
class HashSplatParameter extends NamedParameter, THashSplatParameter {
|
||||
private Generated::HashSplatParameter g;
|
||||
|
||||
HashSplatParameter() { this = THashSplatParameter(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "HashSplatParameter" }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) }
|
||||
|
||||
final override string toString() { result = "**" + this.getName() }
|
||||
|
||||
final override string getName() { result = g.getName().getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,23 +140,39 @@ class HashSplatParameter extends @hash_splat_parameter, NamedParameter {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class KeywordParameter extends @keyword_parameter, NamedParameter {
|
||||
final override KeywordParameter::Range range;
|
||||
class KeywordParameter extends NamedParameter, TKeywordParameter {
|
||||
private Generated::KeywordParameter g;
|
||||
|
||||
KeywordParameter() { this = TKeywordParameter(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "KeywordParameter" }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) }
|
||||
|
||||
/**
|
||||
* Gets the default value, i.e. the value assigned to the parameter when one
|
||||
* is not provided by the caller. If the parameter is mandatory and does not
|
||||
* have a default value, this predicate has no result.
|
||||
*/
|
||||
final Expr getDefaultValue() { result = range.getDefaultValue() }
|
||||
final Expr getDefaultValue() { toGenerated(result) = g.getValue() }
|
||||
|
||||
/**
|
||||
* Holds if the parameter is optional. That is, there is a default value that
|
||||
* is used when the caller omits this parameter.
|
||||
*/
|
||||
final predicate isOptional() { exists(this.getDefaultValue()) }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
final override string getName() { result = g.getName().getValue() }
|
||||
|
||||
final override Location getLocation() { result = g.getName().getLocation() }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = NamedParameter.super.getAChild(pred)
|
||||
or
|
||||
pred = "getDefaultValue" and result = this.getDefaultValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -138,8 +184,10 @@ class KeywordParameter extends @keyword_parameter, NamedParameter {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class OptionalParameter extends @optional_parameter, NamedParameter {
|
||||
final override OptionalParameter::Range range;
|
||||
class OptionalParameter extends NamedParameter, TOptionalParameter {
|
||||
private Generated::OptionalParameter g;
|
||||
|
||||
OptionalParameter() { this = TOptionalParameter(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "OptionalParameter" }
|
||||
|
||||
@@ -147,7 +195,21 @@ class OptionalParameter extends @optional_parameter, NamedParameter {
|
||||
* Gets the default value, i.e. the value assigned to the parameter when one
|
||||
* is not provided by the caller.
|
||||
*/
|
||||
final Expr getDefaultValue() { result = range.getDefaultValue() }
|
||||
final Expr getDefaultValue() { toGenerated(result) = g.getValue() }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
final override string getName() { result = g.getName().getValue() }
|
||||
|
||||
final override Location getLocation() { result = g.getName().getLocation() }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
result = NamedParameter.super.getAChild(pred)
|
||||
or
|
||||
pred = "getDefaultValue" and result = this.getDefaultValue()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,8 +220,16 @@ class OptionalParameter extends @optional_parameter, NamedParameter {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class SplatParameter extends @splat_parameter, NamedParameter {
|
||||
final override SplatParameter::Range range;
|
||||
class SplatParameter extends NamedParameter, TSplatParameter {
|
||||
private Generated::SplatParameter g;
|
||||
|
||||
SplatParameter() { this = TSplatParameter(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SplatParameter" }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, g.getName()) }
|
||||
|
||||
final override string toString() { result = "*" + this.getName() }
|
||||
|
||||
final override string getName() { result = g.getName().getValue() }
|
||||
}
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql.Locations
|
||||
private import internal.Pattern
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
private import internal.Variable
|
||||
|
||||
/** A pattern. */
|
||||
class Pattern extends AstNode {
|
||||
override Pattern::Range range;
|
||||
|
||||
Pattern() { range = this }
|
||||
Pattern() {
|
||||
explicitAssignmentNode(toGenerated(this), _) or
|
||||
implicitAssignmentNode(toGenerated(this)) or
|
||||
implicitParameterAssignmentNode(toGenerated(this), _)
|
||||
}
|
||||
|
||||
/** Gets a variable used in (or introduced by) this pattern. */
|
||||
Variable getAVariable() { result = range.getAVariable() }
|
||||
Variable getAVariable() { none() }
|
||||
}
|
||||
|
||||
private class LhsExpr_ =
|
||||
TVariableAccess or TTokenConstantAccess or TScopeResolutionConstantAccess or TMethodCall or
|
||||
TSimpleParameter;
|
||||
|
||||
/**
|
||||
* A "left-hand-side" expression. An `LhsExpr` can occur on the left-hand side of
|
||||
* operator assignments (`AssignOperation`), in patterns (`Pattern`) on the left-hand side of
|
||||
@@ -29,17 +36,14 @@ class Pattern extends AstNode {
|
||||
* rescue E => var
|
||||
* ```
|
||||
*/
|
||||
class LhsExpr extends Pattern, Expr {
|
||||
override LhsExpr::Range range;
|
||||
class LhsExpr extends Pattern, LhsExpr_, Expr {
|
||||
override Variable getAVariable() { result = this.(VariableAccess).getVariable() }
|
||||
}
|
||||
|
||||
private class TVariablePattern = TVariableAccess or TSimpleParameter;
|
||||
|
||||
/** A simple variable pattern. */
|
||||
class VariablePattern extends Pattern, VariablePattern::VariableToken {
|
||||
override VariablePattern::Range range;
|
||||
|
||||
/** Gets the variable used in (or introduced by) this pattern. */
|
||||
Variable getVariable() { access(this, result) }
|
||||
}
|
||||
class VariablePattern extends Pattern, LhsExpr, TVariablePattern { }
|
||||
|
||||
/**
|
||||
* A tuple pattern.
|
||||
@@ -51,13 +55,25 @@ class VariablePattern extends Pattern, VariablePattern::VariableToken {
|
||||
* a, b, *rest, c, d = value
|
||||
* ```
|
||||
*/
|
||||
class TuplePattern extends Pattern {
|
||||
override TuplePattern::Range range;
|
||||
|
||||
class TuplePattern extends Pattern, TTuplePattern {
|
||||
override string getAPrimaryQlClass() { result = "TuplePattern" }
|
||||
|
||||
private Generated::AstNode getChild(int i) {
|
||||
result = toGenerated(this).(Generated::DestructuredParameter).getChild(i)
|
||||
or
|
||||
result = toGenerated(this).(Generated::DestructuredLeftAssignment).getChild(i)
|
||||
or
|
||||
result = toGenerated(this).(Generated::LeftAssignmentList).getChild(i)
|
||||
}
|
||||
|
||||
/** Gets the `i`th pattern in this tuple pattern. */
|
||||
final Pattern getElement(int i) { result = range.getElement(i) }
|
||||
final Pattern getElement(int i) {
|
||||
exists(Generated::AstNode c | c = this.getChild(i) |
|
||||
toGenerated(result) = c.(Generated::RestAssignment).getChild()
|
||||
or
|
||||
toGenerated(result) = c
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a sub pattern in this tuple pattern. */
|
||||
final Pattern getAnElement() { result = this.getElement(_) }
|
||||
@@ -69,5 +85,13 @@ class TuplePattern extends Pattern {
|
||||
* a, b, *rest, c, d = value
|
||||
* ```
|
||||
*/
|
||||
final int getRestIndex() { result = range.getRestIndex() }
|
||||
final int getRestIndex() {
|
||||
result = unique(int i | getChild(i) instanceof Generated::RestAssignment)
|
||||
}
|
||||
|
||||
override Variable getAVariable() { result = this.getElement(_).getAVariable() }
|
||||
|
||||
override string toString() { result = "(..., ...)" }
|
||||
|
||||
override AstNode getAChild(string pred) { pred = "getElement" and result = getElement(_) }
|
||||
}
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
private import codeql_ruby.AST
|
||||
private import internal.AST
|
||||
private import internal.Scope
|
||||
private import internal.TreeSitter
|
||||
|
||||
class Scope extends AstNode, Scope::ScopeType {
|
||||
override Scope::Range range;
|
||||
class Scope extends AstNode, TScopeType {
|
||||
private Scope::Range range;
|
||||
|
||||
AstNode getADescendant() { result = range.getADescendant() }
|
||||
Scope() { range = toGenerated(this) }
|
||||
|
||||
ModuleBase getEnclosingModule() { result = range.getEnclosingModule() }
|
||||
/** Gets the enclosing module, if any. */
|
||||
ModuleBase getEnclosingModule() { toGenerated(result) = range.getEnclosingModule() }
|
||||
|
||||
MethodBase getEnclosingMethod() { result = range.getEnclosingMethod() }
|
||||
/** 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() { result = range.getOuterScope() }
|
||||
Scope getOuterScope() { toGenerated(result) = range.getOuterScope() }
|
||||
|
||||
/** Gets a variable that is declared in this scope. */
|
||||
final Variable getAVariable() { result.getDeclaringScope() = this }
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.CFG
|
||||
private import internal.Expr
|
||||
private import internal.Statement
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
private import internal.Variable
|
||||
private import codeql_ruby.controlflow.internal.ControlFlowGraphImpl
|
||||
|
||||
/**
|
||||
@@ -9,14 +10,12 @@ private import codeql_ruby.controlflow.internal.ControlFlowGraphImpl
|
||||
*
|
||||
* This is the root QL class for all statements.
|
||||
*/
|
||||
class Stmt extends AstNode {
|
||||
override Stmt::Range range;
|
||||
|
||||
class Stmt extends AstNode, TStmt {
|
||||
/** Gets a control-flow node for this statement, if any. */
|
||||
CfgNodes::AstCfgNode getAControlFlowNode() { result.getNode() = this }
|
||||
|
||||
/** Gets the control-flow scope of this statement, if any. */
|
||||
CfgScope getCfgScope() { result = getCfgScope(this) }
|
||||
CfgScope getCfgScope() { result = getCfgScope(toGenerated(this)) }
|
||||
|
||||
/** Gets the enclosing callable, if any. */
|
||||
Callable getEnclosingCallable() { result = this.getCfgScope() }
|
||||
@@ -25,10 +24,10 @@ class Stmt extends AstNode {
|
||||
/**
|
||||
* An empty statement (`;`).
|
||||
*/
|
||||
class EmptyStmt extends Stmt, @token_empty_statement {
|
||||
final override EmptyStmt::Range range;
|
||||
|
||||
class EmptyStmt extends Stmt, TEmptyStmt {
|
||||
final override string getAPrimaryQlClass() { result = "EmptyStmt" }
|
||||
|
||||
final override string toString() { result = ";" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -39,10 +38,10 @@ class EmptyStmt extends Stmt, @token_empty_statement {
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class BeginExpr extends BodyStatement, @begin {
|
||||
final override Begin::Range range;
|
||||
|
||||
class BeginExpr extends BodyStmt, TBeginExpr {
|
||||
final override string getAPrimaryQlClass() { result = "BeginExpr" }
|
||||
|
||||
final override string toString() { result = "begin ... " }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,10 +50,16 @@ class BeginExpr extends BodyStatement, @begin {
|
||||
* BEGIN { puts "starting ..." }
|
||||
* ```
|
||||
*/
|
||||
class BeginBlock extends StmtSequence, @begin_block {
|
||||
final override BeginBlock::Range range;
|
||||
class BeginBlock extends StmtSequence, TBeginBlock {
|
||||
private Generated::BeginBlock g;
|
||||
|
||||
BeginBlock() { this = TBeginBlock(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "BeginBlock" }
|
||||
|
||||
final override string toString() { result = "BEGIN { ... }" }
|
||||
|
||||
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,10 +68,16 @@ class BeginBlock extends StmtSequence, @begin_block {
|
||||
* END { puts "shutting down" }
|
||||
* ```
|
||||
*/
|
||||
class EndBlock extends StmtSequence, @end_block {
|
||||
final override EndBlock::Range range;
|
||||
class EndBlock extends StmtSequence, TEndBlock {
|
||||
private Generated::EndBlock g;
|
||||
|
||||
EndBlock() { this = TEndBlock(g) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "EndBlock" }
|
||||
|
||||
final override string toString() { result = "END { ... }" }
|
||||
|
||||
final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,16 +88,24 @@ class EndBlock extends StmtSequence, @end_block {
|
||||
* - undef :"method_#{ name }"
|
||||
* ```
|
||||
*/
|
||||
class UndefStmt extends Stmt, @undef {
|
||||
final override UndefStmt::Range range;
|
||||
class UndefStmt extends Stmt, TUndefStmt {
|
||||
private Generated::Undef g;
|
||||
|
||||
UndefStmt() { this = TUndefStmt(g) }
|
||||
|
||||
/** Gets the `n`th method name to undefine. */
|
||||
final MethodName getMethodName(int n) { result = range.getMethodName(n) }
|
||||
final MethodName getMethodName(int n) { toGenerated(result) = g.getChild(n) }
|
||||
|
||||
/** Gets a method name to undefine. */
|
||||
final MethodName getAMethodName() { result = getMethodName(_) }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "UndefStmt" }
|
||||
|
||||
final override string toString() { result = "undef ..." }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getMethodName" and result = this.getMethodName(_)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,16 +116,26 @@ class UndefStmt extends Stmt, @undef {
|
||||
* - alias bar :"method_#{ name }"
|
||||
* ```
|
||||
*/
|
||||
class AliasStmt extends Stmt, @alias {
|
||||
final override AliasStmt::Range range;
|
||||
class AliasStmt extends Stmt, TAliasStmt {
|
||||
private Generated::Alias g;
|
||||
|
||||
AliasStmt() { this = TAliasStmt(g) }
|
||||
|
||||
/** Gets the new method name. */
|
||||
final MethodName getNewName() { result = range.getNewName() }
|
||||
final MethodName getNewName() { toGenerated(result) = g.getName() }
|
||||
|
||||
/** Gets the original method name. */
|
||||
final MethodName getOldName() { result = range.getOldName() }
|
||||
final MethodName getOldName() { toGenerated(result) = g.getAlias() }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "AliasStmt" }
|
||||
|
||||
final override string toString() { result = "alias ..." }
|
||||
|
||||
final override AstNode getAChild(string pred) {
|
||||
pred = "getNewName" and result = this.getNewName()
|
||||
or
|
||||
pred = "getOldName" and result = this.getOldName()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,11 +150,30 @@ class AliasStmt extends Stmt, @alias {
|
||||
* next value
|
||||
* ```
|
||||
*/
|
||||
class ReturningStmt extends Stmt {
|
||||
override ReturningStmt::Range range;
|
||||
class ReturningStmt extends Stmt, TReturningStmt {
|
||||
private Generated::ArgumentList getArgumentList() {
|
||||
result = any(Generated::Return g | this = TReturnStmt(g)).getChild()
|
||||
or
|
||||
result = any(Generated::Break g | this = TBreakStmt(g)).getChild()
|
||||
or
|
||||
result = any(Generated::Next g | this = TNextStmt(g)).getChild()
|
||||
}
|
||||
|
||||
/** Gets the returned value, if any. */
|
||||
final Expr getValue() { result = range.getValue() }
|
||||
final Expr getValue() {
|
||||
toGenerated(result) =
|
||||
any(Generated::AstNode res |
|
||||
exists(Generated::ArgumentList a, int c |
|
||||
a = this.getArgumentList() and c = count(a.getChild(_))
|
||||
|
|
||||
res = a.getChild(0) and c = 1
|
||||
or
|
||||
res = a and c > 1
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override AstNode getAChild(string pred) { pred = "getValue" and result = this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,10 +183,10 @@ class ReturningStmt extends Stmt {
|
||||
* return value
|
||||
* ```
|
||||
*/
|
||||
class ReturnStmt extends ReturningStmt, @return {
|
||||
final override ReturnStmt::Range range;
|
||||
|
||||
class ReturnStmt extends ReturningStmt, TReturnStmt {
|
||||
final override string getAPrimaryQlClass() { result = "ReturnStmt" }
|
||||
|
||||
final override string toString() { result = "return" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,10 +196,10 @@ class ReturnStmt extends ReturningStmt, @return {
|
||||
* break value
|
||||
* ```
|
||||
*/
|
||||
class BreakStmt extends ReturningStmt, @break {
|
||||
final override BreakStmt::Range range;
|
||||
|
||||
class BreakStmt extends ReturningStmt, TBreakStmt {
|
||||
final override string getAPrimaryQlClass() { result = "BreakStmt" }
|
||||
|
||||
final override string toString() { result = "break" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,10 +209,10 @@ class BreakStmt extends ReturningStmt, @break {
|
||||
* next value
|
||||
* ```
|
||||
*/
|
||||
class NextStmt extends ReturningStmt, @next {
|
||||
final override NextStmt::Range range;
|
||||
|
||||
class NextStmt extends ReturningStmt, TNextStmt {
|
||||
final override string getAPrimaryQlClass() { result = "NextStmt" }
|
||||
|
||||
final override string toString() { result = "next" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,10 +221,10 @@ class NextStmt extends ReturningStmt, @next {
|
||||
* redo
|
||||
* ```
|
||||
*/
|
||||
class RedoStmt extends Stmt, @redo {
|
||||
final override RedoStmt::Range range;
|
||||
|
||||
class RedoStmt extends Stmt, TRedoStmt {
|
||||
final override string getAPrimaryQlClass() { result = "RedoStmt" }
|
||||
|
||||
final override string toString() { result = "redo" }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,8 +233,8 @@ class RedoStmt extends Stmt, @redo {
|
||||
* retry
|
||||
* ```
|
||||
*/
|
||||
class RetryStmt extends Stmt, @retry {
|
||||
final override RetryStmt::Range range;
|
||||
|
||||
class RetryStmt extends Stmt, TRetryStmt {
|
||||
final override string getAPrimaryQlClass() { result = "RetryStmt" }
|
||||
|
||||
final override string toString() { result = "retry" }
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
private import codeql_ruby.AST
|
||||
private import codeql.Locations
|
||||
private import internal.AST
|
||||
private import internal.TreeSitter
|
||||
private import internal.Variable
|
||||
|
||||
/** A variable declared in a scope. */
|
||||
@@ -20,7 +22,7 @@ class Variable extends TVariable {
|
||||
final Location getLocation() { result = range.getLocation() }
|
||||
|
||||
/** Gets the scope this variable is declared in. */
|
||||
final Scope getDeclaringScope() { result = range.getDeclaringScope() }
|
||||
final Scope getDeclaringScope() { toGenerated(result) = range.getDeclaringScope() }
|
||||
|
||||
/** Gets an access to this variable. */
|
||||
VariableAccess getAnAccess() { result.getVariable() = this }
|
||||
@@ -77,11 +79,9 @@ class ClassVariable extends Variable, TClassVariable {
|
||||
}
|
||||
|
||||
/** An access to a variable. */
|
||||
class VariableAccess extends Expr {
|
||||
override VariableAccess::Range range;
|
||||
|
||||
class VariableAccess extends Expr, TVariableAccess {
|
||||
/** Gets the variable this identifier refers to. */
|
||||
Variable getVariable() { result = range.getVariable() }
|
||||
Variable getVariable() { none() }
|
||||
|
||||
/**
|
||||
* Holds if this access is a write access belonging to the explicit
|
||||
@@ -93,7 +93,9 @@ class VariableAccess extends Expr {
|
||||
*
|
||||
* both `a` and `b` are write accesses belonging to the same assignment.
|
||||
*/
|
||||
predicate isExplicitWrite(AstNode assignment) { range.isExplicitWrite(assignment) }
|
||||
predicate isExplicitWrite(AstNode assignment) {
|
||||
explicitWriteAccess(toGenerated(this), toGenerated(assignment))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this access is a write access belonging to an implicit assignment.
|
||||
@@ -110,7 +112,7 @@ class VariableAccess extends Expr {
|
||||
* the access to `elements` in the parameter list is an implicit assignment,
|
||||
* as is the first access to `e`.
|
||||
*/
|
||||
predicate isImplicitWrite() { range.isImplicitWrite() }
|
||||
predicate isImplicitWrite() { implicitWriteAccess(toGenerated(this)) }
|
||||
}
|
||||
|
||||
/** An access to a variable where the value is updated. */
|
||||
@@ -132,14 +134,15 @@ class VariableReadAccess extends VariableAccess {
|
||||
}
|
||||
|
||||
/** An access to a local variable. */
|
||||
class LocalVariableAccess extends VariableAccess, LocalVariableAccess::LocalVariableRange {
|
||||
final override LocalVariableAccess::Range range;
|
||||
class LocalVariableAccess extends VariableAccess, TLocalVariableAccess {
|
||||
private Generated::Identifier g;
|
||||
private LocalVariable v;
|
||||
|
||||
final override LocalVariable getVariable() { result = range.getVariable() }
|
||||
LocalVariableAccess() { this = TLocalVariableAccess(g, v) }
|
||||
|
||||
final override string getAPrimaryQlClass() {
|
||||
not this instanceof NamedParameter and result = "LocalVariableAccess"
|
||||
}
|
||||
final override LocalVariable getVariable() { result = v }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "LocalVariableAccess" }
|
||||
|
||||
/**
|
||||
* Holds if this access is a captured variable access. For example in
|
||||
@@ -157,6 +160,8 @@ class LocalVariableAccess extends VariableAccess, LocalVariableAccess::LocalVari
|
||||
* the access to `x` in the second `puts x` is not.
|
||||
*/
|
||||
final predicate isCapturedAccess() { isCapturedAccess(this) }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
/** An access to a local variable where the value is updated. */
|
||||
@@ -166,12 +171,17 @@ class LocalVariableWriteAccess extends LocalVariableAccess, VariableWriteAccess
|
||||
class LocalVariableReadAccess extends LocalVariableAccess, VariableReadAccess { }
|
||||
|
||||
/** An access to a global variable. */
|
||||
class GlobalVariableAccess extends VariableAccess, @token_global_variable {
|
||||
final override GlobalVariableAccess::Range range;
|
||||
class GlobalVariableAccess extends VariableAccess, TGlobalVariableAccess {
|
||||
private Generated::GlobalVariable g;
|
||||
private GlobalVariable v;
|
||||
|
||||
final override GlobalVariable getVariable() { result = range.getVariable() }
|
||||
GlobalVariableAccess() { this = TGlobalVariableAccess(g, v) }
|
||||
|
||||
final override GlobalVariable getVariable() { result = v }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "GlobalVariableAccess" }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
/** An access to a global variable where the value is updated. */
|
||||
@@ -181,19 +191,29 @@ class GlobalVariableWriteAccess extends GlobalVariableAccess, VariableWriteAcces
|
||||
class GlobalVariableReadAccess extends GlobalVariableAccess, VariableReadAccess { }
|
||||
|
||||
/** An access to an instance variable. */
|
||||
class InstanceVariableAccess extends VariableAccess, @token_instance_variable {
|
||||
final override InstanceVariableAccess::Range range;
|
||||
class InstanceVariableAccess extends VariableAccess, TInstanceVariableAccess {
|
||||
private Generated::InstanceVariable g;
|
||||
private InstanceVariable v;
|
||||
|
||||
final override InstanceVariable getVariable() { result = range.getVariable() }
|
||||
InstanceVariableAccess() { this = TInstanceVariableAccess(g, v) }
|
||||
|
||||
final override InstanceVariable getVariable() { result = v }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "InstanceVariableAccess" }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
/** An access to a class variable. */
|
||||
class ClassVariableAccess extends VariableAccess, @token_class_variable {
|
||||
final override ClassVariableAccess::Range range;
|
||||
class ClassVariableAccess extends VariableAccess, TClassVariableAccess {
|
||||
private Generated::ClassVariable g;
|
||||
private ClassVariable v;
|
||||
|
||||
final override ClassVariable getVariable() { result = range.getVariable() }
|
||||
ClassVariableAccess() { this = TClassVariableAccess(g, v) }
|
||||
|
||||
final override ClassVariable getVariable() { result = v }
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "ClassVariableAccess" }
|
||||
|
||||
final override string toString() { result = g.getValue() }
|
||||
}
|
||||
|
||||
@@ -1,17 +1,500 @@
|
||||
import codeql.Locations
|
||||
private import TreeSitter
|
||||
private import codeql_ruby.ast.internal.Parameter
|
||||
private import codeql_ruby.ast.internal.Variable
|
||||
private import codeql_ruby.AST as AST
|
||||
|
||||
module AstNode {
|
||||
abstract class Range extends @ast_node {
|
||||
Generated::AstNode generated;
|
||||
module MethodName {
|
||||
predicate range(Generated::UnderscoreMethodName g) {
|
||||
exists(Generated::Undef u | u.getChild(_) = g)
|
||||
or
|
||||
exists(Generated::Alias a | a.getName() = g or a.getAlias() = g)
|
||||
}
|
||||
|
||||
Range() { this = generated }
|
||||
class Token =
|
||||
@setter or @token_class_variable or @token_constant or @token_global_variable or
|
||||
@token_identifier or @token_instance_variable or @token_operator;
|
||||
}
|
||||
|
||||
cached
|
||||
abstract string toString();
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
newtype TAstNode =
|
||||
TAddExpr(Generated::Binary g) { g instanceof @binary_plus } or
|
||||
TAliasStmt(Generated::Alias g) or
|
||||
TArgumentList(Generated::AstNode g) {
|
||||
(
|
||||
g.getParent() instanceof Generated::Break or
|
||||
g.getParent() instanceof Generated::Return or
|
||||
g.getParent() instanceof Generated::Next or
|
||||
g.getParent() instanceof Generated::Assignment or
|
||||
g.getParent() instanceof Generated::OperatorAssignment
|
||||
) and
|
||||
(
|
||||
strictcount(g.(Generated::ArgumentList).getChild(_)) > 1
|
||||
or
|
||||
g instanceof Generated::RightAssignmentList
|
||||
)
|
||||
} or
|
||||
TAssignAddExpr(Generated::OperatorAssignment g) { g instanceof @operator_assignment_plusequal } or
|
||||
TAssignBitwiseAndExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_ampersandequal
|
||||
} or
|
||||
TAssignBitwiseOrExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_pipeequal
|
||||
} or
|
||||
TAssignBitwiseXorExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_caretequal
|
||||
} or
|
||||
TAssignDivExpr(Generated::OperatorAssignment g) { g instanceof @operator_assignment_slashequal } or
|
||||
TAssignExponentExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_starstarequal
|
||||
} or
|
||||
TAssignExpr(Generated::Assignment g) or
|
||||
TAssignLShiftExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_langlelangleequal
|
||||
} or
|
||||
TAssignLogicalAndExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_ampersandampersandequal
|
||||
} or
|
||||
TAssignLogicalOrExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_pipepipeequal
|
||||
} or
|
||||
TAssignModuloExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_percentequal
|
||||
} or
|
||||
TAssignMulExpr(Generated::OperatorAssignment g) { g instanceof @operator_assignment_starequal } or
|
||||
TAssignRShiftExpr(Generated::OperatorAssignment g) {
|
||||
g instanceof @operator_assignment_ranglerangleequal
|
||||
} or
|
||||
TAssignSubExpr(Generated::OperatorAssignment g) { g instanceof @operator_assignment_minusequal } or
|
||||
TBareStringLiteral(Generated::BareString g) or
|
||||
TBareSymbolLiteral(Generated::BareSymbol g) or
|
||||
TBeginBlock(Generated::BeginBlock g) or
|
||||
TBeginExpr(Generated::Begin g) or
|
||||
TBitwiseAndExpr(Generated::Binary g) { g instanceof @binary_ampersand } or
|
||||
TBitwiseOrExpr(Generated::Binary g) { g instanceof @binary_pipe } or
|
||||
TBitwiseXorExpr(Generated::Binary g) { g instanceof @binary_caret } or
|
||||
TBlockArgument(Generated::BlockArgument g) or
|
||||
TBlockParameter(Generated::BlockParameter g) or
|
||||
TBraceBlock(Generated::Block g) { not g.getParent() instanceof Generated::Lambda } or
|
||||
TBreakStmt(Generated::Break g) or
|
||||
TCaseEqExpr(Generated::Binary g) { g instanceof @binary_equalequalequal } or
|
||||
TCaseExpr(Generated::Case g) or
|
||||
TCharacterLiteral(Generated::Character g) or
|
||||
TClass(Generated::Class g) or
|
||||
TClassVariableAccess(Generated::ClassVariable g, AST::ClassVariable v) {
|
||||
ClassVariableAccess::range(g, v)
|
||||
} or
|
||||
TComplementExpr(Generated::Unary g) { g instanceof @unary_tilde } or
|
||||
TComplexLiteral(Generated::Complex g) or
|
||||
TDefinedExpr(Generated::Unary g) { g instanceof @unary_definedquestion } or
|
||||
TDelimitedSymbolLiteral(Generated::DelimitedSymbol g) or
|
||||
TDestructuredLeftAssignment(Generated::DestructuredLeftAssignment g) or
|
||||
TDivExpr(Generated::Binary g) { g instanceof @binary_slash } or
|
||||
TDo(Generated::Do g) or
|
||||
TDoBlock(Generated::DoBlock g) { not g.getParent() instanceof Generated::Lambda } or
|
||||
TElementReference(Generated::ElementReference g) or
|
||||
TElse(Generated::Else g) or
|
||||
TElsif(Generated::Elsif g) or
|
||||
TEmptyStmt(Generated::EmptyStatement g) or
|
||||
TEndBlock(Generated::EndBlock g) or
|
||||
TEnsure(Generated::Ensure g) or
|
||||
TEqExpr(Generated::Binary g) { g instanceof @binary_equalequal } or
|
||||
TExponentExpr(Generated::Binary g) { g instanceof @binary_starstar } or
|
||||
TFalseLiteral(Generated::False g) or
|
||||
TFloatLiteral(Generated::Float g) { not any(Generated::Rational r).getChild() = g } or
|
||||
TForExpr(Generated::For g) or
|
||||
TForIn(Generated::In g) or // TODO REMOVE
|
||||
TGEExpr(Generated::Binary g) { g instanceof @binary_rangleequal } or
|
||||
TGTExpr(Generated::Binary g) { g instanceof @binary_rangle } or
|
||||
TGlobalVariableAccess(Generated::GlobalVariable g, AST::GlobalVariable v) {
|
||||
GlobalVariableAccess::range(g, v)
|
||||
} or
|
||||
THashKeySymbolLiteral(Generated::HashKeySymbol g) or
|
||||
THashLiteral(Generated::Hash g) or
|
||||
THashSplatArgument(Generated::HashSplatArgument g) or
|
||||
THashSplatParameter(Generated::HashSplatParameter g) or
|
||||
THereDoc(Generated::HeredocBeginning g) or
|
||||
TIdentifierMethodCall(Generated::Identifier g) { vcall(g) and not access(g, _) } or
|
||||
TIf(Generated::If g) or
|
||||
TIfModifierExpr(Generated::IfModifier g) or
|
||||
TInstanceVariableAccess(Generated::InstanceVariable g, AST::InstanceVariable v) {
|
||||
InstanceVariableAccess::range(g, v)
|
||||
} or
|
||||
TIntegerLiteral(Generated::Integer g) { not any(Generated::Rational r).getChild() = g } or
|
||||
TKeywordParameter(Generated::KeywordParameter g) or
|
||||
TLEExpr(Generated::Binary g) { g instanceof @binary_langleequal } or
|
||||
TLShiftExpr(Generated::Binary g) { g instanceof @binary_langlelangle } or
|
||||
TLTExpr(Generated::Binary g) { g instanceof @binary_langle } or
|
||||
TLambda(Generated::Lambda g) or
|
||||
TLeftAssignmentList(Generated::LeftAssignmentList g) or
|
||||
TLocalVariableAccess(Generated::Identifier g, AST::LocalVariable v) {
|
||||
LocalVariableAccess::range(g, v)
|
||||
} or
|
||||
TLogicalAndExpr(Generated::Binary g) {
|
||||
g instanceof @binary_and or g instanceof @binary_ampersandampersand
|
||||
} 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
|
||||
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
|
||||
TNextStmt(Generated::Next g) or
|
||||
TNilLiteral(Generated::Nil g) or
|
||||
TNoRegexMatchExpr(Generated::Binary g) { g instanceof @binary_bangtilde } or
|
||||
TNotExpr(Generated::Unary g) { g instanceof @unary_bang or g instanceof @unary_not } or
|
||||
TOptionalParameter(Generated::OptionalParameter g) or
|
||||
TPair(Generated::Pair g) or
|
||||
TParenthesizedExpr(Generated::ParenthesizedStatements g) or
|
||||
TRShiftExpr(Generated::Binary g) { g instanceof @binary_ranglerangle } or
|
||||
TRangeLiteral(Generated::Range g) or
|
||||
TRationalLiteral(Generated::Rational g) or
|
||||
TRedoStmt(Generated::Redo g) or
|
||||
TRegexLiteral(Generated::Regex g) or
|
||||
TRegexMatchExpr(Generated::Binary g) { g instanceof @binary_equaltilde } or
|
||||
TRegularArrayLiteral(Generated::Array g) or
|
||||
TRegularMethodCall(Generated::Call g) { not g.getMethod() instanceof Generated::Super } or
|
||||
TRegularStringLiteral(Generated::String g) or
|
||||
TRegularSuperCall(Generated::Call g) { g.getMethod() instanceof Generated::Super } or
|
||||
TRescueClause(Generated::Rescue g) or
|
||||
TRescueModifierExpr(Generated::RescueModifier g) or
|
||||
TRetryStmt(Generated::Retry g) or
|
||||
TReturnStmt(Generated::Return g) or
|
||||
TScopeResolutionConstantAccess(Generated::ScopeResolution g, Generated::Constant constant) {
|
||||
constant = g.getName() and
|
||||
(
|
||||
// A tree-sitter `scope_resolution` node with a `constant` name field is a
|
||||
// read of that constant in any context where an identifier would be a
|
||||
// vcall.
|
||||
vcall(g)
|
||||
or
|
||||
explicitAssignmentNode(g, _)
|
||||
)
|
||||
} or
|
||||
TScopeResolutionMethodCall(Generated::ScopeResolution g, Generated::Identifier i) {
|
||||
i = g.getName() and
|
||||
not exists(Generated::Call c | c.getMethod() = g)
|
||||
} or
|
||||
TSelf(Generated::Self g) or
|
||||
TSimpleParameter(Generated::Identifier g) { g instanceof Parameter::Range } or
|
||||
TSimpleSymbolLiteral(Generated::SimpleSymbol g) or
|
||||
TSingletonClass(Generated::SingletonClass g) or
|
||||
TSingletonMethod(Generated::SingletonMethod g) or
|
||||
TSpaceshipExpr(Generated::Binary g) { g instanceof @binary_langleequalrangle } or
|
||||
TSplatArgument(Generated::SplatArgument g) or
|
||||
TSplatParameter(Generated::SplatParameter g) or
|
||||
TStringArrayLiteral(Generated::StringArray g) or
|
||||
TStringConcatenation(Generated::ChainedString g) or
|
||||
TStringEscapeSequenceComponent(Generated::EscapeSequence g) or
|
||||
TStringInterpolationComponent(Generated::Interpolation g) or
|
||||
TStringTextComponent(Generated::Token g) {
|
||||
g instanceof Generated::StringContent or g instanceof Generated::HeredocContent
|
||||
} or
|
||||
TSubExpr(Generated::Binary g) { g instanceof @binary_minus } or
|
||||
TSubshellLiteral(Generated::Subshell g) or
|
||||
TSymbolArrayLiteral(Generated::SymbolArray g) or
|
||||
TTernaryIfExpr(Generated::Conditional g) or
|
||||
TThen(Generated::Then g) or
|
||||
TTokenConstantAccess(Generated::Constant g) {
|
||||
// A tree-sitter `constant` token is a read of that constant in any context
|
||||
// where an identifier would be a vcall.
|
||||
vcall(g)
|
||||
or
|
||||
explicitAssignmentNode(g, _)
|
||||
} or
|
||||
TTokenMethodName(MethodName::Token g) { MethodName::range(g) } or
|
||||
TTokenSuperCall(Generated::Super g) { vcall(g) } or
|
||||
TToplevel(Generated::Program g) { g.getLocation().getFile().getExtension() != "erb" } or
|
||||
TTrueLiteral(Generated::True g) or
|
||||
TTuplePatternParameter(Generated::DestructuredParameter g) or
|
||||
TUnaryMinusExpr(Generated::Unary g) { g instanceof @unary_minus } or
|
||||
TUnaryPlusExpr(Generated::Unary g) { g instanceof @unary_plus } or
|
||||
TUndefStmt(Generated::Undef g) or
|
||||
TUnlessExpr(Generated::Unless g) or
|
||||
TUnlessModifierExpr(Generated::UnlessModifier g) or
|
||||
TUntilExpr(Generated::Until g) or
|
||||
TUntilModifierExpr(Generated::UntilModifier g) or
|
||||
TWhenExpr(Generated::When g) or
|
||||
TWhileExpr(Generated::While g) or
|
||||
TWhileModifierExpr(Generated::WhileModifier g) or
|
||||
TYieldCall(Generated::Yield g)
|
||||
|
||||
Location getLocation() { result = generated.getLocation() }
|
||||
|
||||
predicate child(string label, AstNode::Range child) { none() }
|
||||
/** Gets the underlying TreeSitter entity for a given AST node. */
|
||||
cached
|
||||
Generated::AstNode toGenerated(AST::AstNode n) {
|
||||
n = TAddExpr(result) or
|
||||
n = TAliasStmt(result) or
|
||||
n = TArgumentList(result) or
|
||||
n = TAssignAddExpr(result) or
|
||||
n = TAssignBitwiseAndExpr(result) or
|
||||
n = TAssignBitwiseOrExpr(result) or
|
||||
n = TAssignBitwiseXorExpr(result) or
|
||||
n = TAssignDivExpr(result) or
|
||||
n = TAssignExponentExpr(result) or
|
||||
n = TAssignExpr(result) or
|
||||
n = TAssignLShiftExpr(result) or
|
||||
n = TAssignLogicalAndExpr(result) or
|
||||
n = TAssignLogicalOrExpr(result) or
|
||||
n = TAssignModuloExpr(result) or
|
||||
n = TAssignMulExpr(result) or
|
||||
n = TAssignRShiftExpr(result) or
|
||||
n = TAssignSubExpr(result) or
|
||||
n = TBareStringLiteral(result) or
|
||||
n = TBareSymbolLiteral(result) or
|
||||
n = TBeginBlock(result) or
|
||||
n = TBeginExpr(result) or
|
||||
n = TBitwiseAndExpr(result) or
|
||||
n = TBitwiseOrExpr(result) or
|
||||
n = TBitwiseXorExpr(result) or
|
||||
n = TBlockArgument(result) or
|
||||
n = TBlockParameter(result) or
|
||||
n = TBraceBlock(result) or
|
||||
n = TBreakStmt(result) or
|
||||
n = TCaseEqExpr(result) or
|
||||
n = TCaseExpr(result) or
|
||||
n = TCharacterLiteral(result) or
|
||||
n = TClass(result) or
|
||||
n = TClassVariableAccess(result, _) or
|
||||
n = TComplementExpr(result) or
|
||||
n = TComplexLiteral(result) or
|
||||
n = TDefinedExpr(result) or
|
||||
n = TDelimitedSymbolLiteral(result) or
|
||||
n = TDestructuredLeftAssignment(result) or
|
||||
n = TDivExpr(result) or
|
||||
n = TDo(result) or
|
||||
n = TDoBlock(result) or
|
||||
n = TElementReference(result) or
|
||||
n = TElse(result) or
|
||||
n = TElsif(result) or
|
||||
n = TEmptyStmt(result) or
|
||||
n = TEndBlock(result) or
|
||||
n = TEnsure(result) or
|
||||
n = TEqExpr(result) or
|
||||
n = TExponentExpr(result) or
|
||||
n = TFalseLiteral(result) or
|
||||
n = TFloatLiteral(result) or
|
||||
n = TForExpr(result) or
|
||||
n = TForIn(result) or // TODO REMOVE
|
||||
n = TGEExpr(result) or
|
||||
n = TGTExpr(result) or
|
||||
n = TGlobalVariableAccess(result, _) or
|
||||
n = THashKeySymbolLiteral(result) or
|
||||
n = THashLiteral(result) or
|
||||
n = THashSplatArgument(result) or
|
||||
n = THashSplatParameter(result) or
|
||||
n = THereDoc(result) or
|
||||
n = TIdentifierMethodCall(result) or
|
||||
n = TIf(result) or
|
||||
n = TIfModifierExpr(result) or
|
||||
n = TInstanceVariableAccess(result, _) or
|
||||
n = TIntegerLiteral(result) or
|
||||
n = TKeywordParameter(result) or
|
||||
n = TLEExpr(result) or
|
||||
n = TLShiftExpr(result) or
|
||||
n = TLTExpr(result) or
|
||||
n = TLambda(result) or
|
||||
n = TLeftAssignmentList(result) or
|
||||
n = TLocalVariableAccess(result, _) or
|
||||
n = TLogicalAndExpr(result) or
|
||||
n = TLogicalOrExpr(result) or
|
||||
n = TMethod(result) or
|
||||
n = TModule(result) or
|
||||
n = TModuloExpr(result) or
|
||||
n = TMulExpr(result) or
|
||||
n = TNEExpr(result) or
|
||||
n = TNextStmt(result) or
|
||||
n = TNilLiteral(result) or
|
||||
n = TNoRegexMatchExpr(result) or
|
||||
n = TNotExpr(result) or
|
||||
n = TOptionalParameter(result) or
|
||||
n = TPair(result) or
|
||||
n = TParenthesizedExpr(result) or
|
||||
n = TRShiftExpr(result) or
|
||||
n = TRangeLiteral(result) or
|
||||
n = TRationalLiteral(result) or
|
||||
n = TRedoStmt(result) or
|
||||
n = TRegexLiteral(result) or
|
||||
n = TRegexMatchExpr(result) or
|
||||
n = TRegularArrayLiteral(result) or
|
||||
n = TRegularMethodCall(result) or
|
||||
n = TRegularStringLiteral(result) or
|
||||
n = TRegularSuperCall(result) or
|
||||
n = TRescueClause(result) or
|
||||
n = TRescueModifierExpr(result) or
|
||||
n = TRetryStmt(result) or
|
||||
n = TReturnStmt(result) or
|
||||
n = TScopeResolutionConstantAccess(result, _) or
|
||||
n = TScopeResolutionMethodCall(result, _) or
|
||||
n = TSelf(result) or
|
||||
n = TSimpleParameter(result) or
|
||||
n = TSimpleSymbolLiteral(result) or
|
||||
n = TSingletonClass(result) or
|
||||
n = TSingletonMethod(result) or
|
||||
n = TSpaceshipExpr(result) or
|
||||
n = TSplatArgument(result) or
|
||||
n = TSplatParameter(result) or
|
||||
n = TStringArrayLiteral(result) or
|
||||
n = TStringConcatenation(result) or
|
||||
n = TStringEscapeSequenceComponent(result) or
|
||||
n = TStringInterpolationComponent(result) or
|
||||
n = TStringTextComponent(result) or
|
||||
n = TSubExpr(result) or
|
||||
n = TSubshellLiteral(result) or
|
||||
n = TSymbolArrayLiteral(result) or
|
||||
n = TTernaryIfExpr(result) or
|
||||
n = TThen(result) or
|
||||
n = TTokenConstantAccess(result) or
|
||||
n = TTokenMethodName(result) or
|
||||
n = TTokenSuperCall(result) or
|
||||
n = TToplevel(result) or
|
||||
n = TTrueLiteral(result) or
|
||||
n = TTuplePatternParameter(result) or
|
||||
n = TUnaryMinusExpr(result) or
|
||||
n = TUnaryPlusExpr(result) or
|
||||
n = TUndefStmt(result) or
|
||||
n = TUnlessExpr(result) or
|
||||
n = TUnlessModifierExpr(result) or
|
||||
n = TUntilExpr(result) or
|
||||
n = TUntilModifierExpr(result) or
|
||||
n = TWhenExpr(result) or
|
||||
n = TWhileExpr(result) or
|
||||
n = TWhileModifierExpr(result) or
|
||||
n = TYieldCall(result)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
TAstNode fromGenerated(Generated::AstNode n) { n = toGenerated(result) }
|
||||
|
||||
class TCall = TMethodCall or TYieldCall;
|
||||
|
||||
class TMethodCall =
|
||||
TIdentifierMethodCall or TScopeResolutionMethodCall or TRegularMethodCall or TElementReference or
|
||||
TSuperCall;
|
||||
|
||||
class TSuperCall = TTokenSuperCall or TRegularSuperCall;
|
||||
|
||||
class TConstantAccess = TTokenConstantAccess or TScopeResolutionConstantAccess or TNamespace;
|
||||
|
||||
class TControlExpr = TConditionalExpr or TCaseExpr or TLoop;
|
||||
|
||||
class TConditionalExpr =
|
||||
TIfExpr or TUnlessExpr or TIfModifierExpr or TUnlessModifierExpr or TTernaryIfExpr;
|
||||
|
||||
class TIfExpr = TIf or TElsif;
|
||||
|
||||
class TConditionalLoop = TWhileExpr or TUntilExpr or TWhileModifierExpr or TUntilModifierExpr;
|
||||
|
||||
class TLoop = TConditionalLoop or TForExpr;
|
||||
|
||||
class TExpr =
|
||||
TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or
|
||||
TCall or TBlockArgument or TSplatArgument or THashSplatArgument or TConstantAccess or
|
||||
TControlExpr or TWhenExpr or TLiteral or TCallable or TVariableAccess or TStmtSequence or
|
||||
TOperation or TSimpleParameter;
|
||||
|
||||
class TStmtSequence =
|
||||
TBeginBlock or TEndBlock or TThen or TElse or TDo or TEnsure or TStringInterpolationComponent or
|
||||
TBlock or TBodyStmt or TParenthesizedExpr;
|
||||
|
||||
class TBodyStmt = TBeginExpr or TModuleBase or TMethod or TLambda or TDoBlock or TSingletonMethod;
|
||||
|
||||
class TLiteral =
|
||||
TNumericLiteral or TNilLiteral or TBooleanLiteral or TStringlikeLiteral or TCharacterLiteral or
|
||||
TArrayLiteral or THashLiteral or TRangeLiteral or TTokenMethodName;
|
||||
|
||||
class TNumericLiteral = TIntegerLiteral or TFloatLiteral or TRationalLiteral or TComplexLiteral;
|
||||
|
||||
class TBooleanLiteral = TTrueLiteral or TFalseLiteral;
|
||||
|
||||
class TStringComponent =
|
||||
TStringTextComponent or TStringEscapeSequenceComponent or TStringInterpolationComponent;
|
||||
|
||||
class TStringlikeLiteral =
|
||||
TStringLiteral or TRegexLiteral or TSymbolLiteral or TSubshellLiteral or THereDoc;
|
||||
|
||||
class TStringLiteral = TRegularStringLiteral or TBareStringLiteral;
|
||||
|
||||
class TSymbolLiteral = TSimpleSymbolLiteral or TComplexSymbolLiteral or THashKeySymbolLiteral;
|
||||
|
||||
class TComplexSymbolLiteral = TDelimitedSymbolLiteral or TBareSymbolLiteral;
|
||||
|
||||
class TArrayLiteral = TRegularArrayLiteral or TStringArrayLiteral or TSymbolArrayLiteral;
|
||||
|
||||
class TCallable = TMethodBase or TLambda or TBlock;
|
||||
|
||||
class TMethodBase = TMethod or TSingletonMethod;
|
||||
|
||||
class TBlock = TDoBlock or TBraceBlock;
|
||||
|
||||
class TModuleBase = TToplevel or TNamespace or TSingletonClass;
|
||||
|
||||
class TNamespace = TClass or TModule;
|
||||
|
||||
class TOperation = TUnaryOperation or TBinaryOperation or TAssignment;
|
||||
|
||||
class TUnaryOperation =
|
||||
TUnaryLogicalOperation or TUnaryArithmeticOperation or TUnaryBitwiseOperation or TDefinedExpr;
|
||||
|
||||
class TUnaryLogicalOperation = TNotExpr;
|
||||
|
||||
class TUnaryArithmeticOperation = TUnaryPlusExpr or TUnaryMinusExpr;
|
||||
|
||||
class TUnaryBitwiseOperation = TComplementExpr;
|
||||
|
||||
class TBinaryOperation =
|
||||
TBinaryArithmeticOperation or TBinaryLogicalOperation or TBinaryBitwiseOperation or
|
||||
TComparisonOperation or TSpaceshipExpr or TRegexMatchExpr or TNoRegexMatchExpr;
|
||||
|
||||
class TBinaryArithmeticOperation =
|
||||
TAddExpr or TSubExpr or TMulExpr or TDivExpr or TModuloExpr or TExponentExpr;
|
||||
|
||||
class TBinaryLogicalOperation = TLogicalAndExpr or TLogicalOrExpr;
|
||||
|
||||
class TBinaryBitwiseOperation =
|
||||
TLShiftExpr or TRShiftExpr or TBitwiseAndExpr or TBitwiseOrExpr or TBitwiseXorExpr;
|
||||
|
||||
class TComparisonOperation = TEqualityOperation or TRelationalOperation;
|
||||
|
||||
class TEqualityOperation = TEqExpr or TNEExpr or TCaseEqExpr;
|
||||
|
||||
class TRelationalOperation = TGTExpr or TGEExpr or TLTExpr or TLEExpr;
|
||||
|
||||
class TAssignment = TAssignExpr or TAssignOperation;
|
||||
|
||||
class TAssignOperation =
|
||||
TAssignArithmeticOperation or TAssignLogicalOperation or TAssignBitwiseOperation;
|
||||
|
||||
class TAssignArithmeticOperation =
|
||||
TAssignAddExpr or TAssignSubExpr or TAssignMulExpr or TAssignDivExpr or TAssignModuloExpr or
|
||||
TAssignExponentExpr;
|
||||
|
||||
class TAssignLogicalOperation = TAssignLogicalAndExpr or TAssignLogicalOrExpr;
|
||||
|
||||
class TAssignBitwiseOperation =
|
||||
TAssignLShiftExpr or TAssignRShiftExpr or TAssignBitwiseAndExpr or TAssignBitwiseOrExpr or
|
||||
TAssignBitwiseXorExpr;
|
||||
|
||||
class TStmt =
|
||||
TEmptyStmt or TBodyStmt or TStmtSequence or TUndefStmt or TAliasStmt or TReturningStmt or
|
||||
TRedoStmt or TRetryStmt or TExpr;
|
||||
|
||||
class TReturningStmt = TReturnStmt or TBreakStmt or TNextStmt;
|
||||
|
||||
class TParameter =
|
||||
TPatternParameter or TBlockParameter or THashSplatParameter or TKeywordParameter or
|
||||
TOptionalParameter or TSplatParameter;
|
||||
|
||||
class TPatternParameter = TSimpleParameter or TTuplePatternParameter;
|
||||
|
||||
class TNamedParameter =
|
||||
TSimpleParameter or TBlockParameter or THashSplatParameter or TKeywordParameter or
|
||||
TOptionalParameter or TSplatParameter;
|
||||
|
||||
class TTuplePattern = TTuplePatternParameter or TDestructuredLeftAssignment or TLeftAssignmentList;
|
||||
|
||||
class TVariableAccess =
|
||||
TLocalVariableAccess or TGlobalVariableAccess or TInstanceVariableAccess or TClassVariableAccess;
|
||||
|
||||
@@ -1,262 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Pattern
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
private import codeql_ruby.ast.internal.Variable
|
||||
|
||||
module Call {
|
||||
abstract class Range extends Expr::Range {
|
||||
abstract Expr getArgument(int n);
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getArgument" and child = getArgument(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module MethodCall {
|
||||
class Range extends Call::Range {
|
||||
MethodCallRange::Range range;
|
||||
|
||||
Range() { this = range }
|
||||
|
||||
final Block getBlock() { result = range.getBlock() }
|
||||
|
||||
final Expr getReceiver() { result = range.getReceiver() }
|
||||
|
||||
final override Expr getArgument(int n) { result = range.getArgument(n) }
|
||||
|
||||
abstract string getMethodName();
|
||||
|
||||
override string toString() {
|
||||
result = range.toString()
|
||||
or
|
||||
not exists(range.toString()) and result = "call to " + concat(this.getMethodName(), "/")
|
||||
}
|
||||
|
||||
final override predicate child(string label, AstNode::Range child) {
|
||||
super.child(label, child)
|
||||
or
|
||||
label = "getReceiver" and child = getReceiver()
|
||||
or
|
||||
label = "getBlock" and child = getBlock()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module MethodCallRange {
|
||||
abstract class Range extends @ast_node {
|
||||
Generated::AstNode generated;
|
||||
|
||||
Range() { this = generated }
|
||||
|
||||
abstract Block getBlock();
|
||||
|
||||
abstract Expr getReceiver();
|
||||
|
||||
abstract string getMethod();
|
||||
|
||||
abstract Expr getArgument(int n);
|
||||
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
private class IdentifierCallRange extends MethodCallRange::Range, @token_identifier {
|
||||
final override Generated::Identifier generated;
|
||||
|
||||
IdentifierCallRange() { vcall(this) and not access(this, _) }
|
||||
|
||||
final override Expr getReceiver() { none() }
|
||||
|
||||
final override string getMethod() { result = generated.getValue() }
|
||||
|
||||
final override Expr getArgument(int n) { none() }
|
||||
|
||||
final override Block getBlock() { none() }
|
||||
}
|
||||
|
||||
private class ScopeResolutionIdentifierCallRange extends MethodCallRange::Range, @scope_resolution {
|
||||
final override Generated::ScopeResolution generated;
|
||||
Generated::Identifier identifier;
|
||||
|
||||
ScopeResolutionIdentifierCallRange() {
|
||||
identifier = generated.getName() and
|
||||
not exists(Generated::Call c | c.getMethod() = this)
|
||||
}
|
||||
|
||||
final override Expr getReceiver() { result = generated.getScope() }
|
||||
|
||||
final override string getMethod() { result = identifier.getValue() }
|
||||
|
||||
final override Expr getArgument(int n) { none() }
|
||||
|
||||
final override Block getBlock() { none() }
|
||||
}
|
||||
|
||||
private class RegularCallRange extends MethodCallRange::Range, @call {
|
||||
final override Generated::Call generated;
|
||||
|
||||
final override Expr getReceiver() {
|
||||
result = generated.getReceiver()
|
||||
or
|
||||
not exists(generated.getReceiver()) and
|
||||
result = generated.getMethod().(Generated::ScopeResolution).getScope()
|
||||
}
|
||||
|
||||
final override string getMethod() {
|
||||
result = "call" and generated.getMethod() instanceof Generated::ArgumentList
|
||||
or
|
||||
result = generated.getMethod().(Generated::Token).getValue()
|
||||
or
|
||||
result =
|
||||
generated.getMethod().(Generated::ScopeResolution).getName().(Generated::Token).getValue()
|
||||
}
|
||||
|
||||
final override Expr getArgument(int n) {
|
||||
result = generated.getArguments().getChild(n)
|
||||
or
|
||||
not exists(generated.getArguments()) and
|
||||
result = generated.getMethod().(Generated::ArgumentList).getChild(n)
|
||||
}
|
||||
|
||||
final override Block getBlock() { result = generated.getBlock() }
|
||||
}
|
||||
}
|
||||
|
||||
module ElementReferenceRange {
|
||||
class Range extends MethodCallRange::Range, @element_reference {
|
||||
final override Generated::ElementReference generated;
|
||||
|
||||
final override Expr getReceiver() { result = generated.getObject() }
|
||||
|
||||
final override string getMethod() { result = "[]" }
|
||||
|
||||
final override string toString() { result = "...[...]" }
|
||||
|
||||
final override Expr getArgument(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override Block getBlock() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module NormalMethodCall {
|
||||
class Range extends MethodCall::Range {
|
||||
Range() {
|
||||
not this instanceof LhsExpr::Range or
|
||||
generated.getParent() instanceof AssignOperation
|
||||
}
|
||||
|
||||
final override string getMethodName() { result = range.getMethod() }
|
||||
}
|
||||
}
|
||||
|
||||
module SetterMethodCall {
|
||||
class Range extends MethodCall::Range, LhsExpr::Range {
|
||||
final override string getMethodName() { result = range.getMethod() + "=" }
|
||||
|
||||
final override string toString() { result = MethodCall::Range.super.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
module ElementReference {
|
||||
class Range extends MethodCall::Range {
|
||||
override ElementReferenceRange::Range range;
|
||||
|
||||
final override string getMethodName() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module SuperCall {
|
||||
class Range extends NormalMethodCall::Range {
|
||||
override SuperCallRange::Range range;
|
||||
}
|
||||
}
|
||||
|
||||
module YieldCall {
|
||||
class Range extends Call::Range, @yield {
|
||||
final override Generated::Yield generated;
|
||||
|
||||
final override Expr getArgument(int n) { result = generated.getChild().getChild(n) }
|
||||
|
||||
final override string toString() { result = "yield ..." }
|
||||
}
|
||||
}
|
||||
|
||||
module SuperCallRange {
|
||||
abstract class Range extends MethodCallRange::Range { }
|
||||
|
||||
private class SuperTokenCallRange extends SuperCallRange::Range, @token_super {
|
||||
final override Generated::Super generated;
|
||||
|
||||
// N.B. `super` tokens can never be accesses, so any vcall with `super` must
|
||||
// be a call.
|
||||
SuperTokenCallRange() { vcall(this) }
|
||||
|
||||
final override Expr getReceiver() { none() }
|
||||
|
||||
final override string getMethod() { result = generated.getValue() }
|
||||
|
||||
final override Expr getArgument(int n) { none() }
|
||||
|
||||
final override Block getBlock() { none() }
|
||||
}
|
||||
|
||||
private class RegularSuperCallRange extends SuperCallRange::Range, @call {
|
||||
final override Generated::Call generated;
|
||||
|
||||
RegularSuperCallRange() { generated.getMethod() instanceof Generated::Super }
|
||||
|
||||
final override Expr getReceiver() { none() }
|
||||
|
||||
final override string getMethod() {
|
||||
result = generated.getMethod().(Generated::Super).getValue()
|
||||
}
|
||||
|
||||
final override Expr getArgument(int n) { result = generated.getArguments().getChild(n) }
|
||||
|
||||
final override Block getBlock() { result = generated.getBlock() }
|
||||
}
|
||||
}
|
||||
|
||||
module BlockArgument {
|
||||
class Range extends Expr::Range, @block_argument {
|
||||
final override Generated::BlockArgument generated;
|
||||
|
||||
final Expr getValue() { result = generated.getChild() }
|
||||
|
||||
final override string toString() { result = "&..." }
|
||||
|
||||
final override predicate child(string label, AstNode::Range child) {
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module SplatArgument {
|
||||
class Range extends Expr::Range, @splat_argument {
|
||||
final override Generated::SplatArgument generated;
|
||||
|
||||
final Expr getValue() { result = generated.getChild() }
|
||||
|
||||
final override string toString() { result = "*..." }
|
||||
|
||||
final override predicate child(string label, AstNode::Range child) {
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module HashSplatArgument {
|
||||
class Range extends Expr::Range, @hash_splat_argument {
|
||||
final override Generated::HashSplatArgument generated;
|
||||
|
||||
final Expr getValue() { result = generated.getChild() }
|
||||
|
||||
final override string toString() { result = "**..." }
|
||||
|
||||
final override predicate child(string label, AstNode::Range child) {
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Pattern
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
private import codeql_ruby.ast.internal.Variable
|
||||
|
||||
module ConstantAccess {
|
||||
abstract class Range extends Expr::Range {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
abstract string getName();
|
||||
|
||||
abstract Expr::Range getScopeExpr();
|
||||
|
||||
abstract predicate hasGlobalScope();
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getScopeExpr" and child = getScopeExpr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ConstantReadAccess {
|
||||
abstract class Range extends ConstantAccess::Range { }
|
||||
|
||||
private class TokenConstantReadAccessRange extends ConstantReadAccess::Range, @token_constant {
|
||||
final override Generated::Constant generated;
|
||||
|
||||
// A tree-sitter `constant` token is a read of that constant in any context
|
||||
// where an identifier would be a vcall.
|
||||
TokenConstantReadAccessRange() { vcall(this) }
|
||||
|
||||
final override string getName() { result = generated.getValue() }
|
||||
|
||||
final override Expr::Range getScopeExpr() { none() }
|
||||
|
||||
final override predicate hasGlobalScope() { none() }
|
||||
}
|
||||
|
||||
private class ScopeResolutionReadAccessRange extends ConstantReadAccess::Range, @scope_resolution {
|
||||
final override Generated::ScopeResolution generated;
|
||||
Generated::Constant constant;
|
||||
|
||||
// A tree-sitter `scope_resolution` node with a `constant` name field is a
|
||||
// read of that constant in any context where an identifier would be a
|
||||
// vcall.
|
||||
ScopeResolutionReadAccessRange() {
|
||||
constant = generated.getName() and
|
||||
vcall(this)
|
||||
}
|
||||
|
||||
final override string getName() { result = constant.getValue() }
|
||||
|
||||
final override Expr::Range getScopeExpr() { result = generated.getScope() }
|
||||
|
||||
final override predicate hasGlobalScope() { not exists(generated.getScope()) }
|
||||
}
|
||||
}
|
||||
|
||||
module ConstantWriteAccess {
|
||||
abstract class Range extends ConstantAccess::Range { }
|
||||
}
|
||||
|
||||
module ConstantAssignment {
|
||||
abstract class Range extends ConstantWriteAccess::Range, LhsExpr::Range {
|
||||
Range() { explicitAssignmentNode(this, _) }
|
||||
|
||||
override string toString() { result = ConstantWriteAccess::Range.super.toString() }
|
||||
}
|
||||
|
||||
private class TokenConstantAssignmentRange extends ConstantAssignment::Range, @token_constant {
|
||||
final override Generated::Constant generated;
|
||||
|
||||
final override string getName() { result = generated.getValue() }
|
||||
|
||||
final override Expr::Range getScopeExpr() { none() }
|
||||
|
||||
final override predicate hasGlobalScope() { none() }
|
||||
}
|
||||
|
||||
private class ScopeResolutionAssignmentRange extends ConstantAssignment::Range, @scope_resolution {
|
||||
final override Generated::ScopeResolution generated;
|
||||
Generated::Constant constant;
|
||||
|
||||
ScopeResolutionAssignmentRange() { constant = generated.getName() }
|
||||
|
||||
final override string getName() { result = constant.getValue() }
|
||||
|
||||
final override Expr::Range getScopeExpr() { result = generated.getScope() }
|
||||
|
||||
final override predicate hasGlobalScope() { not exists(generated.getScope()) }
|
||||
}
|
||||
}
|
||||
@@ -1,299 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Pattern
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
module ControlExpr {
|
||||
abstract class Range extends Expr::Range { }
|
||||
}
|
||||
|
||||
module ConditionalExpr {
|
||||
abstract class Range extends ControlExpr::Range {
|
||||
abstract Expr getCondition();
|
||||
|
||||
abstract Stmt getBranch(boolean cond);
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getCondition" and child = getCondition()
|
||||
or
|
||||
label = "getBranch" and child = getBranch(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module IfExpr {
|
||||
abstract class Range extends ConditionalExpr::Range {
|
||||
abstract Stmt getThen();
|
||||
|
||||
abstract Stmt getElse();
|
||||
|
||||
final override string toString() {
|
||||
if this instanceof @elsif then result = "elsif ..." else result = "if ..."
|
||||
}
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
super.child(label, child)
|
||||
or
|
||||
label = "getThen" and child = getThen()
|
||||
or
|
||||
label = "getElse" and child = getElse()
|
||||
}
|
||||
}
|
||||
|
||||
private class IfRange extends IfExpr::Range, @if {
|
||||
final override Generated::If generated;
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final override Stmt getThen() { result = generated.getConsequence() }
|
||||
|
||||
final override Stmt getElse() { result = generated.getAlternative() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) {
|
||||
cond = true and result = getThen()
|
||||
or
|
||||
cond = false and result = getElse()
|
||||
}
|
||||
}
|
||||
|
||||
private class ElsifRange extends IfExpr::Range, @elsif {
|
||||
final override Generated::Elsif generated;
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final override Stmt getThen() { result = generated.getConsequence() }
|
||||
|
||||
final override Stmt getElse() { result = generated.getAlternative() }
|
||||
|
||||
final override Expr getBranch(boolean cond) {
|
||||
cond = true and result = getThen()
|
||||
or
|
||||
cond = false and result = getElse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module UnlessExpr {
|
||||
class Range extends ConditionalExpr::Range, @unless {
|
||||
final override Generated::Unless generated;
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final Stmt getThen() { result = generated.getConsequence() }
|
||||
|
||||
final Stmt getElse() { result = generated.getAlternative() }
|
||||
|
||||
final override Expr getBranch(boolean cond) {
|
||||
cond = false and result = getThen()
|
||||
or
|
||||
cond = true and result = getElse()
|
||||
}
|
||||
|
||||
final override string toString() { result = "unless ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ConditionalExpr::Range.super.child(label, child)
|
||||
or
|
||||
label = "getThen" and child = getThen()
|
||||
or
|
||||
label = "getElse" and child = getElse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module IfModifierExpr {
|
||||
class Range extends ConditionalExpr::Range, @if_modifier {
|
||||
final override Generated::IfModifier generated;
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) { cond = true and result = getBody() }
|
||||
|
||||
final override string toString() { result = "... if ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ConditionalExpr::Range.super.child(label, child)
|
||||
or
|
||||
label = "getBody" and child = getBody()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module UnlessModifierExpr {
|
||||
class Range extends ConditionalExpr::Range, @unless_modifier {
|
||||
final override Generated::UnlessModifier generated;
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) { cond = false and result = getBody() }
|
||||
|
||||
final override string toString() { result = "... unless ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ConditionalExpr::Range.super.child(label, child)
|
||||
or
|
||||
label = "getBody" and child = getBody()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module TernaryIfExpr {
|
||||
class Range extends ConditionalExpr::Range, @conditional {
|
||||
final override Generated::Conditional generated;
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final Stmt getThen() { result = generated.getConsequence() }
|
||||
|
||||
final Stmt getElse() { result = generated.getAlternative() }
|
||||
|
||||
final override Stmt getBranch(boolean cond) {
|
||||
cond = true and result = getThen()
|
||||
or
|
||||
cond = false and result = getElse()
|
||||
}
|
||||
|
||||
final override string toString() { result = "... ? ... : ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ConditionalExpr::Range.super.child(label, child)
|
||||
or
|
||||
label = "getThen" and child = getThen()
|
||||
or
|
||||
label = "getElse" and child = getElse()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module CaseExpr {
|
||||
class Range extends ControlExpr::Range, @case__ {
|
||||
final override Generated::Case generated;
|
||||
|
||||
final Expr getValue() { result = generated.getValue() }
|
||||
|
||||
final Expr getBranch(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() { result = "case ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getValue" and child = getValue()
|
||||
or
|
||||
label = "getBranch" and child = getBranch(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module WhenExpr {
|
||||
class Range extends Expr::Range, @when {
|
||||
final override Generated::When generated;
|
||||
|
||||
final Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final Expr getPattern(int n) { result = generated.getPattern(n).getChild() }
|
||||
|
||||
final override string toString() { result = "when ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getBody" and child = getBody()
|
||||
or
|
||||
label = "getPattern" and child = getPattern(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Loop {
|
||||
abstract class Range extends ControlExpr::Range {
|
||||
abstract Stmt getBody();
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getBody" and child = getBody()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ConditionalLoop {
|
||||
abstract class Range extends Loop::Range {
|
||||
abstract Expr getCondition();
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
super.child(label, child)
|
||||
or
|
||||
label = "getCondition" and child = getCondition()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module WhileExpr {
|
||||
class Range extends ConditionalLoop::Range, @while {
|
||||
final override Generated::While generated;
|
||||
|
||||
final override Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final override string toString() { result = "while ..." }
|
||||
}
|
||||
}
|
||||
|
||||
module UntilExpr {
|
||||
class Range extends ConditionalLoop::Range, @until {
|
||||
final override Generated::Until generated;
|
||||
|
||||
final override Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final override string toString() { result = "until ..." }
|
||||
}
|
||||
}
|
||||
|
||||
module WhileModifierExpr {
|
||||
class Range extends ConditionalLoop::Range, @while_modifier {
|
||||
final override Generated::WhileModifier generated;
|
||||
|
||||
final override Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final override string toString() { result = "... while ..." }
|
||||
}
|
||||
}
|
||||
|
||||
module UntilModifierExpr {
|
||||
class Range extends ConditionalLoop::Range, @until_modifier {
|
||||
final override Generated::UntilModifier generated;
|
||||
|
||||
final override Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final override Expr getCondition() { result = generated.getCondition() }
|
||||
|
||||
final override string toString() { result = "... until ..." }
|
||||
}
|
||||
}
|
||||
|
||||
module ForExpr {
|
||||
class Range extends Loop::Range, @for {
|
||||
final override Generated::For generated;
|
||||
|
||||
final override StmtSequence getBody() { result = generated.getBody() }
|
||||
|
||||
final Pattern getPattern() { result = generated.getPattern() }
|
||||
|
||||
final Expr getValue() { result = generated.getValue().getChild() }
|
||||
|
||||
final override string toString() { result = "for ... in ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Loop::Range.super.child(label, child)
|
||||
or
|
||||
label = "getPattern" and child = getPattern()
|
||||
or
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,227 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Literal
|
||||
private import codeql_ruby.ast.internal.Statement
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
module Expr {
|
||||
abstract class Range extends Stmt::Range { }
|
||||
}
|
||||
|
||||
module Self {
|
||||
class Range extends Expr::Range, @token_self {
|
||||
final override Generated::Self generated;
|
||||
|
||||
final override string toString() { result = "self" }
|
||||
}
|
||||
}
|
||||
|
||||
module ArgumentList {
|
||||
private class ValidParent = @break or @return or @next or @assignment or @operator_assignment;
|
||||
|
||||
abstract class Range extends Expr::Range {
|
||||
Range() { generated.getParent() instanceof ValidParent }
|
||||
|
||||
abstract Expr getElement(int i);
|
||||
|
||||
final override string toString() { result = "..., ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getElement" and child = getElement(_)
|
||||
}
|
||||
}
|
||||
|
||||
private class ArgArgumentList extends ArgumentList::Range, @argument_list {
|
||||
final override Generated::ArgumentList generated;
|
||||
|
||||
ArgArgumentList() { strictcount(generated.getChild(_)) > 1 }
|
||||
|
||||
final override Expr getElement(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
|
||||
private class AssignmentList extends ArgumentList::Range, @right_assignment_list {
|
||||
final override Generated::RightAssignmentList generated;
|
||||
|
||||
final override Expr getElement(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
}
|
||||
|
||||
module StmtSequence {
|
||||
abstract class Range extends Expr::Range {
|
||||
abstract Stmt getStmt(int n);
|
||||
|
||||
int getNumberOfStatements() { result = count(this.getStmt(_)) }
|
||||
|
||||
override string toString() {
|
||||
exists(int c | c = this.getNumberOfStatements() |
|
||||
c = 0 and result = ";"
|
||||
or
|
||||
c = 1 and result = this.getStmt(0).toString()
|
||||
or
|
||||
c > 1 and result = "...; ..."
|
||||
)
|
||||
}
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getStmt" and child = getStmt(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module BodyStatement {
|
||||
abstract class Range extends StmtSequence::Range {
|
||||
final override Stmt getStmt(int n) {
|
||||
result =
|
||||
rank[n + 1](Generated::AstNode node, int i |
|
||||
node = getChild(i) and
|
||||
not node instanceof Generated::Else and
|
||||
not node instanceof Generated::Rescue and
|
||||
not node instanceof Generated::Ensure
|
||||
|
|
||||
node order by i
|
||||
)
|
||||
}
|
||||
|
||||
final RescueClause getRescue(int n) {
|
||||
result = rank[n + 1](Generated::Rescue node, int i | node = getChild(i) | node order by i)
|
||||
}
|
||||
|
||||
final StmtSequence getElse() { result = unique(Generated::Else s | s = getChild(_)) }
|
||||
|
||||
final StmtSequence getEnsure() { result = unique(Generated::Ensure s | s = getChild(_)) }
|
||||
|
||||
abstract Generated::AstNode getChild(int i);
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
StmtSequence::Range.super.child(label, child)
|
||||
or
|
||||
label = "getRescue" and child = getRescue(_)
|
||||
or
|
||||
label = "getElse" and child = getElse()
|
||||
or
|
||||
label = "getEnsure" and child = getEnsure()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ParenthesizedExpr {
|
||||
class Range extends StmtSequence::Range, @parenthesized_statements {
|
||||
final override Generated::ParenthesizedStatements generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() {
|
||||
exists(int c | c = this.getNumberOfStatements() |
|
||||
c = 0 and result = "()"
|
||||
or
|
||||
c > 0 and result = "(" + StmtSequence::Range.super.toString() + ")"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ThenExpr {
|
||||
class Range extends StmtSequence::Range, @then {
|
||||
final override Generated::Then generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
}
|
||||
}
|
||||
|
||||
module ElseExpr {
|
||||
class Range extends StmtSequence::Range, @else {
|
||||
final override Generated::Else generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
}
|
||||
}
|
||||
|
||||
module DoExpr {
|
||||
class Range extends StmtSequence::Range, @do {
|
||||
final override Generated::Do generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
}
|
||||
}
|
||||
|
||||
module Ensure {
|
||||
class Range extends StmtSequence::Range, @ensure {
|
||||
final override Generated::Ensure generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() { result = "ensure ..." }
|
||||
}
|
||||
}
|
||||
|
||||
module RescueClause {
|
||||
class Range extends Expr::Range, @rescue {
|
||||
final override Generated::Rescue generated;
|
||||
|
||||
final Expr getException(int n) { result = generated.getExceptions().getChild(n) }
|
||||
|
||||
final LhsExpr getVariableExpr() { result = generated.getVariable().getChild() }
|
||||
|
||||
final StmtSequence getBody() { result = generated.getBody() }
|
||||
|
||||
final override string toString() { result = "rescue ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getException" and child = getException(_)
|
||||
or
|
||||
label = "getVariableExpr" and child = getVariableExpr()
|
||||
or
|
||||
label = "getBody" and child = getBody()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module RescueModifierExpr {
|
||||
class Range extends Expr::Range, @rescue_modifier {
|
||||
final override Generated::RescueModifier generated;
|
||||
|
||||
final Stmt getBody() { result = generated.getBody() }
|
||||
|
||||
final Stmt getHandler() { result = generated.getHandler() }
|
||||
|
||||
final override string toString() { result = "... rescue ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getBody" and child = getBody()
|
||||
or
|
||||
label = "getHandler" and child = getHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Pair {
|
||||
class Range extends Expr::Range, @pair {
|
||||
final override Generated::Pair generated;
|
||||
|
||||
final Expr getKey() { result = generated.getKey() }
|
||||
|
||||
final Expr getValue() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = "Pair" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getKey" and child = getKey()
|
||||
or
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module StringConcatenation {
|
||||
class Range extends Expr::Range, @chained_string {
|
||||
final override Generated::ChainedString generated;
|
||||
|
||||
final StringLiteral::Range getString(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = "\"...\" \"...\"" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getString" and child = getString(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,446 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
module Literal {
|
||||
abstract class Range extends Expr::Range {
|
||||
abstract string getValueText();
|
||||
|
||||
override string toString() { result = this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module NumericLiteral {
|
||||
abstract class Range extends Literal::Range { }
|
||||
}
|
||||
|
||||
module IntegerLiteral {
|
||||
class Range extends NumericLiteral::Range, @token_integer {
|
||||
final override Generated::Integer generated;
|
||||
|
||||
Range() { not any(Generated::Rational r).getChild() = this }
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module FloatLiteral {
|
||||
class Range extends NumericLiteral::Range, @token_float {
|
||||
final override Generated::Float generated;
|
||||
|
||||
Range() { not any(Generated::Rational r).getChild() = this }
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module RationalLiteral {
|
||||
class Range extends NumericLiteral::Range, @rational {
|
||||
final override Generated::Rational generated;
|
||||
|
||||
final override string getValueText() {
|
||||
result = generated.getChild().(Generated::Token).getValue() + "r"
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module ComplexLiteral {
|
||||
class Range extends NumericLiteral::Range, @token_complex {
|
||||
final override Generated::Complex generated;
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module NilLiteral {
|
||||
class Range extends Literal::Range, @token_nil {
|
||||
final override Generated::Nil generated;
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module BooleanLiteral {
|
||||
class DbUnion = @token_true or @token_false;
|
||||
|
||||
class Range extends Literal::Range, DbUnion {
|
||||
final override Generated::Token generated;
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getValueText() }
|
||||
|
||||
predicate isTrue() { this instanceof @token_true }
|
||||
|
||||
predicate isFalse() { this instanceof @token_false }
|
||||
}
|
||||
}
|
||||
|
||||
module StringComponent {
|
||||
abstract class Range extends AstNode::Range {
|
||||
abstract string getValueText();
|
||||
}
|
||||
}
|
||||
|
||||
module StringTextComponent {
|
||||
class StringContentToken = @token_string_content or @token_heredoc_content;
|
||||
|
||||
class Range extends StringComponent::Range, StringContentToken {
|
||||
final override Generated::Token generated;
|
||||
|
||||
final override string toString() { result = generated.getValue() }
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
module StringEscapeSequenceComponent {
|
||||
class Range extends StringComponent::Range, @token_escape_sequence {
|
||||
final override Generated::EscapeSequence generated;
|
||||
|
||||
final override string toString() { result = generated.getValue() }
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
module StringInterpolationComponent {
|
||||
class Range extends StringComponent::Range, StmtSequence::Range, @interpolation {
|
||||
final override Generated::Interpolation generated;
|
||||
|
||||
final override string toString() { result = "#{...}" }
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string getValueText() { none() }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
StmtSequence::Range.super.child(label, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module StringlikeLiteral {
|
||||
abstract class Range extends Literal::Range {
|
||||
abstract StringComponent::Range getComponent(int i);
|
||||
|
||||
string getStartDelimiter() { result = "" }
|
||||
|
||||
string getEndDelimiter() { result = "" }
|
||||
|
||||
final predicate isSimple() { count(this.getComponent(_)) <= 1 }
|
||||
|
||||
override string getValueText() {
|
||||
// 0 components should result in the empty string
|
||||
// if there are any interpolations, there should be no result
|
||||
// otherwise, concatenate all the components
|
||||
forall(StringComponent c | c = this.getComponent(_) |
|
||||
not c instanceof StringInterpolationComponent::Range
|
||||
) and
|
||||
result =
|
||||
concat(StringComponent::Range c, int i |
|
||||
c = this.getComponent(i)
|
||||
|
|
||||
c.getValueText() order by i
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(string full, string summary |
|
||||
full =
|
||||
concat(StringComponent::Range c, int i, string s |
|
||||
c = this.getComponent(i) and
|
||||
if c instanceof Generated::Token
|
||||
then s = c.(Generated::Token).getValue()
|
||||
else s = "#{...}"
|
||||
|
|
||||
s order by i
|
||||
) and
|
||||
(
|
||||
// summary should be 32 chars max (incl. ellipsis)
|
||||
full.length() > 32 and summary = full.substring(0, 29) + "..."
|
||||
or
|
||||
full.length() <= 32 and summary = full
|
||||
) and
|
||||
result = this.getStartDelimiter() + summary + this.getEndDelimiter()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getComponent" and child = getComponent(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module StringLiteral {
|
||||
abstract class Range extends StringlikeLiteral::Range {
|
||||
final override string getStartDelimiter() { result = "\"" }
|
||||
|
||||
final override string getEndDelimiter() { result = "\"" }
|
||||
}
|
||||
|
||||
private class RegularStringRange extends StringLiteral::Range, @string__ {
|
||||
final override Generated::String generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
|
||||
private class BareStringRange extends StringLiteral::Range, @bare_string {
|
||||
final override Generated::BareString generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
}
|
||||
|
||||
module RegexLiteral {
|
||||
class Range extends StringlikeLiteral::Range, @regex {
|
||||
final override Generated::Regex generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string getStartDelimiter() { result = "/" }
|
||||
|
||||
final override string getEndDelimiter() { result = "/" }
|
||||
|
||||
final string getFlagString() {
|
||||
// For `/foo/i`, there should be an `/i` token in the database with `this`
|
||||
// as its parents. Strip the delimiter, which can vary.
|
||||
result =
|
||||
max(Generated::Token t |
|
||||
t.getParent() = this
|
||||
|
|
||||
t.getValue().suffix(1) order by t.getParentIndex()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module SymbolLiteral {
|
||||
abstract class Range extends StringlikeLiteral::Range { }
|
||||
|
||||
class SimpleSymbolRange extends SymbolLiteral::Range {
|
||||
final override Generated::SimpleSymbol generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { none() }
|
||||
|
||||
final override string getStartDelimiter() { result = ":" }
|
||||
|
||||
// Tree-sitter gives us value text including the colon, which we skip.
|
||||
final override string getValueText() { result = generated.getValue().suffix(1) }
|
||||
|
||||
final override string toString() { result = generated.getValue() }
|
||||
}
|
||||
|
||||
abstract private class ComplexSymbolRange extends SymbolLiteral::Range {
|
||||
final override string getStartDelimiter() { result = ":\"" }
|
||||
|
||||
final override string getEndDelimiter() { result = "\"" }
|
||||
}
|
||||
|
||||
class DelimitedSymbolRange extends ComplexSymbolRange, @delimited_symbol {
|
||||
final override Generated::DelimitedSymbol generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
|
||||
class BareSymbolRange extends ComplexSymbolRange, @bare_symbol {
|
||||
final override Generated::BareSymbol generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
|
||||
class HashKeySymbolRange extends SymbolLiteral::Range, @token_hash_key_symbol {
|
||||
final override Generated::HashKeySymbol generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { none() }
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = ":" + this.getValueText() }
|
||||
}
|
||||
}
|
||||
|
||||
module SubshellLiteral {
|
||||
class Range extends StringlikeLiteral::Range, @subshell {
|
||||
final override Generated::Subshell generated;
|
||||
|
||||
final override StringComponent::Range getComponent(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string getStartDelimiter() { result = "`" }
|
||||
|
||||
final override string getEndDelimiter() { result = "`" }
|
||||
}
|
||||
}
|
||||
|
||||
module CharacterLiteral {
|
||||
class Range extends Literal::Range, @token_character {
|
||||
final override Generated::Character generated;
|
||||
|
||||
final override string getValueText() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = generated.getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
module HereDoc {
|
||||
private Generated::HeredocBody heredoc(Generated::HeredocBeginning start) {
|
||||
exists(int i, File f |
|
||||
start =
|
||||
rank[i](Generated::HeredocBeginning b |
|
||||
f = b.getLocation().getFile()
|
||||
|
|
||||
b order by b.getLocation().getStartLine(), b.getLocation().getStartColumn()
|
||||
) and
|
||||
result =
|
||||
rank[i](Generated::HeredocBody b |
|
||||
f = b.getLocation().getFile()
|
||||
|
|
||||
b order by b.getLocation().getStartLine(), b.getLocation().getStartColumn()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
class Range extends StringlikeLiteral::Range, @token_heredoc_beginning {
|
||||
final override Generated::HeredocBeginning generated;
|
||||
private Generated::HeredocBody body;
|
||||
|
||||
Range() { body = heredoc(this) }
|
||||
|
||||
final override StringComponent::Range getComponent(int n) { result = body.getChild(n) }
|
||||
|
||||
final string getQuoteStyle() {
|
||||
exists(string s |
|
||||
s = generated.getValue() and
|
||||
s.charAt(s.length() - 1) = result and
|
||||
result = ["'", "`", "\""]
|
||||
)
|
||||
}
|
||||
|
||||
final string getIndentationModifier() {
|
||||
exists(string s |
|
||||
s = generated.getValue() and
|
||||
s.charAt(2) = result and
|
||||
result = ["-", "~"]
|
||||
)
|
||||
}
|
||||
|
||||
final override string toString() { result = generated.getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
module ArrayLiteral {
|
||||
abstract class Range extends Literal::Range {
|
||||
final override string getValueText() { none() }
|
||||
|
||||
abstract Expr getElement(int i);
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getElement" and child = getElement(_)
|
||||
}
|
||||
}
|
||||
|
||||
private class RegularArrayRange extends ArrayLiteral::Range, @array {
|
||||
final override Generated::Array generated;
|
||||
|
||||
final override Expr getElement(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = "[...]" }
|
||||
}
|
||||
|
||||
private class StringArrayRange extends ArrayLiteral::Range, @string_array {
|
||||
final override Generated::StringArray generated;
|
||||
|
||||
final override Expr getElement(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = "%w(...)" }
|
||||
}
|
||||
|
||||
private class SymbolArrayRange extends ArrayLiteral::Range, @symbol_array {
|
||||
final override Generated::SymbolArray generated;
|
||||
|
||||
final override Expr getElement(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = "%i(...)" }
|
||||
}
|
||||
}
|
||||
|
||||
module HashLiteral {
|
||||
class Range extends Literal::Range, @hash {
|
||||
final override Generated::Hash generated;
|
||||
|
||||
final override string getValueText() { none() }
|
||||
|
||||
final Expr getElement(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = "{...}" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getElement" and child = getElement(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module RangeLiteral {
|
||||
class Range extends Literal::Range, @range {
|
||||
final override Generated::Range generated;
|
||||
|
||||
final override string getValueText() { none() }
|
||||
|
||||
final override string toString() { result = "_ " + generated.getOperator() + " _" }
|
||||
|
||||
final Expr getBegin() { result = generated.getBegin() }
|
||||
|
||||
final Expr getEnd() { result = generated.getEnd() }
|
||||
|
||||
final predicate isInclusive() { this instanceof @range_dotdot }
|
||||
|
||||
final predicate isExclusive() { this instanceof @range_dotdotdot }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getBegin" and child = getBegin()
|
||||
or
|
||||
label = "getEnd" and child = getEnd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module MethodName {
|
||||
private class TokenTypes =
|
||||
@setter or @token_class_variable or @token_constant or @token_global_variable or
|
||||
@token_identifier or @token_instance_variable or @token_operator;
|
||||
|
||||
abstract class Range extends Literal::Range, @underscore_method_name {
|
||||
Range() {
|
||||
exists(Generated::Undef u | u.getChild(_) = generated)
|
||||
or
|
||||
exists(Generated::Alias a | a.getName() = generated or a.getAlias() = generated)
|
||||
}
|
||||
}
|
||||
|
||||
private class TokenMethodName extends MethodName::Range, TokenTypes {
|
||||
final override Generated::UnderscoreMethodName generated;
|
||||
|
||||
final override string getValueText() {
|
||||
result = generated.(Generated::Token).getValue()
|
||||
or
|
||||
result = generated.(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
}
|
||||
|
||||
private class SimpleSymbolMethodName extends MethodName::Range, SymbolLiteral::SimpleSymbolRange,
|
||||
@token_simple_symbol { }
|
||||
|
||||
private class DelimitedSymbolMethodName extends MethodName::Range,
|
||||
SymbolLiteral::DelimitedSymbolRange, @delimited_symbol { }
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Parameter
|
||||
private import codeql_ruby.ast.internal.Scope
|
||||
private import TreeSitter
|
||||
|
||||
module Callable {
|
||||
abstract class Range extends Expr::Range {
|
||||
abstract Parameter::Range getParameter(int n);
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getParameter" and child = getParameter(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module MethodBase {
|
||||
abstract class Range extends Callable::Range, BodyStatement::Range, Scope::Range {
|
||||
abstract string getName();
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Callable::Range.super.child(label, child) or BodyStatement::Range.super.child(label, child)
|
||||
}
|
||||
|
||||
override string toString() { result = BodyStatement::Range.super.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
module Method {
|
||||
class Range extends MethodBase::Range, @method {
|
||||
final override Generated::Method generated;
|
||||
|
||||
override Parameter::Range getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
|
||||
override string getName() {
|
||||
result = generated.getName().(Generated::Token).getValue() or
|
||||
result = generated.getName().(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
|
||||
final predicate isSetter() { generated.getName() instanceof Generated::Setter }
|
||||
|
||||
final override Generated::AstNode getChild(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
}
|
||||
}
|
||||
|
||||
module SingletonMethod {
|
||||
class Range extends MethodBase::Range, @singleton_method {
|
||||
final override Generated::SingletonMethod generated;
|
||||
|
||||
override Parameter::Range getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
|
||||
override string getName() {
|
||||
result = generated.getName().(Generated::Token).getValue() or
|
||||
result = generated.getName().(SymbolLiteral).getValueText() or
|
||||
result = generated.getName().(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
|
||||
final Generated::AstNode getObject() { result = generated.getObject() }
|
||||
|
||||
final override Generated::AstNode getChild(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
MethodBase::Range.super.child(label, child)
|
||||
or
|
||||
label = "getObject" and child = getObject()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Lambda {
|
||||
class Range extends Callable::Range, BodyStatement::Range, @lambda {
|
||||
final override Generated::Lambda generated;
|
||||
|
||||
final override Parameter::Range getParameter(int n) {
|
||||
result = generated.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override Generated::AstNode getChild(int i) {
|
||||
result = generated.getBody().(Generated::DoBlock).getChild(i) or
|
||||
result = generated.getBody().(Generated::Block).getChild(i)
|
||||
}
|
||||
|
||||
final override string toString() { result = "-> { ... }" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Callable::Range.super.child(label, child)
|
||||
or
|
||||
BodyStatement::Range.super.child(label, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Block {
|
||||
abstract class Range extends Callable::Range, StmtSequence::Range, Scope::Range {
|
||||
Range() { not generated.getParent() instanceof Generated::Lambda }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Callable::Range.super.child(label, child)
|
||||
or
|
||||
StmtSequence::Range.super.child(label, child)
|
||||
}
|
||||
|
||||
override string toString() { result = StmtSequence::Range.super.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
module DoBlock {
|
||||
class Range extends Block::Range, BodyStatement::Range, @do_block {
|
||||
final override Generated::DoBlock generated;
|
||||
|
||||
final override Generated::AstNode getChild(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override Parameter::Range getParameter(int n) {
|
||||
result = generated.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override string toString() { result = "do ... end" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Block::Range.super.child(label, child)
|
||||
or
|
||||
BodyStatement::Range.super.child(label, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module BraceBlock {
|
||||
class Range extends Block::Range, @block {
|
||||
final override Generated::Block generated;
|
||||
|
||||
final override Parameter::Range getParameter(int n) {
|
||||
result = generated.getParameters().getChild(n)
|
||||
}
|
||||
|
||||
final override Stmt getStmt(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string toString() { result = "{ ... }" }
|
||||
}
|
||||
}
|
||||
@@ -1,132 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Constant
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Scope
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
module ModuleBase {
|
||||
abstract class Range extends BodyStatement::Range, Scope::Range {
|
||||
override string toString() { result = BodyStatement::Range.super.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
module Namespace {
|
||||
abstract class Range extends ModuleBase::Range, ConstantWriteAccess::Range {
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ModuleBase::Range.super.child(label, child) or
|
||||
ConstantWriteAccess::Range.super.child(label, child)
|
||||
}
|
||||
|
||||
override string toString() { result = ModuleBase::Range.super.toString() }
|
||||
}
|
||||
}
|
||||
|
||||
module Toplevel {
|
||||
class Range extends ModuleBase::Range, @program {
|
||||
final override Generated::Program generated;
|
||||
|
||||
Range() { generated.getLocation().getFile().getExtension() != "erb" }
|
||||
|
||||
final override Generated::AstNode getChild(int i) {
|
||||
result = generated.getChild(i) and
|
||||
not result instanceof Generated::BeginBlock
|
||||
}
|
||||
|
||||
final StmtSequence getBeginBlock(int n) {
|
||||
result = rank[n](int i, Generated::BeginBlock b | b = generated.getChild(i) | b order by i)
|
||||
}
|
||||
|
||||
final override string toString() { result = generated.getLocation().getFile().getBaseName() }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ModuleBase::Range.super.child(label, child)
|
||||
or
|
||||
label = "getBeginBlock" and child = getBeginBlock(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Class {
|
||||
class Range extends Namespace::Range, @class {
|
||||
final override Generated::Class generated;
|
||||
|
||||
final override Generated::AstNode getChild(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string getName() {
|
||||
result = generated.getName().(Generated::Token).getValue() or
|
||||
result =
|
||||
generated.getName().(Generated::ScopeResolution).getName().(Generated::Token).getValue()
|
||||
}
|
||||
|
||||
final override Expr::Range getScopeExpr() {
|
||||
result = generated.getName().(Generated::ScopeResolution).getScope()
|
||||
}
|
||||
|
||||
final override predicate hasGlobalScope() {
|
||||
exists(Generated::ScopeResolution sr |
|
||||
sr = generated.getName() and
|
||||
not exists(sr.getScope())
|
||||
)
|
||||
}
|
||||
|
||||
final Expr getSuperclassExpr() { result = generated.getSuperclass().getChild() }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Namespace::Range.super.child(label, child)
|
||||
or
|
||||
label = "getSuperclassExpr" and child = getSuperclassExpr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module SingletonClass {
|
||||
class Range extends ModuleBase::Range, @singleton_class {
|
||||
final override Generated::SingletonClass generated;
|
||||
|
||||
final override Generated::AstNode getChild(int i) { result = generated.getChild(i) }
|
||||
|
||||
final Expr getValue() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = "class << ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ModuleBase::Range.super.child(label, child)
|
||||
or
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module Module {
|
||||
class Range extends Namespace::Range, @module {
|
||||
final override Generated::Module generated;
|
||||
|
||||
final override Generated::AstNode getChild(int i) { result = generated.getChild(i) }
|
||||
|
||||
final override string getName() {
|
||||
result = generated.getName().(Generated::Token).getValue() or
|
||||
result =
|
||||
generated.getName().(Generated::ScopeResolution).getName().(Generated::Token).getValue()
|
||||
}
|
||||
|
||||
final override Expr::Range getScopeExpr() {
|
||||
result = generated.getName().(Generated::ScopeResolution).getScope()
|
||||
}
|
||||
|
||||
final override predicate hasGlobalScope() {
|
||||
exists(Generated::ScopeResolution sr |
|
||||
sr = generated.getName() and
|
||||
not exists(sr.getScope())
|
||||
)
|
||||
}
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Namespace::Range.super.child(label, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,355 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
|
||||
module Operation {
|
||||
abstract class Range extends Expr::Range {
|
||||
abstract string getOperator();
|
||||
|
||||
abstract Stmt getAnOperand();
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getAnOperand" and child = getAnOperand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module UnaryOperation {
|
||||
abstract class Range extends Operation::Range, @unary {
|
||||
final override Generated::Unary generated;
|
||||
|
||||
final override string getOperator() { result = generated.getOperator() }
|
||||
|
||||
Expr getOperand() { result = generated.getOperand() }
|
||||
|
||||
final override Expr getAnOperand() { result = this.getOperand() }
|
||||
|
||||
override string toString() { result = this.getOperator() + " ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Operation::Range.super.child(label, child)
|
||||
or
|
||||
label = "getOperand" and child = getOperand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module UnaryLogicalOperation {
|
||||
abstract class Range extends UnaryOperation::Range { }
|
||||
}
|
||||
|
||||
module UnaryArithmeticOperation {
|
||||
abstract class Range extends UnaryOperation::Range { }
|
||||
}
|
||||
|
||||
module UnaryBitwiseOperation {
|
||||
abstract class Range extends UnaryOperation::Range { }
|
||||
}
|
||||
|
||||
module NotExpr {
|
||||
class DbUnion = @unary_bang or @unary_not;
|
||||
|
||||
class Range extends UnaryLogicalOperation::Range, DbUnion { }
|
||||
}
|
||||
|
||||
module UnaryPlusExpr {
|
||||
class Range extends UnaryArithmeticOperation::Range, @unary_plus { }
|
||||
}
|
||||
|
||||
module UnaryMinusExpr {
|
||||
class Range extends UnaryArithmeticOperation::Range, @unary_minus { }
|
||||
}
|
||||
|
||||
module ComplementExpr {
|
||||
class Range extends UnaryBitwiseOperation::Range, @unary_tilde { }
|
||||
}
|
||||
|
||||
module DefinedExpr {
|
||||
class Range extends UnaryOperation::Range, @unary_definedquestion { }
|
||||
}
|
||||
|
||||
module BinaryOperation {
|
||||
abstract class Range extends Operation::Range, @binary {
|
||||
final override Generated::Binary generated;
|
||||
|
||||
final override string getOperator() { result = generated.getOperator() }
|
||||
|
||||
final Expr getLeftOperand() { result = generated.getLeft() }
|
||||
|
||||
final Stmt getRightOperand() { result = generated.getRight() }
|
||||
|
||||
final override Stmt getAnOperand() {
|
||||
result = this.getLeftOperand() or result = this.getRightOperand()
|
||||
}
|
||||
|
||||
override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Operation::Range.super.child(label, child)
|
||||
or
|
||||
label = "getLeftOperand" and child = getLeftOperand()
|
||||
or
|
||||
label = "getRightOperand" and child = getRightOperand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module BinaryArithmeticOperation {
|
||||
abstract class Range extends BinaryOperation::Range { }
|
||||
}
|
||||
|
||||
module BinaryLogicalOperation {
|
||||
abstract class Range extends BinaryOperation::Range { }
|
||||
}
|
||||
|
||||
module BinaryBitwiseOperation {
|
||||
abstract class Range extends BinaryOperation::Range { }
|
||||
}
|
||||
|
||||
module ComparisonOperation {
|
||||
abstract class Range extends BinaryOperation::Range, @binary { }
|
||||
}
|
||||
|
||||
module AddExpr {
|
||||
class Range extends BinaryArithmeticOperation::Range, @binary_plus { }
|
||||
}
|
||||
|
||||
module SubExpr {
|
||||
class Range extends BinaryArithmeticOperation::Range, @binary_minus { }
|
||||
}
|
||||
|
||||
module MulExpr {
|
||||
class Range extends BinaryArithmeticOperation::Range, @binary_star { }
|
||||
}
|
||||
|
||||
module DivExpr {
|
||||
class Range extends BinaryArithmeticOperation::Range, @binary_slash { }
|
||||
}
|
||||
|
||||
module ModuloExpr {
|
||||
class Range extends BinaryArithmeticOperation::Range, @binary_percent { }
|
||||
}
|
||||
|
||||
module ExponentExpr {
|
||||
class Range extends BinaryArithmeticOperation::Range, @binary_starstar { }
|
||||
}
|
||||
|
||||
module LogicalAndExpr {
|
||||
class DbUnion = @binary_and or @binary_ampersandampersand;
|
||||
|
||||
class Range extends BinaryLogicalOperation::Range, DbUnion { }
|
||||
}
|
||||
|
||||
module LogicalOrExpr {
|
||||
class DbUnion = @binary_or or @binary_pipepipe;
|
||||
|
||||
class Range extends BinaryLogicalOperation::Range, DbUnion { }
|
||||
}
|
||||
|
||||
module LShiftExpr {
|
||||
class Range extends BinaryBitwiseOperation::Range, @binary_langlelangle { }
|
||||
}
|
||||
|
||||
module RShiftExpr {
|
||||
class Range extends BinaryBitwiseOperation::Range, @binary_ranglerangle { }
|
||||
}
|
||||
|
||||
module BitwiseAndExpr {
|
||||
class Range extends BinaryBitwiseOperation::Range, @binary_ampersand { }
|
||||
}
|
||||
|
||||
module BitwiseOrExpr {
|
||||
class Range extends BinaryBitwiseOperation::Range, @binary_pipe { }
|
||||
}
|
||||
|
||||
module BitwiseXorExpr {
|
||||
class Range extends BinaryBitwiseOperation::Range, @binary_caret { }
|
||||
}
|
||||
|
||||
module EqualityOperation {
|
||||
abstract class Range extends ComparisonOperation::Range { }
|
||||
}
|
||||
|
||||
module EqExpr {
|
||||
class Range extends EqualityOperation::Range, @binary_equalequal { }
|
||||
}
|
||||
|
||||
module NEExpr {
|
||||
class Range extends EqualityOperation::Range, @binary_bangequal { }
|
||||
}
|
||||
|
||||
module CaseEqExpr {
|
||||
class Range extends EqualityOperation::Range, @binary_equalequalequal { }
|
||||
}
|
||||
|
||||
module RelationalOperation {
|
||||
abstract class Range extends ComparisonOperation::Range {
|
||||
abstract Expr getGreaterOperand();
|
||||
|
||||
abstract Expr getLesserOperand();
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
ComparisonOperation::Range.super.child(label, child)
|
||||
or
|
||||
label = "getGreaterOperand" and child = getGreaterOperand()
|
||||
or
|
||||
label = "getLesserOperand" and child = getLesserOperand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module GTExpr {
|
||||
class Range extends RelationalOperation::Range, @binary_rangle {
|
||||
final override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
}
|
||||
}
|
||||
|
||||
module GEExpr {
|
||||
class Range extends RelationalOperation::Range, @binary_rangleequal {
|
||||
final override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
}
|
||||
}
|
||||
|
||||
module LTExpr {
|
||||
class Range extends RelationalOperation::Range, @binary_langle {
|
||||
final override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
}
|
||||
}
|
||||
|
||||
module LEExpr {
|
||||
class Range extends RelationalOperation::Range, @binary_langleequal {
|
||||
final override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
final override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
}
|
||||
}
|
||||
|
||||
module SpaceshipExpr {
|
||||
class Range extends BinaryOperation::Range, @binary_langleequalrangle { }
|
||||
}
|
||||
|
||||
module RegexMatchExpr {
|
||||
class Range extends BinaryOperation::Range, @binary_equaltilde { }
|
||||
}
|
||||
|
||||
module NoRegexMatchExpr {
|
||||
class Range extends BinaryOperation::Range, @binary_bangtilde { }
|
||||
}
|
||||
|
||||
module Assignment {
|
||||
abstract class Range extends Operation::Range {
|
||||
abstract Pattern getLeftOperand();
|
||||
|
||||
abstract Expr getRightOperand();
|
||||
|
||||
final override Expr getAnOperand() {
|
||||
result = this.getLeftOperand() or result = this.getRightOperand()
|
||||
}
|
||||
|
||||
override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
Operation::Range.super.child(label, child)
|
||||
or
|
||||
label = "getLeftOperand" and child = getLeftOperand()
|
||||
or
|
||||
label = "getRightOperand" and child = getRightOperand()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module AssignExpr {
|
||||
class Range extends Assignment::Range, @assignment {
|
||||
final override Generated::Assignment generated;
|
||||
|
||||
final override Pattern getLeftOperand() { result = generated.getLeft() }
|
||||
|
||||
final override Expr getRightOperand() { result = generated.getRight() }
|
||||
|
||||
final override string getOperator() { result = "=" }
|
||||
}
|
||||
}
|
||||
|
||||
module AssignOperation {
|
||||
abstract class Range extends Assignment::Range, @operator_assignment {
|
||||
final override Generated::OperatorAssignment generated;
|
||||
|
||||
final override string getOperator() { result = generated.getOperator() }
|
||||
|
||||
final override LhsExpr getLeftOperand() { result = generated.getLeft() }
|
||||
|
||||
final override Expr getRightOperand() { result = generated.getRight() }
|
||||
}
|
||||
}
|
||||
|
||||
module AssignArithmeticOperation {
|
||||
abstract class Range extends AssignOperation::Range { }
|
||||
}
|
||||
|
||||
module AssignLogicalOperation {
|
||||
abstract class Range extends AssignOperation::Range { }
|
||||
}
|
||||
|
||||
module AssignBitwiseOperation {
|
||||
abstract class Range extends AssignOperation::Range { }
|
||||
}
|
||||
|
||||
module AssignAddExpr {
|
||||
class Range extends AssignArithmeticOperation::Range, @operator_assignment_plusequal { }
|
||||
}
|
||||
|
||||
module AssignSubExpr {
|
||||
class Range extends AssignArithmeticOperation::Range, @operator_assignment_minusequal { }
|
||||
}
|
||||
|
||||
module AssignMulExpr {
|
||||
class Range extends AssignArithmeticOperation::Range, @operator_assignment_starequal { }
|
||||
}
|
||||
|
||||
module AssignDivExpr {
|
||||
class Range extends AssignArithmeticOperation::Range, @operator_assignment_slashequal { }
|
||||
}
|
||||
|
||||
module AssignExponentExpr {
|
||||
class Range extends AssignArithmeticOperation::Range, @operator_assignment_starstarequal { }
|
||||
}
|
||||
|
||||
module AssignModuloExpr {
|
||||
class Range extends AssignArithmeticOperation::Range, @operator_assignment_percentequal { }
|
||||
}
|
||||
|
||||
module AssignLogicalAndExpr {
|
||||
class Range extends AssignLogicalOperation::Range, @operator_assignment_ampersandampersandequal {
|
||||
}
|
||||
}
|
||||
|
||||
module AssignLogicalOrExpr {
|
||||
class Range extends AssignLogicalOperation::Range, @operator_assignment_pipepipeequal { }
|
||||
}
|
||||
|
||||
module AssignLShiftExpr {
|
||||
class Range extends AssignBitwiseOperation::Range, @operator_assignment_langlelangleequal { }
|
||||
}
|
||||
|
||||
module AssignRShiftExpr {
|
||||
class Range extends AssignBitwiseOperation::Range, @operator_assignment_ranglerangleequal { }
|
||||
}
|
||||
|
||||
module AssignBitwiseAndExpr {
|
||||
class Range extends AssignBitwiseOperation::Range, @operator_assignment_ampersandequal { }
|
||||
}
|
||||
|
||||
module AssignBitwiseOrExpr {
|
||||
class Range extends AssignBitwiseOperation::Range, @operator_assignment_pipeequal { }
|
||||
}
|
||||
|
||||
module AssignBitwiseXorExpr {
|
||||
class Range extends AssignBitwiseOperation::Range, @operator_assignment_caretequal { }
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
private import codeql_ruby.AST
|
||||
private import AST
|
||||
private import TreeSitter
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Variable
|
||||
private import codeql_ruby.ast.internal.Method
|
||||
private import codeql_ruby.ast.internal.Pattern
|
||||
private import codeql.Locations
|
||||
|
||||
module Parameter {
|
||||
class Range extends AstNode::Range {
|
||||
class Range extends Generated::AstNode {
|
||||
private int pos;
|
||||
|
||||
Range() {
|
||||
@@ -19,143 +14,6 @@ module Parameter {
|
||||
this = any(Generated::LambdaParameters lp).getChild(pos)
|
||||
}
|
||||
|
||||
final int getPosition() { result = pos }
|
||||
|
||||
LocalVariable getAVariable() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module NamedParameter {
|
||||
abstract class Range extends Parameter::Range {
|
||||
abstract string getName();
|
||||
|
||||
abstract LocalVariable getVariable();
|
||||
|
||||
override LocalVariable getAVariable() { result = this.getVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
module SimpleParameter {
|
||||
class Range extends NamedParameter::Range, PatternParameter::Range, VariablePattern::Range {
|
||||
final override string getName() { result = this.getVariableName() }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariable(_, _, this) }
|
||||
|
||||
final override LocalVariable getAVariable() { result = this.getVariable() }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
}
|
||||
}
|
||||
|
||||
module PatternParameter {
|
||||
class Range extends Parameter::Range, Pattern::Range {
|
||||
override LocalVariable getAVariable() { result = this.(Pattern::Range).getAVariable() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module TuplePatternParameter {
|
||||
class Range extends PatternParameter::Range, TuplePattern::Range {
|
||||
override LocalVariable getAVariable() { result = TuplePattern::Range.super.getAVariable() }
|
||||
|
||||
override string toString() { result = TuplePattern::Range.super.toString() }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
PatternParameter::Range.super.child(label, child) or
|
||||
TuplePattern::Range.super.child(label, child)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module BlockParameter {
|
||||
class Range extends NamedParameter::Range, @block_parameter {
|
||||
final override Generated::BlockParameter generated;
|
||||
|
||||
final override string getName() { result = generated.getName().getValue() }
|
||||
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariable(_, _, generated.getName())
|
||||
}
|
||||
|
||||
final override string toString() { result = "&" + this.getName() }
|
||||
}
|
||||
}
|
||||
|
||||
module HashSplatParameter {
|
||||
class Range extends NamedParameter::Range, @hash_splat_parameter {
|
||||
final override Generated::HashSplatParameter generated;
|
||||
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariable(_, _, generated.getName())
|
||||
}
|
||||
|
||||
final override string toString() { result = "**" + this.getName() }
|
||||
|
||||
final override string getName() { result = generated.getName().getValue() }
|
||||
}
|
||||
}
|
||||
|
||||
module KeywordParameter {
|
||||
class Range extends NamedParameter::Range, @keyword_parameter {
|
||||
final override Generated::KeywordParameter generated;
|
||||
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariable(_, _, generated.getName())
|
||||
}
|
||||
|
||||
final Expr::Range getDefaultValue() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
final override string getName() { result = generated.getName().getValue() }
|
||||
|
||||
final override Location getLocation() { result = generated.getName().getLocation() }
|
||||
|
||||
final override predicate child(string label, AstNode::Range child) {
|
||||
NamedParameter::Range.super.child(label, child)
|
||||
or
|
||||
label = "getDefaultValue" and child = getDefaultValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module OptionalParameter {
|
||||
class Range extends NamedParameter::Range, @optional_parameter {
|
||||
final override Generated::OptionalParameter generated;
|
||||
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariable(_, _, generated.getName())
|
||||
}
|
||||
|
||||
final Expr::Range getDefaultValue() { result = generated.getValue() }
|
||||
|
||||
final override string toString() { result = this.getName() }
|
||||
|
||||
final override string getName() { result = generated.getName().getValue() }
|
||||
|
||||
final override Location getLocation() { result = generated.getName().getLocation() }
|
||||
|
||||
final override predicate child(string label, AstNode::Range child) {
|
||||
NamedParameter::Range.super.child(label, child)
|
||||
or
|
||||
label = "getDefaultValue" and child = getDefaultValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module SplatParameter {
|
||||
class Range extends NamedParameter::Range, @splat_parameter {
|
||||
final override Generated::SplatParameter generated;
|
||||
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariable(_, _, generated.getName())
|
||||
}
|
||||
|
||||
final override string toString() { result = "*" + this.getName() }
|
||||
|
||||
final override string getName() { result = generated.getName().getValue() }
|
||||
int getPosition() { result = pos }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import TreeSitter
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Variable
|
||||
private import codeql_ruby.ast.internal.Method
|
||||
private import codeql.Locations
|
||||
|
||||
/**
|
||||
* Holds if `n` is in the left-hand-side of an explicit assignment `assignment`.
|
||||
*/
|
||||
predicate explicitAssignmentNode(Generated::AstNode n, Generated::AstNode assignment) {
|
||||
n = assignment.(Generated::Assignment).getLeft()
|
||||
or
|
||||
n = assignment.(Generated::OperatorAssignment).getLeft()
|
||||
or
|
||||
exists(Generated::AstNode parent |
|
||||
parent = n.getParent() and
|
||||
explicitAssignmentNode(parent, assignment)
|
||||
|
|
||||
parent instanceof Generated::DestructuredLeftAssignment
|
||||
or
|
||||
parent instanceof Generated::LeftAssignmentList
|
||||
or
|
||||
parent instanceof Generated::RestAssignment
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` is inside an implicit assignment. */
|
||||
predicate implicitAssignmentNode(Generated::AstNode n) {
|
||||
n = any(Generated::ExceptionVariable ev).getChild()
|
||||
or
|
||||
n = any(Generated::For for).getPattern()
|
||||
or
|
||||
implicitAssignmentNode(n.getParent())
|
||||
}
|
||||
|
||||
/** Holds if `n` is inside a parameter. */
|
||||
predicate implicitParameterAssignmentNode(Generated::AstNode n, Callable::Range c) {
|
||||
n = c.getParameter(_)
|
||||
or
|
||||
implicitParameterAssignmentNode(n.getParent().(Generated::DestructuredParameter), c)
|
||||
}
|
||||
|
||||
module Pattern {
|
||||
abstract class Range extends AstNode::Range {
|
||||
cached
|
||||
Range() {
|
||||
explicitAssignmentNode(this, _)
|
||||
or
|
||||
implicitAssignmentNode(this)
|
||||
or
|
||||
implicitParameterAssignmentNode(this, _)
|
||||
}
|
||||
|
||||
Variable getAVariable() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module LhsExpr {
|
||||
abstract class Range extends Pattern::Range, Expr::Range { }
|
||||
}
|
||||
|
||||
module VariablePattern {
|
||||
class VariableToken =
|
||||
@token_identifier or @token_instance_variable or @token_class_variable or @token_global_variable;
|
||||
|
||||
class Range extends LhsExpr::Range, VariableToken {
|
||||
override Generated::Token generated;
|
||||
|
||||
string getVariableName() { result = generated.getValue() }
|
||||
|
||||
override Variable getAVariable() { access(this, result) }
|
||||
|
||||
override string toString() { result = this.getVariableName() }
|
||||
}
|
||||
}
|
||||
|
||||
module TuplePattern {
|
||||
private class Range_ =
|
||||
@destructured_parameter or @destructured_left_assignment or @left_assignment_list;
|
||||
|
||||
class Range extends Pattern::Range, Range_ {
|
||||
Pattern::Range getElement(int i) {
|
||||
exists(Generated::AstNode c | c = getChild(i) |
|
||||
result = c.(Generated::RestAssignment).getChild()
|
||||
or
|
||||
not c instanceof Generated::RestAssignment and result = c
|
||||
)
|
||||
}
|
||||
|
||||
private Generated::AstNode getChild(int i) {
|
||||
result = this.(Generated::DestructuredParameter).getChild(i)
|
||||
or
|
||||
result = this.(Generated::DestructuredLeftAssignment).getChild(i)
|
||||
or
|
||||
result = this.(Generated::LeftAssignmentList).getChild(i)
|
||||
}
|
||||
|
||||
int getRestIndex() { result = unique(int i | getChild(i) instanceof Generated::RestAssignment) }
|
||||
|
||||
override Variable getAVariable() { result = this.getElement(_).getAVariable() }
|
||||
|
||||
override string toString() { result = "(..., ...)" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getElement" and child = getElement(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,19 @@
|
||||
private import TreeSitter
|
||||
private import codeql_ruby.ast.Scope
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Module
|
||||
private import codeql_ruby.ast.internal.Method
|
||||
private import codeql_ruby.ast.internal.Statement
|
||||
private import codeql_ruby.ast.internal.Parameter
|
||||
|
||||
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;
|
||||
|
||||
module Scope {
|
||||
class ScopeType = MethodLike or ModuleLike or BlockLike;
|
||||
class TypeRange = Callable::TypeRange or ModuleBase::TypeRange or @end_block;
|
||||
|
||||
class BlockLike = @do_block or @lambda or @block or @end_block;
|
||||
|
||||
class ModuleLike = @program or @module or @class or @singleton_class;
|
||||
|
||||
class MethodLike = @method or @singleton_method;
|
||||
|
||||
class Range extends AstNode::Range, ScopeType {
|
||||
Range() { not exists(Generated::Lambda l | l.getBody() = this) }
|
||||
|
||||
Generated::AstNode getADescendant() { this = scopeOf(result) }
|
||||
class Range extends Generated::AstNode, TypeRange {
|
||||
Range() { not this = any(Generated::Lambda l).getBody() }
|
||||
|
||||
ModuleBase::Range getEnclosingModule() {
|
||||
result = this
|
||||
@@ -32,19 +29,34 @@ module Scope {
|
||||
result = this.getOuterScope().getEnclosingMethod()
|
||||
}
|
||||
|
||||
Scope::Range getOuterScope() { result = scopeOf(this) }
|
||||
|
||||
override string toString() { none() }
|
||||
Range getOuterScope() { result = scopeOf(this) }
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets the enclosing scope of a node */
|
||||
private Scope::Range scopeOf(Generated::AstNode n) {
|
||||
exists(Generated::AstNode p | p = parentOf(n) |
|
||||
p instanceof Scope::Range and result = p
|
||||
or
|
||||
not p instanceof Scope::Range and result = scopeOf(p)
|
||||
)
|
||||
module MethodBase {
|
||||
class TypeRange = @method or @singleton_method;
|
||||
|
||||
class Range extends Scope::Range, TypeRange { }
|
||||
}
|
||||
|
||||
module Callable {
|
||||
class TypeRange = MethodBase::TypeRange or @do_block or @lambda or @block;
|
||||
|
||||
class Range extends Scope::Range, TypeRange {
|
||||
Parameter::Range getParameter(int i) {
|
||||
result = this.(Generated::Method).getParameters().getChild(i) or
|
||||
result = this.(Generated::SingletonMethod).getParameters().getChild(i) or
|
||||
result = this.(Generated::DoBlock).getParameters().getChild(i) or
|
||||
result = this.(Generated::Lambda).getParameters().getChild(i) or
|
||||
result = this.(Generated::Block).getParameters().getChild(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ModuleBase {
|
||||
class TypeRange = @program or @module or @class or @singleton_class;
|
||||
|
||||
class Range extends Scope::Range, TypeRange { }
|
||||
}
|
||||
|
||||
private Generated::AstNode parentOf(Generated::AstNode n) {
|
||||
@@ -61,3 +73,13 @@ private Generated::AstNode parentOf(Generated::AstNode n) {
|
||||
else result = parent
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the enclosing scope of a node */
|
||||
cached
|
||||
Scope::Range scopeOf(Generated::AstNode n) {
|
||||
exists(Generated::AstNode p | p = parentOf(n) |
|
||||
p = result
|
||||
or
|
||||
not p instanceof Scope::Range and result = scopeOf(p)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
|
||||
module Stmt {
|
||||
abstract class Range extends AstNode::Range { }
|
||||
}
|
||||
|
||||
module EmptyStmt {
|
||||
class Range extends Stmt::Range, @token_empty_statement {
|
||||
final override Generated::EmptyStatement generated;
|
||||
|
||||
final override string toString() { result = ";" }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) { none() }
|
||||
}
|
||||
}
|
||||
|
||||
module Begin {
|
||||
class Range extends BodyStatement::Range, @begin {
|
||||
final override Generated::Begin generated;
|
||||
|
||||
final override Generated::AstNode getChild(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() { result = "begin ... " }
|
||||
}
|
||||
}
|
||||
|
||||
module BeginBlock {
|
||||
class Range extends StmtSequence::Range, @begin_block {
|
||||
final override Generated::BeginBlock generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() { result = "BEGIN { ... }" }
|
||||
}
|
||||
}
|
||||
|
||||
module EndBlock {
|
||||
class Range extends StmtSequence::Range, @end_block {
|
||||
final override Generated::EndBlock generated;
|
||||
|
||||
final override Stmt getStmt(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() { result = "END { ... }" }
|
||||
}
|
||||
}
|
||||
|
||||
module UndefStmt {
|
||||
class Range extends Stmt::Range, @undef {
|
||||
final override Generated::Undef generated;
|
||||
|
||||
final MethodName getMethodName(int n) { result = generated.getChild(n) }
|
||||
|
||||
final override string toString() { result = "undef ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getMethodName" and child = getMethodName(_)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module AliasStmt {
|
||||
class Range extends Stmt::Range, @alias {
|
||||
final override Generated::Alias generated;
|
||||
|
||||
final MethodName getNewName() { result = generated.getName() }
|
||||
|
||||
final MethodName getOldName() { result = generated.getAlias() }
|
||||
|
||||
final override string toString() { result = "alias ..." }
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getNewName" and child = getNewName()
|
||||
or
|
||||
label = "getOldName" and child = getOldName()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ReturningStmt {
|
||||
abstract class Range extends Stmt::Range {
|
||||
abstract Generated::ArgumentList getArgumentList();
|
||||
|
||||
final Expr getValue() {
|
||||
exists(Generated::ArgumentList a, int c |
|
||||
a = this.getArgumentList() and c = count(a.getChild(_))
|
||||
|
|
||||
result = a.getChild(0) and c = 1
|
||||
or
|
||||
result = a and c > 1
|
||||
)
|
||||
}
|
||||
|
||||
override predicate child(string label, AstNode::Range child) {
|
||||
label = "getValue" and child = getValue()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module ReturnStmt {
|
||||
class Range extends ReturningStmt::Range, @return {
|
||||
final override Generated::Return generated;
|
||||
|
||||
final override string toString() { result = "return" }
|
||||
|
||||
final override Generated::ArgumentList getArgumentList() { result = generated.getChild() }
|
||||
}
|
||||
}
|
||||
|
||||
module BreakStmt {
|
||||
class Range extends ReturningStmt::Range, @break {
|
||||
final override Generated::Break generated;
|
||||
|
||||
final override string toString() { result = "break" }
|
||||
|
||||
final override Generated::ArgumentList getArgumentList() { result = generated.getChild() }
|
||||
}
|
||||
}
|
||||
|
||||
module NextStmt {
|
||||
class Range extends ReturningStmt::Range, @next {
|
||||
final override Generated::Next generated;
|
||||
|
||||
final override string toString() { result = "next" }
|
||||
|
||||
final override Generated::ArgumentList getArgumentList() { result = generated.getChild() }
|
||||
}
|
||||
}
|
||||
|
||||
module RedoStmt {
|
||||
class Range extends Stmt::Range, @redo {
|
||||
final override Generated::Redo generated;
|
||||
|
||||
final override string toString() { result = "redo" }
|
||||
}
|
||||
}
|
||||
|
||||
module RetryStmt {
|
||||
class Range extends Stmt::Range, @retry {
|
||||
final override Generated::Retry generated;
|
||||
|
||||
final override string toString() { result = "retry" }
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,45 @@ private import TreeSitter
|
||||
private import codeql.Locations
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.Expr
|
||||
private import codeql_ruby.ast.internal.Method
|
||||
private import codeql_ruby.ast.internal.Module
|
||||
private import codeql_ruby.ast.internal.Pattern
|
||||
private import codeql_ruby.ast.internal.Parameter
|
||||
private import codeql_ruby.ast.internal.Scope
|
||||
|
||||
/**
|
||||
* Holds if `n` is in the left-hand-side of an explicit assignment `assignment`.
|
||||
*/
|
||||
predicate explicitAssignmentNode(Generated::AstNode n, Generated::AstNode assignment) {
|
||||
n = assignment.(Generated::Assignment).getLeft()
|
||||
or
|
||||
n = assignment.(Generated::OperatorAssignment).getLeft()
|
||||
or
|
||||
exists(Generated::AstNode parent |
|
||||
parent = n.getParent() and
|
||||
explicitAssignmentNode(parent, assignment)
|
||||
|
|
||||
parent instanceof Generated::DestructuredLeftAssignment
|
||||
or
|
||||
parent instanceof Generated::LeftAssignmentList
|
||||
or
|
||||
parent instanceof Generated::RestAssignment
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` is inside an implicit assignment. */
|
||||
predicate implicitAssignmentNode(Generated::AstNode n) {
|
||||
n = any(Generated::ExceptionVariable ev).getChild()
|
||||
or
|
||||
n = any(Generated::For for).getPattern()
|
||||
or
|
||||
implicitAssignmentNode(n.getParent())
|
||||
}
|
||||
|
||||
/** Holds if `n` is inside a parameter. */
|
||||
predicate implicitParameterAssignmentNode(Generated::AstNode n, Callable::Range c) {
|
||||
n = c.getParameter(_)
|
||||
or
|
||||
implicitParameterAssignmentNode(n.getParent().(Generated::DestructuredParameter), c)
|
||||
}
|
||||
|
||||
private predicate instanceVariableAccess(
|
||||
Generated::InstanceVariable var, string name, Scope::Range scope, boolean instance
|
||||
) {
|
||||
@@ -23,11 +55,11 @@ private predicate classVariableAccess(Generated::ClassVariable var, string name,
|
||||
}
|
||||
|
||||
private predicate hasEnclosingMethod(Generated::AstNode node) {
|
||||
exists(Scope::Range s | node = s.getADescendant() and exists(s.getEnclosingMethod()))
|
||||
exists(Scope::Range s | scopeOf(node) = s and exists(s.getEnclosingMethod()))
|
||||
}
|
||||
|
||||
private ModuleBase::Range enclosingModuleOrClass(Generated::AstNode node) {
|
||||
exists(Scope::Range s | node = s.getADescendant() and result = s.getEnclosingModule())
|
||||
exists(Scope::Range s | scopeOf(node) = s and result = s.getEnclosingModule())
|
||||
}
|
||||
|
||||
private predicate parameterAssignment(Callable::Range scope, string name, Generated::Identifier i) {
|
||||
@@ -49,8 +81,8 @@ private predicate scopeDefinesParameterVariable(
|
||||
)
|
||||
or
|
||||
exists(Parameter::Range p |
|
||||
p = scope.(Callable::Range).getParameter(_) and
|
||||
name = p.(NamedParameter::Range).getName()
|
||||
p = scope.getParameter(_) and
|
||||
name = i.getValue()
|
||||
|
|
||||
i = p.(Generated::BlockParameter).getName() or
|
||||
i = p.(Generated::HashSplatParameter).getName() or
|
||||
@@ -64,7 +96,7 @@ private predicate scopeDefinesParameterVariable(
|
||||
private predicate scopeAssigns(Scope::Range scope, string name, Generated::Identifier i) {
|
||||
(explicitAssignmentNode(i, _) or implicitAssignmentNode(i)) and
|
||||
name = i.getValue() and
|
||||
scope = enclosingScope(i)
|
||||
scope = scopeOf(i)
|
||||
}
|
||||
|
||||
/** Holds if location `one` starts strictly before location `two` */
|
||||
@@ -75,39 +107,8 @@ private predicate strictlyBefore(Location one, Location two) {
|
||||
one.getStartLine() = two.getStartLine() and one.getStartColumn() < two.getStartColumn()
|
||||
}
|
||||
|
||||
private Generated::AstNode getNodeForIdentifier(Generated::Identifier id) {
|
||||
exists(Generated::AstNode parent | parent = id.getParent() |
|
||||
if
|
||||
parent instanceof Generated::BlockParameter
|
||||
or
|
||||
parent instanceof Generated::SplatParameter
|
||||
or
|
||||
parent instanceof Generated::HashSplatParameter
|
||||
or
|
||||
parent instanceof Generated::KeywordParameter
|
||||
or
|
||||
parent instanceof Generated::OptionalParameter
|
||||
then result = parent
|
||||
else result = id
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/** Gets the enclosing scope for `node`. */
|
||||
cached
|
||||
Scope::Range enclosingScope(Generated::AstNode node) { result.getADescendant() = node }
|
||||
|
||||
cached
|
||||
newtype TScope =
|
||||
TGlobalScope() or
|
||||
TTopLevelScope(Generated::Program node) or
|
||||
TModuleScope(Generated::Module node) or
|
||||
TClassScope(Generated::AstNode cls) {
|
||||
cls instanceof Generated::Class or cls instanceof Generated::SingletonClass
|
||||
} or
|
||||
TCallableScope(Callable::Range c)
|
||||
|
||||
cached
|
||||
newtype TVariable =
|
||||
TGlobalVariable(string name) { name = any(Generated::GlobalVariable var).getValue() } or
|
||||
@@ -292,7 +293,7 @@ private module Cached {
|
||||
variable.getName() = name and
|
||||
name = access.getValue()
|
||||
|
|
||||
variable.getDeclaringScope() = enclosingScope(access) and
|
||||
variable.getDeclaringScope() = scopeOf(access) and
|
||||
not strictlyBefore(access.getLocation(), variable.getLocation()) and
|
||||
// In case of overlapping parameter names, later parameters should not
|
||||
// be considered accesses to the first parameter
|
||||
@@ -302,7 +303,7 @@ private module Cached {
|
||||
or
|
||||
exists(Scope::Range declScope |
|
||||
variable.getDeclaringScope() = declScope and
|
||||
inherits(enclosingScope(access), name, declScope)
|
||||
inherits(scopeOf(access), name, declScope)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -329,8 +330,8 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate isCapturedAccess(LocalVariableAccess::Range access) {
|
||||
access.getVariable().getDeclaringScope() != enclosingScope(access)
|
||||
predicate isCapturedAccess(LocalVariableAccess access) {
|
||||
toGenerated(access.getVariable().getDeclaringScope()) != scopeOf(toGenerated(access))
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -353,7 +354,8 @@ private module Cached {
|
||||
import Cached
|
||||
|
||||
/** Holds if this scope inherits `name` from an outer scope `outer`. */
|
||||
private predicate inherits(Block::Range scope, string name, Scope::Range outer) {
|
||||
private predicate inherits(Scope::Range scope, string name, Scope::Range outer) {
|
||||
(scope instanceof Generated::Block or scope instanceof Generated::DoBlock) and
|
||||
not scopeDefinesParameterVariable(scope, name, _) and
|
||||
(
|
||||
outer = scope.getOuterScope() and
|
||||
@@ -362,7 +364,7 @@ private predicate inherits(Block::Range scope, string name, Scope::Range outer)
|
||||
or
|
||||
exists(Generated::Identifier i |
|
||||
scopeAssigns(outer, name, i) and
|
||||
strictlyBefore(i.getLocation(), scope.(Generated::AstNode).getLocation())
|
||||
strictlyBefore(i.getLocation(), scope.getLocation())
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -396,7 +398,7 @@ module LocalVariable {
|
||||
|
||||
final override Scope::Range getDeclaringScope() { result = scope }
|
||||
|
||||
final VariableAccess getDefiningAccess() { result = getNodeForIdentifier(i) }
|
||||
final VariableAccess getDefiningAccess() { toGenerated(result) = i }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,8 +416,6 @@ module GlobalVariable {
|
||||
}
|
||||
}
|
||||
|
||||
private class ModuleOrClassScope = TClassScope or TModuleScope or TTopLevelScope;
|
||||
|
||||
module InstanceVariable {
|
||||
class Range extends Variable::Range, TInstanceVariable {
|
||||
private ModuleBase::Range scope;
|
||||
@@ -451,86 +451,29 @@ module ClassVariable {
|
||||
}
|
||||
}
|
||||
|
||||
module VariableAccess {
|
||||
abstract class Range extends Expr::Range {
|
||||
abstract Variable getVariable();
|
||||
|
||||
final predicate isExplicitWrite(AstNode assignment) {
|
||||
exists(Generated::Identifier i | this = getNodeForIdentifier(i) |
|
||||
explicitWriteAccess(i, assignment)
|
||||
)
|
||||
or
|
||||
not this = getNodeForIdentifier(_) and explicitWriteAccess(this, assignment)
|
||||
}
|
||||
|
||||
final predicate isImplicitWrite() {
|
||||
exists(Generated::Identifier i | this = getNodeForIdentifier(i) | implicitWriteAccess(i))
|
||||
or
|
||||
not this = getNodeForIdentifier(_) and implicitWriteAccess(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module LocalVariableAccess {
|
||||
class LocalVariableRange =
|
||||
@token_identifier or @splat_parameter or @keyword_parameter or @optional_parameter or
|
||||
@hash_splat_parameter or @block_parameter;
|
||||
|
||||
class Range extends VariableAccess::Range, LocalVariableRange {
|
||||
LocalVariable variable;
|
||||
|
||||
Range() {
|
||||
exists(Generated::Identifier id |
|
||||
this = getNodeForIdentifier(id) and
|
||||
access(id, variable) and
|
||||
(
|
||||
explicitWriteAccess(id, _)
|
||||
or
|
||||
implicitWriteAccess(id)
|
||||
or
|
||||
vcall(id)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = generated.(Generated::Identifier).getValue() }
|
||||
|
||||
final override LocalVariable getVariable() { result = variable }
|
||||
predicate range(Generated::Identifier id, LocalVariable v) {
|
||||
access(id, v) and
|
||||
(
|
||||
explicitWriteAccess(id, _)
|
||||
or
|
||||
implicitWriteAccess(id)
|
||||
or
|
||||
vcall(id)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module GlobalVariableAccess {
|
||||
class Range extends VariableAccess::Range, @token_global_variable {
|
||||
GlobalVariable variable;
|
||||
|
||||
Range() { this.(Generated::GlobalVariable).getValue() = variable.getName() }
|
||||
|
||||
final override GlobalVariable getVariable() { result = variable }
|
||||
|
||||
override string toString() { result = generated.(Generated::GlobalVariable).getValue() }
|
||||
}
|
||||
predicate range(Generated::GlobalVariable n, GlobalVariable v) { n.getValue() = v.getName() }
|
||||
}
|
||||
|
||||
module InstanceVariableAccess {
|
||||
class Range extends VariableAccess::Range, @token_instance_variable {
|
||||
InstanceVariable variable;
|
||||
|
||||
Range() { instanceVariableAccess(this, variable) }
|
||||
|
||||
final override InstanceVariable getVariable() { result = variable }
|
||||
|
||||
override string toString() { result = generated.(Generated::InstanceVariable).getValue() }
|
||||
predicate range(Generated::InstanceVariable n, InstanceVariable v) {
|
||||
instanceVariableAccess(n, v)
|
||||
}
|
||||
}
|
||||
|
||||
module ClassVariableAccess {
|
||||
class Range extends VariableAccess::Range, @token_class_variable {
|
||||
ClassVariable variable;
|
||||
|
||||
Range() { classVariableAccess(this, variable) }
|
||||
|
||||
final override ClassVariable getVariable() { result = variable }
|
||||
|
||||
override string toString() { result = generated.(Generated::ClassVariable).getValue() }
|
||||
}
|
||||
predicate range(Generated::ClassVariable n, ClassVariable v) { classVariableAccess(n, v) }
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
private import codeql.Locations
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.ast.internal.TreeSitter
|
||||
private import codeql_ruby.controlflow.ControlFlowGraph
|
||||
private import internal.ControlFlowGraphImpl
|
||||
private import CfgNodes
|
||||
@@ -351,14 +353,14 @@ class ExitBasicBlock extends BasicBlock {
|
||||
}
|
||||
|
||||
private module JoinBlockPredecessors {
|
||||
private predicate id(AstNode x, AstNode y) { x = y }
|
||||
private predicate id(Generated::AstNode x, Generated::AstNode y) { x = y }
|
||||
|
||||
private predicate idOf(AstNode x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
private predicate idOf(Generated::AstNode x, int y) = equivalenceRelation(id/2)(x, y)
|
||||
|
||||
int getId(JoinBlockPredecessor jbp) {
|
||||
idOf(jbp.getFirstNode().(AstCfgNode).getNode(), result)
|
||||
idOf(toGenerated(jbp.getFirstNode().(AstCfgNode).getNode()), result)
|
||||
or
|
||||
idOf(jbp.(EntryBasicBlock).getScope(), result)
|
||||
idOf(toGenerated(jbp.(EntryBasicBlock).getScope()), result)
|
||||
}
|
||||
|
||||
string getSplitString(JoinBlockPredecessor jbp) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/** Provides classes representing nodes in a control flow graph. */
|
||||
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.controlflow.BasicBlocks
|
||||
private import ControlFlowGraph
|
||||
private import internal.ControlFlowGraphImpl
|
||||
@@ -62,11 +63,11 @@ class ExitNode extends CfgNode, TExitNode {
|
||||
* (dead) code or not important for control flow, and multiple when there are different
|
||||
* splits for the AST node.
|
||||
*/
|
||||
class AstCfgNode extends CfgNode, TAstNode {
|
||||
class AstCfgNode extends CfgNode, TAstCfgNode {
|
||||
private Splits splits;
|
||||
private AstNode n;
|
||||
|
||||
AstCfgNode() { this = TAstNode(n, splits) }
|
||||
AstCfgNode() { this = TAstCfgNode(toGenerated(n), splits) }
|
||||
|
||||
final override AstNode getNode() { result = n }
|
||||
|
||||
@@ -131,7 +132,7 @@ abstract private class ExprChildMapping extends Expr {
|
||||
|
||||
pragma[noinline]
|
||||
private BasicBlock getABasicBlockInScope() {
|
||||
result.getANode() = TAstNode(this.getAChildStar(), _)
|
||||
result.getANode() = TAstCfgNode(toGenerated(this.getAChildStar()), _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
private import codeql.Locations
|
||||
private import codeql_ruby.AST as AST
|
||||
private import codeql_ruby.ast.internal.AST as ASTInternal
|
||||
private import codeql_ruby.controlflow.BasicBlocks
|
||||
private import SuccessorTypes
|
||||
private import internal.ControlFlowGraphImpl
|
||||
@@ -10,13 +11,13 @@ private import internal.Completion
|
||||
|
||||
/** An AST node with an associated control-flow graph. */
|
||||
class CfgScope extends AST::AstNode {
|
||||
CfgScope() { this instanceof CfgScope::Range_ }
|
||||
CfgScope() { ASTInternal::toGenerated(this) instanceof CfgScope::Range_ }
|
||||
|
||||
/** Gets the CFG scope that this scope is nested under, if any. */
|
||||
final CfgScope getOuterCfgScope() {
|
||||
exists(AST::AstNode parent |
|
||||
parent = this.getParent() and
|
||||
result = getCfgScope(parent)
|
||||
result = getCfgScope(ASTInternal::toGenerated(parent))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.AST
|
||||
private import codeql_ruby.controlflow.ControlFlowGraph
|
||||
private import ControlFlowGraphImpl
|
||||
private import NonReturning
|
||||
@@ -53,7 +54,7 @@ private predicate nestedEnsureCompletion(Completion outer, int nestLevel) {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate completionIsValidForStmt(AstNode n, Completion c) {
|
||||
n instanceof InRange and
|
||||
n = TForIn(_) and
|
||||
c instanceof EmptinessCompletion
|
||||
or
|
||||
n instanceof BreakStmt and
|
||||
@@ -205,7 +206,7 @@ private predicate inMatchingContext(AstNode n) {
|
||||
w.getPattern(_) = n
|
||||
)
|
||||
or
|
||||
n = any(Trees::DefaultValueParameterTree t | t.hasDefaultValue())
|
||||
toGenerated(n).(Trees::DefaultValueParameterTree).hasDefaultValue()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.TreeSitter::Generated
|
||||
private import codeql_ruby.CFG
|
||||
private import Completion
|
||||
private import Splitting
|
||||
|
||||
@@ -31,9 +31,10 @@
|
||||
* caught up by its surrounding loop and turned into a `NormalCompletion`.
|
||||
*/
|
||||
|
||||
private import codeql_ruby.AST as AST
|
||||
private import codeql_ruby.ast.internal.AST as ASTInternal
|
||||
private import codeql_ruby.ast.internal.Control as Control
|
||||
private import codeql_ruby.ast.internal.Scope
|
||||
private import codeql_ruby.ast.Scope
|
||||
private import codeql_ruby.ast.internal.TreeSitter::Generated
|
||||
private import AstNodes
|
||||
private import codeql_ruby.ast.internal.Variable
|
||||
@@ -202,7 +203,7 @@ private predicate succImpl(AstNode pred, AstNode succ, Completion c) {
|
||||
}
|
||||
|
||||
private predicate isHidden(ControlFlowTree t) {
|
||||
not t instanceof ASTInternal::AstNode::Range
|
||||
not t = ASTInternal::toGenerated(_)
|
||||
or
|
||||
t.isHidden()
|
||||
}
|
||||
@@ -290,16 +291,17 @@ abstract private class PreOrderTree extends ControlFlowTree {
|
||||
}
|
||||
|
||||
// TODO: remove this class; it should be replaced with an implicit non AST node
|
||||
class InRange extends ASTInternal::AstNode::Range, @in {
|
||||
private class ForIn extends AST::AstNode, ASTInternal::TForIn {
|
||||
final override string toString() { result = "In" }
|
||||
}
|
||||
|
||||
// TODO: remove this class; it should be replaced with an implicit non AST node
|
||||
class ForRange extends Control::ForExpr::Range, @for {
|
||||
override predicate child(string label, ASTInternal::AstNode::Range child) {
|
||||
Control::ForExpr::Range.super.child(label, child)
|
||||
private class ForRange extends AST::ForExpr {
|
||||
override AST::AstNode getAChild(string pred) {
|
||||
result = AST::ForExpr.super.getAChild(pred)
|
||||
or
|
||||
label = "<in>" and this.(AstNode).getAFieldOrChild().(In) = child
|
||||
pred = "<in>" and
|
||||
result = ASTInternal::TForIn(ASTInternal::toGenerated(this).(For).getValue())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,7 +309,7 @@ class ForRange extends Control::ForExpr::Range, @for {
|
||||
predicate isValidFor(Completion c, ControlFlowTree node) {
|
||||
c instanceof SimpleCompletion and isHidden(node)
|
||||
or
|
||||
c.isValidFor(node)
|
||||
c.isValidFor(ASTInternal::fromGenerated(node))
|
||||
}
|
||||
|
||||
abstract private class StandardPreOrderTree extends StandardNode, PreOrderTree {
|
||||
@@ -343,7 +345,8 @@ private class LeftToRightPostOrderNodes =
|
||||
@operator_assignment or @pair or @parenthesized_statements or @range or @redo or @regex or
|
||||
@rest_assignment or @retry or @return or @right_assignment_list or @scope_resolution or
|
||||
@token_simple_symbol or @splat_argument or @string__ or @string_array or @subshell or
|
||||
@superclass or @symbol_array or @token_hash_key_symbol or @unary;
|
||||
@superclass or @symbol_array or @token_hash_key_symbol or @unary or @splat_parameter or
|
||||
@hash_splat_parameter or @block_parameter;
|
||||
|
||||
private class LeftToRightPostOrderTree extends StandardPostOrderTree, LeftToRightPostOrderNodes {
|
||||
LeftToRightPostOrderTree() {
|
||||
@@ -357,7 +360,10 @@ private class LeftToRightPostOrderTree extends StandardPostOrderTree, LeftToRigh
|
||||
this instanceof ChainedString or
|
||||
this instanceof ExceptionVariable or
|
||||
this instanceof LeftAssignmentList or
|
||||
this instanceof RightAssignmentList
|
||||
this instanceof RightAssignmentList or
|
||||
this instanceof SplatParameter or
|
||||
this instanceof HashSplatParameter or
|
||||
this instanceof BlockParameter
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,8 +447,6 @@ module Trees {
|
||||
}
|
||||
}
|
||||
|
||||
private class BlockParameterTree extends LeafTree, BlockParameter { }
|
||||
|
||||
private class CaseTree extends PreOrderTree, Case {
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getValue() or child = this.getChild(_)
|
||||
@@ -505,18 +509,24 @@ module Trees {
|
||||
private class ConstantTree extends LeafTree, Constant { }
|
||||
|
||||
/** A parameter that may have a default value. */
|
||||
abstract class DefaultValueParameterTree extends PreOrderTree {
|
||||
abstract class DefaultValueParameterTree extends ControlFlowTree {
|
||||
abstract AstNode getDefaultValue();
|
||||
|
||||
abstract AstNode getAccessNode();
|
||||
|
||||
predicate hasDefaultValue() { exists(this.getDefaultValue()) }
|
||||
|
||||
final override predicate propagatesAbnormal(AstNode child) { child = this.getDefaultValue() }
|
||||
final override predicate propagatesAbnormal(AstNode child) {
|
||||
child = this.getDefaultValue() or child = this.getAccessNode()
|
||||
}
|
||||
|
||||
final override predicate first(AstNode first) { first = this.getAccessNode() }
|
||||
|
||||
final override predicate last(AstNode last, Completion c) {
|
||||
last(this.getDefaultValue(), last, c) and
|
||||
c instanceof NormalCompletion
|
||||
or
|
||||
last = this and
|
||||
last = this.getAccessNode() and
|
||||
(
|
||||
not this.hasDefaultValue() and
|
||||
c instanceof SimpleCompletion
|
||||
@@ -527,7 +537,7 @@ module Trees {
|
||||
}
|
||||
|
||||
final override predicate succ(AstNode pred, AstNode succ, Completion c) {
|
||||
pred = this and
|
||||
pred = this.getAccessNode() and
|
||||
first(this.getDefaultValue(), succ) and
|
||||
c.(MatchingCompletion).getValue() = false
|
||||
}
|
||||
@@ -668,8 +678,6 @@ module Trees {
|
||||
|
||||
private class GlobalVariableTree extends LeafTree, GlobalVariable { }
|
||||
|
||||
private class HashSplatParameterTree extends LeafTree, HashSplatParameter { }
|
||||
|
||||
private HeredocBody heredoc(HeredocBeginning start) {
|
||||
exists(int i, File f |
|
||||
start =
|
||||
@@ -725,6 +733,8 @@ module Trees {
|
||||
|
||||
private class KeywordParameterTree extends DefaultValueParameterTree, KeywordParameter {
|
||||
final override AstNode getDefaultValue() { result = this.getValue() }
|
||||
|
||||
final override AstNode getAccessNode() { result = this.getName() }
|
||||
}
|
||||
|
||||
class LambdaTree extends LeafTree, Lambda {
|
||||
@@ -823,6 +833,8 @@ module Trees {
|
||||
|
||||
private class OptionalParameterTree extends DefaultValueParameterTree, OptionalParameter {
|
||||
final override AstNode getDefaultValue() { result = this.getValue() }
|
||||
|
||||
final override AstNode getAccessNode() { result = this.getName() }
|
||||
}
|
||||
|
||||
private class RationalTree extends LeafTree, Rational { }
|
||||
@@ -1183,8 +1195,6 @@ module Trees {
|
||||
}
|
||||
}
|
||||
|
||||
private class SplatParameterTree extends LeafTree, SplatParameter { }
|
||||
|
||||
private class SuperTree extends LeafTree, Super { }
|
||||
|
||||
private class TrueTree extends LeafTree, True { }
|
||||
@@ -1261,14 +1271,14 @@ module Trees {
|
||||
|
||||
private Scope::Range parent(Scope::Range n) {
|
||||
result = n.getOuterScope() and
|
||||
not n instanceof CfgScope
|
||||
not n instanceof CfgScope::Range_
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/** Gets the CFG scope of node `n`. */
|
||||
cached
|
||||
CfgScope getCfgScope(AstNode n) { result = parent*(any(Scope::Range x | x.getADescendant() = n)) }
|
||||
CfgScope getCfgScope(AstNode n) { ASTInternal::toGenerated(result) = parent*(scopeOf(n)) }
|
||||
|
||||
private predicate isAbnormalExitType(SuccessorType t) {
|
||||
t instanceof RaiseSuccessor or t instanceof ExitSuccessor
|
||||
@@ -1288,7 +1298,7 @@ private module Cached {
|
||||
succExitSplits(b.getANode(), _, scope, _)
|
||||
)
|
||||
} or
|
||||
TAstNode(AstNode n, Splits splits) {
|
||||
TAstCfgNode(AstNode n, Splits splits) {
|
||||
exists(Reachability::SameSplitsBlock b | b.isReachable(splits) | n = b.getANode())
|
||||
}
|
||||
|
||||
@@ -1312,10 +1322,10 @@ private module Cached {
|
||||
exists(CfgScope scope, AstNode succElement, Splits succSplits |
|
||||
pred = TEntryNode(scope) and
|
||||
succEntrySplits(scope, succElement, succSplits, t) and
|
||||
result = TAstNode(succElement, succSplits)
|
||||
result = TAstCfgNode(succElement, succSplits)
|
||||
)
|
||||
or
|
||||
exists(AstNode predNode, Splits predSplits | pred = TAstNode(predNode, predSplits) |
|
||||
exists(AstNode predNode, Splits predSplits | pred = TAstCfgNode(predNode, predSplits) |
|
||||
exists(CfgScope scope, boolean normal |
|
||||
succExitSplits(predNode, predSplits, scope, t) and
|
||||
(if isAbnormalExitType(t) then normal = false else normal = true) and
|
||||
@@ -1325,7 +1335,7 @@ private module Cached {
|
||||
exists(AstNode succElement, Splits succSplits, Completion c |
|
||||
succSplits(predNode, predSplits, succElement, succSplits, c) and
|
||||
t = c.getAMatchingSuccessorType() and
|
||||
result = TAstNode(succElement, succSplits)
|
||||
result = TAstCfgNode(succElement, succSplits)
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -1349,5 +1359,5 @@ import Cached
|
||||
|
||||
/** An AST node that is split into multiple control flow nodes. */
|
||||
class SplitAstNode extends AstNode {
|
||||
SplitAstNode() { strictcount(CfgNode n | n.getNode() = this) > 1 }
|
||||
SplitAstNode() { strictcount(CfgNode n | ASTInternal::toGenerated(n.getNode()) = this) > 1 }
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
* Provides classes and predicates relevant for splitting the control flow graph.
|
||||
*/
|
||||
|
||||
private import codeql_ruby.AST
|
||||
private import codeql_ruby.ast.internal.TreeSitter::Generated
|
||||
private import codeql_ruby.ast.internal.AST as ASTInternal
|
||||
private import codeql_ruby.AST as AST
|
||||
private import Completion
|
||||
private import ControlFlowGraphImpl
|
||||
private import SuccessorTypes
|
||||
@@ -217,19 +219,28 @@ private module ConditionalCompletionSplitting {
|
||||
succ(pred, succ, c) and
|
||||
last(succ, _, completion) and
|
||||
(
|
||||
last(succ.(NotExpr).getOperand(), pred, c) and
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ).(AST::NotExpr).getOperand()),
|
||||
pred, c) and
|
||||
completion.(BooleanCompletion).getDual() = c
|
||||
or
|
||||
last(succ.(LogicalAndExpr).getAnOperand(), pred, c) and
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::LogicalAndExpr)
|
||||
.getAnOperand()), pred, c) and
|
||||
completion = c
|
||||
or
|
||||
last(succ.(LogicalOrExpr).getAnOperand(), pred, c) and
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::LogicalOrExpr)
|
||||
.getAnOperand()), pred, c) and
|
||||
completion = c
|
||||
or
|
||||
last(succ.(ParenthesizedExpr).getLastExpr(), pred, c) and
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::ParenthesizedExpr)
|
||||
.getLastExpr()), pred, c) and
|
||||
completion = c
|
||||
or
|
||||
last(succ.(ConditionalExpr).getBranch(_), pred, c) and
|
||||
last(ASTInternal::toGenerated(ASTInternal::fromGenerated(succ)
|
||||
.(AST::ConditionalExpr)
|
||||
.getBranch(_)), pred, c) and
|
||||
completion = c
|
||||
)
|
||||
}
|
||||
@@ -244,7 +255,7 @@ private module ConditionalCompletionSplitting {
|
||||
|
||||
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
|
||||
this.appliesTo(last) and
|
||||
succExit(scope, last, c) and
|
||||
succExit(ASTInternal::toGenerated(scope), last, c) and
|
||||
if c instanceof ConditionalCompletion then completion = c else any()
|
||||
}
|
||||
|
||||
@@ -461,7 +472,7 @@ module EnsureSplitting {
|
||||
}
|
||||
|
||||
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
|
||||
succExit(scope, last, c) and
|
||||
succExit(ASTInternal::toGenerated(scope), last, c) and
|
||||
(
|
||||
exit(_, last, c, _)
|
||||
or
|
||||
@@ -506,7 +517,7 @@ class Splits extends TSplits {
|
||||
|
||||
private predicate succEntrySplitsFromRank(CfgScope pred, AstNode succ, Splits splits, int rnk) {
|
||||
splits = TSplitsNil() and
|
||||
succEntry(pred, succ) and
|
||||
succEntry(ASTInternal::toGenerated(pred), succ) and
|
||||
rnk = 0
|
||||
or
|
||||
exists(SplitImpl head, Splits tail | succEntrySplitsCons(pred, succ, head, tail, rnk) |
|
||||
@@ -529,7 +540,7 @@ private predicate succEntrySplitsCons(
|
||||
pragma[noinline]
|
||||
predicate succEntrySplits(CfgScope pred, AstNode succ, Splits succSplits, SuccessorType t) {
|
||||
exists(int rnk |
|
||||
succEntry(pred, succ) and
|
||||
succEntry(ASTInternal::toGenerated(pred), succ) and
|
||||
t instanceof NormalSuccessor and
|
||||
succEntrySplitsFromRank(pred, succ, succSplits, rnk)
|
||||
|
|
||||
@@ -548,7 +559,7 @@ predicate succExitSplits(AstNode last, Splits predSplits, CfgScope scope, Succes
|
||||
exists(Reachability::SameSplitsBlock b, Completion c | last = b.getANode() |
|
||||
b.isReachable(predSplits) and
|
||||
t = c.getAMatchingSuccessorType() and
|
||||
succExit(scope, last, c) and
|
||||
succExit(ASTInternal::toGenerated(scope), last, c) and
|
||||
forall(SplitImpl predSplit | predSplit = predSplits.getASplit() |
|
||||
predSplit.hasExitScope(scope, last, c)
|
||||
)
|
||||
|
||||
@@ -52,7 +52,7 @@ class PrintAstNode extends AstNode {
|
||||
/**
|
||||
* Gets the child node that is accessed using the predicate `edgeName`.
|
||||
*/
|
||||
PrintAstNode getChild(string edgeName) { range.child(edgeName, result) }
|
||||
PrintAstNode getChild(string edgeName) { result = this.getAChild(edgeName) }
|
||||
}
|
||||
|
||||
private predicate shouldPrintNode(AstNode n) {
|
||||
|
||||
@@ -13,12 +13,14 @@ calls/calls.rb:
|
||||
# 17| getStmt: [MethodCall] call to foo
|
||||
# 17| getBlock: [BraceBlock] { ... }
|
||||
# 17| getParameter: [SimpleParameter] x
|
||||
# 17| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 17| getStmt: [AddExpr] ... + ...
|
||||
# 17| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 17| getAnOperand/getRightOperand: [IntegerLiteral] 1
|
||||
# 20| getStmt: [MethodCall] call to foo
|
||||
# 20| getBlock: [DoBlock] do ... end
|
||||
# 20| getParameter: [SimpleParameter] x
|
||||
# 20| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 21| getStmt: [AddExpr] ... + ...
|
||||
# 21| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 21| getAnOperand/getRightOperand: [IntegerLiteral] 1
|
||||
@@ -28,6 +30,7 @@ calls/calls.rb:
|
||||
# 25| getComponent: [StringTextComponent] foo
|
||||
# 25| getBlock: [DoBlock] do ... end
|
||||
# 25| getParameter: [SimpleParameter] x
|
||||
# 25| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 26| getStmt: [AddExpr] ... + ...
|
||||
# 26| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 26| getAnOperand/getRightOperand: [IntegerLiteral] 1
|
||||
@@ -153,16 +156,20 @@ calls/calls.rb:
|
||||
# 144| getReceiver: [ConstantReadAccess] X
|
||||
# 148| getStmt: [Method] method_with_keyword_param
|
||||
# 148| getParameter: [KeywordParameter] keyword
|
||||
# 148| getDefiningAccess: [LocalVariableAccess] keyword
|
||||
# 148| getDefaultValue: [MethodCall] call to foo
|
||||
# 150| getStmt: [Method] method_with_keyword_param2
|
||||
# 150| getParameter: [KeywordParameter] keyword
|
||||
# 150| getDefiningAccess: [LocalVariableAccess] keyword
|
||||
# 150| getDefaultValue: [MethodCall] call to foo
|
||||
# 150| getReceiver: [ConstantReadAccess] X
|
||||
# 154| getStmt: [Method] method_with_optional_param
|
||||
# 154| getParameter: [OptionalParameter] param
|
||||
# 154| getDefiningAccess: [LocalVariableAccess] param
|
||||
# 154| getDefaultValue: [MethodCall] call to foo
|
||||
# 156| getStmt: [Method] method_with_optional_param2
|
||||
# 156| getParameter: [OptionalParameter] param
|
||||
# 156| getDefiningAccess: [LocalVariableAccess] param
|
||||
# 156| getDefaultValue: [MethodCall] call to foo
|
||||
# 156| getReceiver: [ConstantReadAccess] X
|
||||
# 160| getStmt: [Module] SomeModule
|
||||
@@ -383,12 +390,14 @@ calls/calls.rb:
|
||||
# 290| getStmt: [SuperCall] call to super
|
||||
# 290| getBlock: [BraceBlock] { ... }
|
||||
# 290| getParameter: [SimpleParameter] x
|
||||
# 290| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 290| getStmt: [AddExpr] ... + ...
|
||||
# 290| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 290| getAnOperand/getRightOperand: [IntegerLiteral] 1
|
||||
# 291| getStmt: [SuperCall] call to super
|
||||
# 291| getBlock: [DoBlock] do ... end
|
||||
# 291| getParameter: [SimpleParameter] x
|
||||
# 291| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 291| getStmt: [MulExpr] ... * ...
|
||||
# 291| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 291| getAnOperand/getRightOperand: [IntegerLiteral] 2
|
||||
@@ -397,6 +406,7 @@ calls/calls.rb:
|
||||
# 292| getArgument: [IntegerLiteral] 5
|
||||
# 292| getBlock: [BraceBlock] { ... }
|
||||
# 292| getParameter: [SimpleParameter] x
|
||||
# 292| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 292| getStmt: [AddExpr] ... + ...
|
||||
# 292| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 292| getAnOperand/getRightOperand: [IntegerLiteral] 100
|
||||
@@ -405,6 +415,7 @@ calls/calls.rb:
|
||||
# 293| getArgument: [IntegerLiteral] 7
|
||||
# 293| getBlock: [DoBlock] do ... end
|
||||
# 293| getParameter: [SimpleParameter] x
|
||||
# 293| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 293| getStmt: [AddExpr] ... + ...
|
||||
# 293| getAnOperand/getLeftOperand: [LocalVariableAccess] x
|
||||
# 293| getAnOperand/getRightOperand: [IntegerLiteral] 200
|
||||
@@ -689,6 +700,7 @@ constants/constants.rb:
|
||||
# 19| getReceiver: [ConstantReadAccess] Names
|
||||
# 19| getBlock: [DoBlock] do ... end
|
||||
# 19| getParameter: [SimpleParameter] name
|
||||
# 19| getDefiningAccess: [LocalVariableAccess] name
|
||||
# 20| getStmt: [MethodCall] call to puts
|
||||
# 20| getArgument: [StringLiteral] "#{...} #{...}"
|
||||
# 20| getComponent: [StringInterpolationComponent] #{...}
|
||||
@@ -1528,8 +1540,11 @@ params/params.rb:
|
||||
# 1| [Toplevel] params.rb
|
||||
# 4| getStmt: [Method] identifier_method_params
|
||||
# 4| getParameter: [SimpleParameter] foo
|
||||
# 4| getDefiningAccess: [LocalVariableAccess] foo
|
||||
# 4| getParameter: [SimpleParameter] bar
|
||||
# 4| getDefiningAccess: [LocalVariableAccess] bar
|
||||
# 4| getParameter: [SimpleParameter] baz
|
||||
# 4| getDefiningAccess: [LocalVariableAccess] baz
|
||||
# 8| getStmt: [AssignExpr] ... = ...
|
||||
# 8| getAnOperand/getLeftOperand: [LocalVariableAccess] hash
|
||||
# 8| getAnOperand/getRightOperand: [HashLiteral] {...}
|
||||
@@ -1537,7 +1552,9 @@ params/params.rb:
|
||||
# 9| getReceiver: [LocalVariableAccess] hash
|
||||
# 9| getBlock: [DoBlock] do ... end
|
||||
# 9| getParameter: [SimpleParameter] key
|
||||
# 9| getDefiningAccess: [LocalVariableAccess] key
|
||||
# 9| getParameter: [SimpleParameter] value
|
||||
# 9| getDefiningAccess: [LocalVariableAccess] value
|
||||
# 10| getStmt: [MethodCall] call to puts
|
||||
# 10| getArgument: [StringLiteral] "#{...} -> #{...}"
|
||||
# 10| getComponent: [StringInterpolationComponent] #{...}
|
||||
@@ -1549,7 +1566,9 @@ params/params.rb:
|
||||
# 14| getAnOperand/getLeftOperand: [LocalVariableAccess] sum
|
||||
# 14| getAnOperand/getRightOperand: [Lambda] -> { ... }
|
||||
# 14| getParameter: [SimpleParameter] foo
|
||||
# 14| getDefiningAccess: [LocalVariableAccess] foo
|
||||
# 14| getParameter: [SimpleParameter] bar
|
||||
# 14| getDefiningAccess: [LocalVariableAccess] bar
|
||||
# 14| getStmt: [AddExpr] ... + ...
|
||||
# 14| getAnOperand/getLeftOperand: [LocalVariableAccess] foo
|
||||
# 14| getAnOperand/getRightOperand: [LocalVariableAccess] bar
|
||||
@@ -1589,24 +1608,36 @@ params/params.rb:
|
||||
# 26| getAnOperand/getRightOperand: [LocalVariableAccess] fourth
|
||||
# 30| getStmt: [Method] method_with_splat
|
||||
# 30| getParameter: [SimpleParameter] wibble
|
||||
# 30| getDefiningAccess: [LocalVariableAccess] wibble
|
||||
# 30| getParameter: [SplatParameter] *splat
|
||||
# 30| getDefiningAccess: [LocalVariableAccess] splat
|
||||
# 30| getParameter: [HashSplatParameter] **double_splat
|
||||
# 30| getDefiningAccess: [LocalVariableAccess] double_splat
|
||||
# 34| getStmt: [MethodCall] call to each
|
||||
# 34| getReceiver: [LocalVariableAccess] array
|
||||
# 34| getBlock: [DoBlock] do ... end
|
||||
# 34| getParameter: [SimpleParameter] val
|
||||
# 34| getDefiningAccess: [LocalVariableAccess] val
|
||||
# 34| getParameter: [SplatParameter] *splat
|
||||
# 34| getDefiningAccess: [LocalVariableAccess] splat
|
||||
# 34| getParameter: [HashSplatParameter] **double_splat
|
||||
# 34| getDefiningAccess: [LocalVariableAccess] double_splat
|
||||
# 38| getStmt: [AssignExpr] ... = ...
|
||||
# 38| getAnOperand/getLeftOperand: [LocalVariableAccess] lambda_with_splats
|
||||
# 38| getAnOperand/getRightOperand: [Lambda] -> { ... }
|
||||
# 38| getParameter: [SimpleParameter] x
|
||||
# 38| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 38| getParameter: [SplatParameter] *blah
|
||||
# 38| getDefiningAccess: [LocalVariableAccess] blah
|
||||
# 38| getParameter: [HashSplatParameter] **wibble
|
||||
# 38| getDefiningAccess: [LocalVariableAccess] wibble
|
||||
# 41| getStmt: [Method] method_with_keyword_params
|
||||
# 41| getParameter: [SimpleParameter] x
|
||||
# 41| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 41| getParameter: [KeywordParameter] foo
|
||||
# 41| getDefiningAccess: [LocalVariableAccess] foo
|
||||
# 41| getParameter: [KeywordParameter] bar
|
||||
# 41| getDefiningAccess: [LocalVariableAccess] bar
|
||||
# 41| getDefaultValue: [IntegerLiteral] 7
|
||||
# 42| getStmt: [AddExpr] ... + ...
|
||||
# 42| getAnOperand/getLeftOperand: [AddExpr] ... + ...
|
||||
@@ -1615,6 +1646,7 @@ params/params.rb:
|
||||
# 42| getAnOperand/getRightOperand: [LocalVariableAccess] bar
|
||||
# 46| getStmt: [Method] use_block_with_keyword
|
||||
# 46| getParameter: [BlockParameter] &block
|
||||
# 46| getDefiningAccess: [LocalVariableAccess] block
|
||||
# 47| getStmt: [MethodCall] call to puts
|
||||
# 47| getArgument: [MethodCall] call to call
|
||||
# 47| getReceiver: [LocalVariableAccess] block
|
||||
@@ -1627,7 +1659,9 @@ params/params.rb:
|
||||
# 49| getStmt: [MethodCall] call to use_block_with_keyword
|
||||
# 49| getBlock: [DoBlock] do ... end
|
||||
# 49| getParameter: [KeywordParameter] xx
|
||||
# 49| getDefiningAccess: [LocalVariableAccess] xx
|
||||
# 49| getParameter: [KeywordParameter] yy
|
||||
# 49| getDefiningAccess: [LocalVariableAccess] yy
|
||||
# 49| getDefaultValue: [IntegerLiteral] 100
|
||||
# 50| getStmt: [AddExpr] ... + ...
|
||||
# 50| getAnOperand/getLeftOperand: [LocalVariableAccess] xx
|
||||
@@ -1636,8 +1670,11 @@ params/params.rb:
|
||||
# 53| getAnOperand/getLeftOperand: [LocalVariableAccess] lambda_with_keyword_params
|
||||
# 53| getAnOperand/getRightOperand: [Lambda] -> { ... }
|
||||
# 53| getParameter: [SimpleParameter] x
|
||||
# 53| getDefiningAccess: [LocalVariableAccess] x
|
||||
# 53| getParameter: [KeywordParameter] y
|
||||
# 53| getDefiningAccess: [LocalVariableAccess] y
|
||||
# 53| getParameter: [KeywordParameter] z
|
||||
# 53| getDefiningAccess: [LocalVariableAccess] z
|
||||
# 53| getDefaultValue: [IntegerLiteral] 3
|
||||
# 54| getStmt: [AddExpr] ... + ...
|
||||
# 54| getAnOperand/getLeftOperand: [AddExpr] ... + ...
|
||||
@@ -1646,12 +1683,16 @@ params/params.rb:
|
||||
# 54| getAnOperand/getRightOperand: [LocalVariableAccess] z
|
||||
# 58| getStmt: [Method] method_with_optional_params
|
||||
# 58| getParameter: [SimpleParameter] val1
|
||||
# 58| getDefiningAccess: [LocalVariableAccess] val1
|
||||
# 58| getParameter: [OptionalParameter] val2
|
||||
# 58| getDefiningAccess: [LocalVariableAccess] val2
|
||||
# 58| getDefaultValue: [IntegerLiteral] 0
|
||||
# 58| getParameter: [OptionalParameter] val3
|
||||
# 58| getDefiningAccess: [LocalVariableAccess] val3
|
||||
# 58| getDefaultValue: [IntegerLiteral] 100
|
||||
# 62| getStmt: [Method] use_block_with_optional
|
||||
# 62| getParameter: [BlockParameter] &block
|
||||
# 62| getDefiningAccess: [LocalVariableAccess] block
|
||||
# 63| getStmt: [MethodCall] call to call
|
||||
# 63| getReceiver: [LocalVariableAccess] block
|
||||
# 63| getArgument: [StringLiteral] "Zeus"
|
||||
@@ -1659,7 +1700,9 @@ params/params.rb:
|
||||
# 65| getStmt: [MethodCall] call to use_block_with_optional
|
||||
# 65| getBlock: [DoBlock] do ... end
|
||||
# 65| getParameter: [SimpleParameter] name
|
||||
# 65| getDefiningAccess: [LocalVariableAccess] name
|
||||
# 65| getParameter: [OptionalParameter] age
|
||||
# 65| getDefiningAccess: [LocalVariableAccess] age
|
||||
# 65| getDefaultValue: [IntegerLiteral] 99
|
||||
# 66| getStmt: [MethodCall] call to puts
|
||||
# 66| getArgument: [StringLiteral] "#{...} is #{...} years old"
|
||||
@@ -1673,9 +1716,12 @@ params/params.rb:
|
||||
# 70| getAnOperand/getLeftOperand: [LocalVariableAccess] lambda_with_optional_params
|
||||
# 70| getAnOperand/getRightOperand: [Lambda] -> { ... }
|
||||
# 70| getParameter: [SimpleParameter] a
|
||||
# 70| getDefiningAccess: [LocalVariableAccess] a
|
||||
# 70| getParameter: [OptionalParameter] b
|
||||
# 70| getDefiningAccess: [LocalVariableAccess] b
|
||||
# 70| getDefaultValue: [IntegerLiteral] 1000
|
||||
# 70| getParameter: [OptionalParameter] c
|
||||
# 70| getDefiningAccess: [LocalVariableAccess] c
|
||||
# 70| getDefaultValue: [IntegerLiteral] 20
|
||||
# 70| getStmt: [AddExpr] ... + ...
|
||||
# 70| getAnOperand/getLeftOperand: [AddExpr] ... + ...
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
break_ensure.rb:
|
||||
# 1| enter break_ensure.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| enter m1
|
||||
#-----| -> elements
|
||||
|
||||
# 1| enter break_ensure.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| m1
|
||||
#-----| -> m2
|
||||
|
||||
# 1| elements
|
||||
#-----| -> elements
|
||||
|
||||
# 1| exit break_ensure.rb
|
||||
|
||||
# 1| exit m1
|
||||
|
||||
# 1| exit break_ensure.rb (normal)
|
||||
#-----| -> exit break_ensure.rb
|
||||
# 1| exit break_ensure.rb
|
||||
|
||||
# 1| exit m1 (normal)
|
||||
#-----| -> exit m1
|
||||
|
||||
# 1| exit break_ensure.rb (normal)
|
||||
#-----| -> exit break_ensure.rb
|
||||
|
||||
# 2| for ... in ...
|
||||
#-----| -> ensure ...
|
||||
|
||||
@@ -338,25 +338,25 @@ break_ensure.rb:
|
||||
#-----| -> [ensure: raise] break
|
||||
|
||||
case.rb:
|
||||
# 1| enter case.rb
|
||||
#-----| -> if_in_case
|
||||
|
||||
# 1| enter if_in_case
|
||||
#-----| -> case ...
|
||||
|
||||
# 1| enter case.rb
|
||||
#-----| -> if_in_case
|
||||
|
||||
# 1| if_in_case
|
||||
#-----| -> exit case.rb (normal)
|
||||
|
||||
# 1| exit case.rb
|
||||
|
||||
# 1| exit if_in_case
|
||||
|
||||
# 1| exit case.rb (normal)
|
||||
#-----| -> exit case.rb
|
||||
# 1| exit case.rb
|
||||
|
||||
# 1| exit if_in_case (normal)
|
||||
#-----| -> exit if_in_case
|
||||
|
||||
# 1| exit case.rb (normal)
|
||||
#-----| -> exit case.rb
|
||||
|
||||
# 2| case ...
|
||||
#-----| -> call to x1
|
||||
|
||||
@@ -544,7 +544,7 @@ cfg.rb:
|
||||
#-----| -> &...
|
||||
|
||||
# 29| enter { ... }
|
||||
#-----| -> &x
|
||||
#-----| -> x
|
||||
|
||||
# 29| call to new
|
||||
#-----| -> true
|
||||
@@ -555,7 +555,7 @@ cfg.rb:
|
||||
# 29| { ... }
|
||||
#-----| -> call to new
|
||||
|
||||
# 29| &x
|
||||
# 29| x
|
||||
#-----| -> x
|
||||
|
||||
# 29| call to call
|
||||
@@ -1094,9 +1094,9 @@ cfg.rb:
|
||||
#-----| -> key
|
||||
|
||||
# 101| key
|
||||
#-----| -> **kwargs
|
||||
#-----| -> kwargs
|
||||
|
||||
# 101| **kwargs
|
||||
# 101| kwargs
|
||||
#-----| -> value
|
||||
|
||||
# 101| exit parameters
|
||||
@@ -1456,7 +1456,7 @@ cfg.rb:
|
||||
#-----| -> call to new
|
||||
|
||||
# 149| enter method
|
||||
#-----| -> *x
|
||||
#-----| -> x
|
||||
|
||||
# 149| method
|
||||
#-----| -> two_parameters
|
||||
@@ -1464,7 +1464,7 @@ cfg.rb:
|
||||
# 149| silly
|
||||
#-----| -> method
|
||||
|
||||
# 149| *x
|
||||
# 149| x
|
||||
#-----| -> x
|
||||
|
||||
# 149| exit method
|
||||
@@ -1825,24 +1825,21 @@ cfg.rb:
|
||||
#-----| -> exit { ... }
|
||||
|
||||
exit.rb:
|
||||
# 1| enter exit.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| enter m1
|
||||
#-----| -> x
|
||||
|
||||
# 1| enter exit.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| m1
|
||||
#-----| -> m2
|
||||
|
||||
# 1| x
|
||||
#-----| -> x
|
||||
|
||||
# 1| exit exit.rb
|
||||
|
||||
# 1| exit m1
|
||||
|
||||
# 1| exit exit.rb (normal)
|
||||
#-----| -> exit exit.rb
|
||||
# 1| exit exit.rb
|
||||
|
||||
# 1| exit m1 (abnormal)
|
||||
#-----| -> exit m1
|
||||
@@ -1850,6 +1847,9 @@ exit.rb:
|
||||
# 1| exit m1 (normal)
|
||||
#-----| -> exit m1
|
||||
|
||||
# 1| exit exit.rb (normal)
|
||||
#-----| -> exit exit.rb
|
||||
|
||||
# 2| if ...
|
||||
#-----| -> "x <= 2"
|
||||
|
||||
@@ -1918,25 +1918,25 @@ exit.rb:
|
||||
#-----| -> call to puts
|
||||
|
||||
heredoc.rb:
|
||||
# 1| enter heredoc.rb
|
||||
#-----| -> double_heredoc
|
||||
|
||||
# 1| enter double_heredoc
|
||||
#-----| -> <<A
|
||||
|
||||
# 1| enter heredoc.rb
|
||||
#-----| -> double_heredoc
|
||||
|
||||
# 1| double_heredoc
|
||||
#-----| -> exit heredoc.rb (normal)
|
||||
|
||||
# 1| exit heredoc.rb
|
||||
|
||||
# 1| exit double_heredoc
|
||||
|
||||
# 1| exit heredoc.rb (normal)
|
||||
#-----| -> exit heredoc.rb
|
||||
# 1| exit heredoc.rb
|
||||
|
||||
# 1| exit double_heredoc (normal)
|
||||
#-----| -> exit double_heredoc
|
||||
|
||||
# 1| exit heredoc.rb (normal)
|
||||
#-----| -> exit heredoc.rb
|
||||
|
||||
# 2| call to puts
|
||||
#-----| -> exit double_heredoc (normal)
|
||||
|
||||
@@ -1947,28 +1947,28 @@ heredoc.rb:
|
||||
#-----| -> call to puts
|
||||
|
||||
ifs.rb:
|
||||
# 1| enter ifs.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| enter m1
|
||||
#-----| -> x
|
||||
|
||||
# 1| enter ifs.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| m1
|
||||
#-----| -> m2
|
||||
|
||||
# 1| x
|
||||
#-----| -> x
|
||||
|
||||
# 1| exit ifs.rb
|
||||
|
||||
# 1| exit m1
|
||||
|
||||
# 1| exit ifs.rb (normal)
|
||||
#-----| -> exit ifs.rb
|
||||
# 1| exit ifs.rb
|
||||
|
||||
# 1| exit m1 (normal)
|
||||
#-----| -> exit m1
|
||||
|
||||
# 1| exit ifs.rb (normal)
|
||||
#-----| -> exit ifs.rb
|
||||
|
||||
# 2| if ...
|
||||
#-----| -> exit m1 (normal)
|
||||
|
||||
@@ -2343,28 +2343,28 @@ ifs.rb:
|
||||
#-----| true -> [false] ! ...
|
||||
|
||||
loops.rb:
|
||||
# 1| enter loops.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| enter m1
|
||||
#-----| -> x
|
||||
|
||||
# 1| enter loops.rb
|
||||
#-----| -> m1
|
||||
|
||||
# 1| m1
|
||||
#-----| -> m2
|
||||
|
||||
# 1| x
|
||||
#-----| -> x
|
||||
|
||||
# 1| exit loops.rb
|
||||
|
||||
# 1| exit m1
|
||||
|
||||
# 1| exit loops.rb (normal)
|
||||
#-----| -> exit loops.rb
|
||||
# 1| exit loops.rb
|
||||
|
||||
# 1| exit m1 (normal)
|
||||
#-----| -> exit m1
|
||||
|
||||
# 1| exit loops.rb (normal)
|
||||
#-----| -> exit loops.rb
|
||||
|
||||
# 2| while ...
|
||||
#-----| -> exit m1 (normal)
|
||||
|
||||
|
||||
@@ -13,11 +13,11 @@ definition
|
||||
| parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x |
|
||||
| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas |
|
||||
| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value |
|
||||
| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size |
|
||||
| parameters.rb:30:15:30:19 | first | parameters.rb:30:15:30:19 | first |
|
||||
@@ -100,12 +100,12 @@ read
|
||||
| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:9:25:9:30 | client |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:11:41:11:46 | client |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:11:14:11:19 | pizzas |
|
||||
| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map | parameters.rb:16:3:16:5 | map |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:11:14:11:19 | pizzas |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:16:3:16:5 | map |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:17:13:17:15 | key |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:17:22:17:26 | value |
|
||||
| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block | parameters.rb:22:3:22:7 | block |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:22:3:22:7 | block |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:40:25:43 | name |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:26:8:26:11 | name |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:27:8:27:11 | size |
|
||||
@@ -181,11 +181,11 @@ firstRead
|
||||
| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:9:25:9:30 | client |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:11:41:11:46 | client |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas |
|
||||
| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map | parameters.rb:16:3:16:5 | map |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:16:3:16:5 | map |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:17:13:17:15 | key |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:17:22:17:26 | value |
|
||||
| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block | parameters.rb:22:3:22:7 | block |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:22:3:22:7 | block |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:40:25:43 | name |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:26:8:26:11 | name |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:27:8:27:11 | size |
|
||||
@@ -250,12 +250,12 @@ lastRead
|
||||
| parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:9:25:9:30 | client |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:11:41:11:46 | client |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:11:14:11:19 | pizzas |
|
||||
| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map | parameters.rb:16:3:16:5 | map |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:11:14:11:19 | pizzas |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:16:3:16:5 | map |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:17:13:17:15 | key |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:17:22:17:26 | value |
|
||||
| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block | parameters.rb:22:3:22:7 | block |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:22:3:22:7 | block |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:26:8:26:11 | name |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:27:8:27:11 | size |
|
||||
| parameters.rb:30:15:30:19 | first | parameters.rb:30:15:30:19 | first | parameters.rb:31:11:31:15 | first |
|
||||
@@ -306,7 +306,7 @@ lastRead
|
||||
| ssa.rb:84:10:86:8 | <captured> | ssa.rb:82:3:82:10 | captured | ssa.rb:85:15:85:22 | captured |
|
||||
adjacentReads
|
||||
| nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:15:11:15:11 | a |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas | parameters.rb:11:14:11:19 | pizzas |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas | parameters.rb:11:14:11:19 | pizzas |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:40:25:43 | name | parameters.rb:26:8:26:11 | name |
|
||||
| scopes.rb:9:9:18:3 | <captured> | scopes.rb:7:1:7:1 | a | scopes.rb:10:9:10:9 | a | scopes.rb:11:4:11:4 | a |
|
||||
| scopes.rb:27:1:27:5 | ... = ... | scopes.rb:27:1:27:1 | x | scopes.rb:28:8:28:8 | x | scopes.rb:31:10:31:10 | x |
|
||||
|
||||
@@ -51,18 +51,18 @@ variableAccess
|
||||
| parameters.rb:3:9:3:9 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | do ... end |
|
||||
| parameters.rb:4:9:4:9 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | do ... end |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:7:25:7:31 | *pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:8:6:8:11 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:9:25:9:30 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:11:14:11:19 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:11:41:11:46 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | order_pizza |
|
||||
| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | print_map |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | print_map |
|
||||
| parameters.rb:16:3:16:5 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | print_map |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | do ... end |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | do ... end |
|
||||
| parameters.rb:17:13:17:15 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | do ... end |
|
||||
| parameters.rb:17:22:17:26 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | do ... end |
|
||||
| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | call_block |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | call_block |
|
||||
| parameters.rb:22:3:22:7 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | call_block |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | opt_param |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | opt_param |
|
||||
@@ -239,11 +239,11 @@ implicitWrite
|
||||
| parameters.rb:1:14:1:14 | x |
|
||||
| parameters.rb:1:18:1:18 | y |
|
||||
| parameters.rb:7:17:7:22 | client |
|
||||
| parameters.rb:7:25:7:31 | *pizzas |
|
||||
| parameters.rb:15:15:15:19 | **map |
|
||||
| parameters.rb:7:26:7:31 | pizzas |
|
||||
| parameters.rb:15:17:15:19 | map |
|
||||
| parameters.rb:16:16:16:18 | key |
|
||||
| parameters.rb:16:21:16:25 | value |
|
||||
| parameters.rb:21:16:21:21 | &block |
|
||||
| parameters.rb:21:17:21:21 | block |
|
||||
| parameters.rb:25:15:25:18 | name |
|
||||
| parameters.rb:25:33:25:36 | size |
|
||||
| parameters.rb:30:15:30:19 | first |
|
||||
|
||||
Reference in New Issue
Block a user