Merge pull request #156 from github/hvitved/ipa-ast

Make external `AstNode` an IPA type
This commit is contained in:
Tom Hvitved
2021-03-17 22:23:05 +01:00
committed by GitHub
40 changed files with 2472 additions and 3208 deletions

View File

@@ -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() }
}

View File

@@ -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() }
}

View File

@@ -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" }
}

View File

@@ -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()
}
}

View File

@@ -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(_) }
}

View File

@@ -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() }
}

View File

@@ -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" }
}

View File

@@ -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())
)
}
}

View File

@@ -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" }
}

View File

@@ -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() }
}

View File

@@ -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(_) }
}

View File

@@ -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 }

View File

@@ -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" }
}

View File

@@ -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() }
}

View File

@@ -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;

View File

@@ -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()
}
}
}

View File

@@ -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()) }
}
}

View File

@@ -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()
}
}
}

View File

@@ -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(_)
}
}
}

View File

@@ -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 { }
}

View File

@@ -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 = "{ ... }" }
}
}

View File

@@ -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)
}
}
}

View File

@@ -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 { }
}

View File

@@ -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 }
}
}

View File

@@ -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(_)
}
}
}

View File

@@ -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)
)
}

View File

@@ -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" }
}
}

View File

@@ -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) }
}

View File

@@ -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) {

View File

@@ -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]

View File

@@ -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))
)
}
}

View File

@@ -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()
}
/**

View File

@@ -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

View File

@@ -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 }
}

View File

@@ -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)
)

View File

@@ -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) {

View File

@@ -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] ... + ...

View File

@@ -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)

View File

@@ -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 |

View File

@@ -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 |