Merge pull request #7154 from aibaars/ruby-pattern-matching

Ruby: pattern matching
This commit is contained in:
Arthur Baars
2021-12-01 12:47:22 +01:00
committed by GitHub
33 changed files with 4782 additions and 150 deletions

BIN
ruby/Cargo.lock generated

Binary file not shown.

View File

@@ -11,7 +11,7 @@ flate2 = "1.0"
node-types = { path = "../node-types" }
tree-sitter = "0.19"
tree-sitter-embedded-template = "0.19"
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "bb6a42e42b048627a74a127d3e0184c1eef01de9" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "951799c6780deaabb0666b846cb7ad4eab627bbb" }
clap = "2.33"
tracing = "0.1"
tracing-subscriber = { version = "0.2", features = ["env-filter"] }

View File

@@ -12,4 +12,4 @@ node-types = { path = "../node-types" }
tracing = "0.1"
tracing-subscriber = { version = "0.2", features = ["env-filter"] }
tree-sitter-embedded-template = "0.19"
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "bb6a42e42b048627a74a127d3e0184c1eef01de9" }
tree-sitter-ruby = { git = "https://github.com/tree-sitter/tree-sitter-ruby.git", rev = "951799c6780deaabb0666b846cb7ad4eab627bbb" }

View File

@@ -1,5 +1,6 @@
private import codeql.ruby.AST
private import internal.AST
private import internal.Control
private import internal.TreeSitter
/**
@@ -308,13 +309,36 @@ class TernaryIfExpr extends ConditionalExpr, TTernaryIfExpr {
}
}
class CaseExpr extends ControlExpr, TCaseExpr {
private Ruby::Case g;
CaseExpr() { this = TCaseExpr(g) }
final override string getAPrimaryQlClass() { result = "CaseExpr" }
/**
* A `case` statement. There are three forms of `case` statements:
* ```rb
* # a value-less case expression acting like an if-elsif expression:
* case
* when x == 0 then puts "zero"
* when x > 0 then puts "positive"
* else puts "negative"
* end
*
* # a case expression that matches a value using `when` clauses:
* case value
* when 1, 2 then puts "a is one or two"
* when 3 then puts "a is three"
* else puts "I don't know what a is"
* end
*
* # a case expression that matches a value against patterns using `in` clauses:
* config = {db: {user: 'admin', password: 'abc123'}}
* case config
* in db: {user:} # matches subhash and puts matched value in variable user
* puts "Connect with user '#{user}'"
* in connection: {username: } unless username == 'admin'
* puts "Connect with user '#{username}'"
* else
* puts "Unrecognized structure of config"
* end
* ```
*/
class CaseExpr extends ControlExpr instanceof CaseExprImpl {
/**
* Gets the expression being compared, if any. For example, `foo` in the following example.
* ```rb
@@ -334,22 +358,25 @@ class CaseExpr extends ControlExpr, TCaseExpr {
* end
* ```
*/
final Expr getValue() { toGenerated(result) = g.getValue() }
final Expr getValue() { result = super.getValue() }
/**
* Gets the `n`th branch of this case expression, either a `WhenExpr` or a
* `StmtSequence`.
* Gets the `n`th branch of this case expression, either a `WhenExpr`, an
* `InClause`, or a `StmtSequence`.
*/
final Expr getBranch(int n) { toGenerated(result) = g.getChild(n) }
final Expr getBranch(int n) { result = super.getBranch(n) }
/**
* Gets a branch of this case expression, either a `WhenExpr` or an
* `ElseExpr`.
* Gets a branch of this case expression, either a `WhenExpr`, an
* `InClause`, or a `StmtSequence`.
*/
final Expr getABranch() { result = this.getBranch(_) }
/** Gets the `n`th `when` branch of this case expression. */
deprecated final WhenExpr getWhenBranch(int n) { result = this.getBranch(n) }
/** Gets a `when` branch of this case expression. */
final WhenExpr getAWhenBranch() { result = this.getABranch() }
deprecated final WhenExpr getAWhenBranch() { result = this.getABranch() }
/** Gets the `else` branch of this case expression, if any. */
final StmtSequence getElseBranch() { result = this.getABranch() }
@@ -359,14 +386,18 @@ class CaseExpr extends ControlExpr, TCaseExpr {
*/
final int getNumberOfBranches() { result = count(this.getBranch(_)) }
final override string getAPrimaryQlClass() { result = "CaseExpr" }
final override string toString() { result = "case ..." }
override AstNode getAChild(string pred) {
result = super.getAChild(pred)
result = ControlExpr.super.getAChild(pred)
or
pred = "getValue" and result = this.getValue()
or
pred = "getBranch" and result = this.getBranch(_)
or
pred = "getElseBranch" and result = this.getElseBranch()
}
}
@@ -422,6 +453,81 @@ class WhenExpr extends Expr, TWhenExpr {
}
}
/**
* An `in` clause of a `case` expression.
* ```rb
* case foo
* in [ a ] then a
* end
* ```
*/
class InClause extends Expr, TInClause {
private Ruby::InClause g;
InClause() { this = TInClause(g) }
final override string getAPrimaryQlClass() { result = "InClause" }
/** Gets the body of this case-in expression. */
final Stmt getBody() { toGenerated(result) = g.getBody() }
/**
* Gets the pattern in this case-in expression. In the
* following example, the pattern is `Point{ x:, y: }`.
* ```rb
* case foo
* in Point{ x:, y: }
* x + y
* end
* ```
*/
final CasePattern getPattern() { toGenerated(result) = g.getPattern() }
/**
* Gets the pattern guard condition in this case-in expression. In the
* following example, there are two pattern guard conditions `x > 10` and `x < 0`.
* ```rb
* case foo
* in [ x ] if x > 10 then ...
* in [ x ] unless x < 0 then ...
* end
* ```
*/
final Expr getCondition() { toGenerated(result) = g.getGuard().getAFieldOrChild() }
/**
* Holds if the pattern guard in this case-in expression is an `if` condition. For example:
* ```rb
* case foo
* in [ x ] if x > 10 then ...
* end
* ```
*/
predicate hasIfCondition() { g.getGuard() instanceof Ruby::IfGuard }
/**
* Holds if the pattern guard in this case-in expression is an `unless` condition. For example:
* ```rb
* case foo
* in [ x ] unless x < 10 then ...
* end
* ```
*/
predicate hasUnlessCondition() { g.getGuard() instanceof Ruby::UnlessGuard }
final override string toString() { result = "in ... then ..." }
override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getBody" and result = this.getBody()
or
pred = "getPattern" and result = this.getPattern()
or
pred = "getCondition" and result = this.getCondition()
}
}
/**
* A loop. That is, a `for` loop, a `while` or `until` loop, or their
* expression-modifier variants.

View File

@@ -223,6 +223,40 @@ private class FalseLiteral extends BooleanLiteral, TFalseLiteral {
final override predicate isFalse() { any() }
}
/**
* An `__ENCODING__` literal.
*/
class EncodingLiteral extends Literal, TEncoding {
final override string getAPrimaryQlClass() { result = "EncodingLiteral" }
final override string toString() { result = "__ENCODING__" }
// TODO: return the encoding defined by a magic encoding: comment, if any.
override string getValueText() { result = "UTF-8" }
}
/**
* A `__LINE__` literal.
*/
class LineLiteral extends Literal, TLine {
final override string getAPrimaryQlClass() { result = "LineLiteral" }
final override string toString() { result = "__LINE__" }
override string getValueText() { result = this.getLocation().getStartLine().toString() }
}
/**
* A `__FILE__` literal.
*/
class FileLiteral extends Literal, TFile {
final override string getAPrimaryQlClass() { result = "FileLiteral" }
final override string toString() { result = "__FILE__" }
override string getValueText() { result = this.getLocation().getFile().getAbsolutePath() }
}
/**
* The base class for a component of a string: `StringTextComponent`,
* `StringEscapeSequenceComponent`, or `StringInterpolationComponent`.

View File

@@ -131,6 +131,23 @@ class HashSplatParameter extends NamedParameter, THashSplatParameter {
final override string getName() { result = g.getName().getValue() }
}
/**
* A `nil` hash splat (`**nil`) indicating that there are no keyword parameters or keyword patterns.
* For example:
* ```rb
* def foo(bar, **nil)
* case bar
* in { x:, **nil } then puts x
* end
* end
* ```
*/
class HashSplatNilParameter extends Parameter, THashSplatNilParameter {
final override string getAPrimaryQlClass() { result = "HashSplatNilParameter" }
final override string toString() { result = "**nil" }
}
/**
* A keyword parameter, including a default value if the parameter is optional.
* For example, in the following example, `foo` is a keyword parameter with a

View File

@@ -97,3 +97,322 @@ class TuplePattern extends Pattern, TTuplePattern {
override AstNode getAChild(string pred) { pred = "getElement" and result = this.getElement(_) }
}
private class TPatternNode =
TArrayPattern or TFindPattern or THashPattern or TAlternativePattern or TAsPattern or
TVariableReferencePattern;
private class TPattern =
TPatternNode or TLiteral or TLambda or TConstantAccess or TLocalVariableAccess or
TUnaryArithmeticOperation;
/**
* A pattern used in a `case-in` expression. For example
* ```rb
* case expr
* in [ x ] then ...
* in Point(a:, b:) then ...
* in Integer => x then ...
* end
* ```
*/
class CasePattern extends AstNode, TPattern {
CasePattern() { casePattern(toGenerated(this)) }
}
/**
* An array pattern, for example:
* ```rb
* in []
* in ["first", Integer => x, "last"]
* in ["a", Integer => x, *]
* in ["a", Integer => x, ]
* in [1, 2, *x, 7, 8]
* in [*init, 7, 8]
* in List["a", Integer => x, *tail]
* ```
*/
class ArrayPattern extends CasePattern, TArrayPattern {
private Ruby::ArrayPattern g;
ArrayPattern() { this = TArrayPattern(g) }
/** Gets the class this pattern matches objects against, if any. */
ConstantReadAccess getClass() { toGenerated(result) = g.getClass() }
/**
* Gets the `n`th element of this list pattern's prefix, i.e. the elements `1, ^two, 3`
* in the following examples:
* ```
* in [ 1, ^two, 3 ]
* in [ 1, ^two, 3, ]
* in [ 1, ^two, 3, *, 4 , 5]
* in [ 1, ^two, 3, *more]
* ```
*/
CasePattern getPrefixElement(int n) {
toGenerated(result) = g.getChild(n) and
(
n < this.restIndex()
or
not exists(restIndex())
)
}
/**
* Gets the `n`th element of this list pattern's suffix, i.e. the elements `4, 5`
* in the following examples:
* ```
* in [ *, 4, 5 ]
* in [ 1, 2, 3, *middle, 4 , 5]
* ```
*/
CasePattern getSuffixElement(int n) { toGenerated(result) = g.getChild(n + this.restIndex() + 1) }
/**
* Gets the variable of the rest token, if any. For example `middle` in `the following array pattern.
* ```rb
* [ 1, 2, 3, *middle, 4 , 5]
* ```
*/
LocalVariableWriteAccess getRestVariableAccess() {
toGenerated(result) = g.getChild(restIndex()).(Ruby::SplatParameter).getName()
}
/**
* Holds if this pattern permits any unmatched remaining elements, i.e. the pattern does not have a trailing `,`
* and does not contain a rest token (`*` or `*name`) either.
*/
predicate allowsUnmatchedElements() { not exists(this.restIndex()) }
private int restIndex() { g.getChild(result) instanceof Ruby::SplatParameter }
final override string getAPrimaryQlClass() { result = "ArrayPattern" }
final override string toString() { result = "[ ..., * ]" }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getClass" and result = this.getClass()
or
pred = "getPrefixElement" and result = this.getPrefixElement(_)
or
pred = "getSuffixElement" and result = this.getSuffixElement(_)
or
pred = "getRestVariableAccess" and result = this.getRestVariableAccess()
}
}
/**
* A find pattern, for example:
* ```rb
* in [*, "a", Integer => x, *]
* in List[*init, "a", Integer => x, *tail]
* in List[*, "a", Integer => x, *]
* ```
*/
class FindPattern extends CasePattern, TFindPattern {
private Ruby::FindPattern g;
FindPattern() { this = TFindPattern(g) }
/** Gets the class this pattern matches objects against, if any. */
ConstantReadAccess getClass() { toGenerated(result) = g.getClass() }
/** Gets the `n`th element of this list pattern. */
CasePattern getElement(int n) { toGenerated(result) = g.getChild(n + 1) }
/** Gets an element of this list pattern. */
CasePattern getAnElement() { result = this.getElement(_) }
/**
* Gets the variable for the prefix of this list pattern, if any. For example `init` in:
* ```rb
* in List[*init, "a", Integer => x, *tail]
* ```
*/
LocalVariableWriteAccess getPrefixVariableAccess() {
toGenerated(result) = g.getChild(0).(Ruby::SplatParameter).getName()
}
/**
* Gets the variable for the suffix of this list pattern, if any. For example `tail` in:
* ```rb
* in List[*init, "a", Integer => x, *tail]
* ```
*/
LocalVariableWriteAccess getSuffixVariableAccess() {
toGenerated(result) = max(int i | | g.getChild(i) order by i).(Ruby::SplatParameter).getName()
}
final override string getAPrimaryQlClass() { result = "FindPattern" }
final override string toString() { result = "[ *,...,* ]" }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getClass" and result = this.getClass()
or
pred = "getElement" and result = this.getElement(_)
or
pred = "getPrefixVariableAccess" and result = this.getPrefixVariableAccess()
or
pred = "getSuffixVariableAccess" and result = this.getSuffixVariableAccess()
}
}
/**
* A hash pattern, for example:
* ```rb
* in {}
* in { a: 1 }
* in { a: 1, **rest }
* in { a: 1, **nil }
* in Node{ label: , children: [] }
* ```
*/
class HashPattern extends CasePattern, THashPattern {
private Ruby::HashPattern g;
HashPattern() { this = THashPattern(g) }
/** Gets the class this pattern matches objects against, if any. */
ConstantReadAccess getClass() { toGenerated(result) = g.getClass() }
private Ruby::KeywordPattern keyValuePair(int n) { result = g.getChild(n) }
/** Gets the key of the `n`th pair. */
StringlikeLiteral getKey(int n) { toGenerated(result) = keyValuePair(n).getKey() }
/** Gets the value of the `n`th pair. */
CasePattern getValue(int n) { toGenerated(result) = keyValuePair(n).getValue() }
/** Gets the value for a given key name. */
CasePattern getValueByKey(string key) {
exists(int i | key = this.getKey(i).getValueText() and result = this.getValue(i))
}
/**
* Gets the variable of the keyword rest token, if any. For example `rest` in:
* ```rb
* in { a: 1, **rest }
* ```
*/
LocalVariableWriteAccess getRestVariableAccess() {
toGenerated(result) =
max(int i | | g.getChild(i) order by i).(Ruby::HashSplatParameter).getName()
}
/**
* Holds if this pattern is terminated by `**nil` indicating that the pattern does not permit
* any unmatched remaining pairs.
*/
predicate allowsUnmatchedElements() { g.getChild(_) instanceof Ruby::HashSplatNil }
final override string getAPrimaryQlClass() { result = "HashPattern" }
final override string toString() { result = "{ ..., ** }" }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getClass" and result = this.getClass()
or
pred = "getKey" and result = this.getKey(_)
or
pred = "getValue" and result = this.getValue(_)
or
pred = "getRestVariableAccess" and result = this.getRestVariableAccess()
}
}
/**
* A composite pattern matching one of the given sub-patterns, for example:
* ```rb
* in 1 | 2 | 3
* ```
*/
class AlternativePattern extends CasePattern, TAlternativePattern {
private Ruby::AlternativePattern g;
AlternativePattern() { this = TAlternativePattern(g) }
/** Gets the `n`th alternative of this pattern. */
CasePattern getAlternative(int n) { toGenerated(result) = g.getAlternatives(n) }
/** Gets an alternative of this pattern. */
CasePattern getAnAlternative() { result = this.getAlternative(_) }
final override string getAPrimaryQlClass() { result = "AlternativePattern" }
final override string toString() { result = "... | ..." }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getAlternative" and result = this.getAlternative(_)
}
}
/**
* A pattern match that binds to the specified local variable, for example `Integer => a`
* in the following:
* ```rb
* case 1
* in Integer => a then puts "#{a} is an integer value"
* end
* ```
*/
class AsPattern extends CasePattern, TAsPattern {
private Ruby::AsPattern g;
AsPattern() { this = TAsPattern(g) }
/** Gets the underlying pattern. */
CasePattern getPattern() { toGenerated(result) = g.getValue() }
/** Gets the variable access for this pattern. */
LocalVariableWriteAccess getVariableAccess() { toGenerated(result) = g.getName() }
final override string getAPrimaryQlClass() { result = "AsPattern" }
final override string toString() { result = "... => ..." }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getPattern" and result = this.getPattern()
or
pred = "getVariableAccess" and result = this.getVariableAccess()
}
}
/**
* A variable reference in a pattern, i.e. `^x` in the following example:
* ```rb
* x = 10
* case expr
* in ^x then puts "ok"
* end
* ```
*/
class VariableReferencePattern extends CasePattern, TVariableReferencePattern {
private Ruby::VariableReferencePattern g;
VariableReferencePattern() { this = TVariableReferencePattern(g) }
/** Gets the variable access corresponding to this variable reference pattern. */
LocalVariableReadAccess getVariableAccess() { toGenerated(result) = g.getName() }
final override string getAPrimaryQlClass() { result = "VariableReferencePattern" }
final override string toString() { result = "^..." }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getVariableAccess" and result = this.getVariableAccess()
}
}

View File

@@ -2,6 +2,7 @@ import codeql.Locations
private import TreeSitter
private import codeql.ruby.ast.internal.Call
private import codeql.ruby.ast.internal.Parameter
private import codeql.ruby.ast.internal.Pattern
private import codeql.ruby.ast.internal.Variable
private import codeql.ruby.AST as AST
private import Synthesis
@@ -30,6 +31,7 @@ private module Cached {
TAddExprReal(Ruby::Binary g) { g instanceof @ruby_binary_plus } or
TAddExprSynth(AST::AstNode parent, int i) { mkSynthChild(AddExprKind(), parent, i) } or
TAliasStmt(Ruby::Alias g) or
TAlternativePattern(Ruby::AlternativePattern g) or
TArgumentList(Ruby::AstNode g) {
(
g.getParent() instanceof Ruby::Break or
@@ -44,6 +46,7 @@ private module Cached {
g instanceof Ruby::RightAssignmentList
)
} or
TArrayPattern(Ruby::ArrayPattern g) or
TAssignAddExpr(Ruby::OperatorAssignment g) { g instanceof @ruby_operator_assignment_plusequal } or
TAssignBitwiseAndExpr(Ruby::OperatorAssignment g) {
g instanceof @ruby_operator_assignment_ampersandequal
@@ -77,6 +80,7 @@ private module Cached {
g instanceof @ruby_operator_assignment_ranglerangleequal
} or
TAssignSubExpr(Ruby::OperatorAssignment g) { g instanceof @ruby_operator_assignment_minusequal } or
TAsPattern(Ruby::AsPattern g) or
TBareStringLiteral(Ruby::BareString g) or
TBareSymbolLiteral(Ruby::BareSymbol g) or
TBeginBlock(Ruby::BeginBlock g) or
@@ -98,6 +102,7 @@ private module Cached {
TBreakStmt(Ruby::Break g) or
TCaseEqExpr(Ruby::Binary g) { g instanceof @ruby_binary_equalequalequal } or
TCaseExpr(Ruby::Case g) or
TCaseMatch(Ruby::CaseMatch g) or
TCharacterLiteral(Ruby::Character g) or
TClassDeclaration(Ruby::Class g) or
TClassVariableAccessReal(Ruby::ClassVariable g, AST::ClassVariable v) {
@@ -124,12 +129,15 @@ private module Cached {
TElse(Ruby::Else g) or
TElsif(Ruby::Elsif g) or
TEmptyStmt(Ruby::EmptyStatement g) or
TEncoding(Ruby::Encoding g) or
TEndBlock(Ruby::EndBlock g) or
TEnsure(Ruby::Ensure g) or
TEqExpr(Ruby::Binary g) { g instanceof @ruby_binary_equalequal } or
TExponentExprReal(Ruby::Binary g) { g instanceof @ruby_binary_starstar } or
TExponentExprSynth(AST::AstNode parent, int i) { mkSynthChild(ExponentExprKind(), parent, i) } or
TFalseLiteral(Ruby::False g) or
TFile(Ruby::File g) or
TFindPattern(Ruby::FindPattern g) or
TFloatLiteral(Ruby::Float g) { not any(Ruby::Rational r).getChild() = g } or
TForExpr(Ruby::For g) or
TForwardParameter(Ruby::ForwardParameter g) or
@@ -144,12 +152,17 @@ private module Cached {
} or
THashKeySymbolLiteral(Ruby::HashKeySymbol g) or
THashLiteral(Ruby::Hash g) or
THashPattern(Ruby::HashPattern g) or
THashSplatExpr(Ruby::HashSplatArgument g) or
THashSplatParameter(Ruby::HashSplatParameter g) or
THashSplatNilParameter(Ruby::HashSplatNil g) { not g.getParent() instanceof Ruby::HashPattern } or
THashSplatParameter(Ruby::HashSplatParameter g) {
not g.getParent() instanceof Ruby::HashPattern
} or
THereDoc(Ruby::HeredocBeginning g) or
TIdentifierMethodCall(Ruby::Identifier g) { isIdentifierMethodCall(g) } or
TIf(Ruby::If g) or
TIfModifierExpr(Ruby::IfModifier g) or
TInClause(Ruby::InClause g) or
TInstanceVariableAccessReal(Ruby::InstanceVariable g, AST::InstanceVariable v) {
InstanceVariableAccess::range(g, v)
} or
@@ -166,6 +179,7 @@ private module Cached {
TLShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(LShiftExprKind(), parent, i) } or
TLTExpr(Ruby::Binary g) { g instanceof @ruby_binary_langle } or
TLambda(Ruby::Lambda g) or
TLine(Ruby::Line g) or
TLeftAssignmentList(Ruby::LeftAssignmentList g) or
TLocalVariableAccessReal(Ruby::Identifier g, TLocalVariableReal v) {
LocalVariableAccess::range(g, v)
@@ -229,6 +243,10 @@ private module Cached {
vcall(g)
or
explicitAssignmentNode(g, _)
or
casePattern(g)
or
classReferencePattern(g)
)
} or
TScopeResolutionMethodCall(Ruby::ScopeResolution g, Ruby::Identifier i) {
@@ -248,7 +266,10 @@ private module Cached {
TSpaceshipExpr(Ruby::Binary g) { g instanceof @ruby_binary_langleequalrangle } or
TSplatExprReal(Ruby::SplatArgument g) or
TSplatExprSynth(AST::AstNode parent, int i) { mkSynthChild(SplatExprKind(), parent, i) } or
TSplatParameter(Ruby::SplatParameter g) or
TSplatParameter(Ruby::SplatParameter g) {
not g.getParent() instanceof Ruby::ArrayPattern and
not g.getParent() instanceof Ruby::FindPattern
} or
TStmtSequenceSynth(AST::AstNode parent, int i) { mkSynthChild(StmtSequenceKind(), parent, i) } or
TStringArrayLiteral(Ruby::StringArray g) or
TStringConcatenation(Ruby::ChainedString g) or
@@ -269,6 +290,10 @@ private module Cached {
vcall(g)
or
explicitAssignmentNode(g, _)
or
casePattern(g)
or
classReferencePattern(g)
} or
TTokenMethodName(MethodName::Token g) { MethodName::range(g) } or
TTokenSuperCall(Ruby::Super g) { vcall(g) } or
@@ -282,34 +307,38 @@ private module Cached {
TUnlessModifierExpr(Ruby::UnlessModifier g) or
TUntilExpr(Ruby::Until g) or
TUntilModifierExpr(Ruby::UntilModifier g) or
TVariableReferencePattern(Ruby::VariableReferencePattern g) or
TWhenExpr(Ruby::When g) or
TWhileExpr(Ruby::While g) or
TWhileModifierExpr(Ruby::WhileModifier g) or
TYieldCall(Ruby::Yield g)
class TAstNodeReal =
TAddExprReal or TAliasStmt or TArgumentList or TAssignAddExpr or TAssignBitwiseAndExpr or
TAssignBitwiseOrExpr or TAssignBitwiseXorExpr or TAssignDivExpr or TAssignExponentExpr or
TAssignExprReal or TAssignLShiftExpr or TAssignLogicalAndExpr or TAssignLogicalOrExpr or
TAssignModuloExpr or TAssignMulExpr or TAssignRShiftExpr or TAssignSubExpr or
TBareStringLiteral or TBareSymbolLiteral or TBeginBlock or TBeginExpr or
TBitwiseAndExprReal or TBitwiseOrExprReal or TBitwiseXorExprReal or TBlockArgument or
TBlockParameter or TBraceBlockReal or TBreakStmt or TCaseEqExpr or TCaseExpr or
TAddExprReal or TAliasStmt or TAlternativePattern or TArgumentList or TArrayPattern or
TAsPattern or TAssignAddExpr or TAssignBitwiseAndExpr or TAssignBitwiseOrExpr or
TAssignBitwiseXorExpr or TAssignDivExpr or TAssignExponentExpr or TAssignExprReal or
TAssignLShiftExpr or TAssignLogicalAndExpr or TAssignLogicalOrExpr or TAssignModuloExpr or
TAssignMulExpr or TAssignRShiftExpr or TAssignSubExpr or TBareStringLiteral or
TBareSymbolLiteral or TBeginBlock or TBeginExpr or TBitwiseAndExprReal or
TBitwiseOrExprReal or TBitwiseXorExprReal or TBlockArgument or TBlockParameter or
TBraceBlockReal or TBreakStmt or TCaseEqExpr or TCaseExpr or TCaseMatch or
TCharacterLiteral or TClassDeclaration or TClassVariableAccessReal or TComplementExpr or
TComplexLiteral or TDefinedExpr or TDelimitedSymbolLiteral or TDestructuredLeftAssignment or
TDivExprReal or TDo or TDoBlock or TElementReference or TElse or TElsif or TEmptyStmt or
TEndBlock or TEnsure or TEqExpr or TExponentExprReal or TFalseLiteral or TFloatLiteral or
TForExpr or TForwardParameter or TForwardArgument or TGEExpr or TGTExpr or
TGlobalVariableAccessReal or THashKeySymbolLiteral or THashLiteral or THashSplatExpr or
THashSplatParameter or THereDoc or TIdentifierMethodCall or TIf or TIfModifierExpr or
TInstanceVariableAccessReal or TIntegerLiteralReal or TKeywordParameter or TLEExpr or
TLShiftExprReal or TLTExpr or TLambda or TLeftAssignmentList or TLocalVariableAccessReal or
TLogicalAndExprReal or TLogicalOrExprReal or TMethod or TModuleDeclaration or
TModuloExprReal or TMulExprReal or TNEExpr or TNextStmt or TNilLiteral or
TNoRegExpMatchExpr or TNotExpr or TOptionalParameter or TPair or TParenthesizedExpr or
TRShiftExprReal or TRangeLiteralReal or TRationalLiteral or TRedoStmt or TRegExpLiteral or
TRegExpMatchExpr or TRegularArrayLiteral or TRegularMethodCall or TRegularStringLiteral or
TRegularSuperCall or TRescueClause or TRescueModifierExpr or TRetryStmt or TReturnStmt or
TEncoding or TEndBlock or TEnsure or TEqExpr or TExponentExprReal or TFalseLiteral or
TFile or TFindPattern or TFloatLiteral or TForExpr or TForwardParameter or
TForwardArgument or TGEExpr or TGTExpr or TGlobalVariableAccessReal or
THashKeySymbolLiteral or THashLiteral or THashPattern or THashSplatExpr or
THashSplatNilParameter or THashSplatParameter or THereDoc or TIdentifierMethodCall or TIf or
TIfModifierExpr or TInClause or TInstanceVariableAccessReal or TIntegerLiteralReal or
TKeywordParameter or TLEExpr or TLShiftExprReal or TLTExpr or TLambda or
TLeftAssignmentList or TLine or TLocalVariableAccessReal or TLogicalAndExprReal or
TLogicalOrExprReal or TMethod or TModuleDeclaration or TModuloExprReal or TMulExprReal or
TNEExpr or TNextStmt or TNilLiteral or TNoRegExpMatchExpr or TNotExpr or
TOptionalParameter or TPair or TParenthesizedExpr or TRShiftExprReal or TRangeLiteralReal or
TRationalLiteral or TRedoStmt or TRegExpLiteral or TRegExpMatchExpr or
TRegularArrayLiteral or TRegularMethodCall or TRegularStringLiteral or TRegularSuperCall or
TRescueClause or TRescueModifierExpr or TRetryStmt or TReturnStmt or
TScopeResolutionConstantAccess or TScopeResolutionMethodCall or TSelfReal or
TSimpleParameterReal or TSimpleSymbolLiteral or TSingletonClass or TSingletonMethod or
TSpaceshipExpr or TSplatExprReal or TSplatParameter or TStringArrayLiteral or
@@ -318,7 +347,7 @@ private module Cached {
TTernaryIfExpr or TThen or TTokenConstantAccess or TTokenMethodName or TTokenSuperCall or
TToplevel or TTrueLiteral or TTuplePatternParameter or TUnaryMinusExpr or TUnaryPlusExpr or
TUndefStmt or TUnlessExpr or TUnlessModifierExpr or TUntilExpr or TUntilModifierExpr or
TWhenExpr or TWhileExpr or TWhileModifierExpr or TYieldCall;
TVariableReferencePattern or TWhenExpr or TWhileExpr or TWhileModifierExpr or TYieldCall;
class TAstNodeSynth =
TAddExprSynth or TAssignExprSynth or TBitwiseAndExprSynth or TBitwiseOrExprSynth or
@@ -339,7 +368,10 @@ private module Cached {
Ruby::AstNode toGenerated(TAstNodeReal n) {
n = TAddExprReal(result) or
n = TAliasStmt(result) or
n = TAlternativePattern(result) or
n = TArgumentList(result) or
n = TArrayPattern(result) or
n = TAsPattern(result) or
n = TAssignAddExpr(result) or
n = TAssignBitwiseAndExpr(result) or
n = TAssignBitwiseOrExpr(result) or
@@ -347,9 +379,9 @@ private module Cached {
n = TAssignDivExpr(result) or
n = TAssignExponentExpr(result) or
n = TAssignExprReal(result) or
n = TAssignLShiftExpr(result) or
n = TAssignLogicalAndExpr(result) or
n = TAssignLogicalOrExpr(result) or
n = TAssignLShiftExpr(result) or
n = TAssignModuloExpr(result) or
n = TAssignMulExpr(result) or
n = TAssignRShiftExpr(result) or
@@ -367,6 +399,7 @@ private module Cached {
n = TBreakStmt(result) or
n = TCaseEqExpr(result) or
n = TCaseExpr(result) or
n = TCaseMatch(result) or
n = TCharacterLiteral(result) or
n = TClassDeclaration(result) or
n = TClassVariableAccessReal(result, _) or
@@ -376,43 +409,50 @@ private module Cached {
n = TDelimitedSymbolLiteral(result) or
n = TDestructuredLeftAssignment(result) or
n = TDivExprReal(result) or
n = TDo(result) or
n = TDoBlock(result) or
n = TDo(result) or
n = TElementReference(result) or
n = TElse(result) or
n = TElsif(result) or
n = TEmptyStmt(result) or
n = TEncoding(result) or
n = TEndBlock(result) or
n = TEnsure(result) or
n = TEqExpr(result) or
n = TExponentExprReal(result) or
n = TFalseLiteral(result) or
n = TFile(result) or
n = TFindPattern(result) or
n = TFloatLiteral(result) or
n = TForExpr(result) or
n = TForwardArgument(result) or
n = TForwardParameter(result) or
n = TGEExpr(result) or
n = TGTExpr(result) or
n = TGlobalVariableAccessReal(result, _) or
n = TGTExpr(result) or
n = THashKeySymbolLiteral(result) or
n = THashLiteral(result) or
n = THashPattern(result) or
n = THashSplatExpr(result) or
n = THashSplatNilParameter(result) or
n = THashSplatParameter(result) or
n = THereDoc(result) or
n = TIdentifierMethodCall(result) or
n = TIf(result) or
n = TIfModifierExpr(result) or
n = TIf(result) or
n = TInClause(result) or
n = TInstanceVariableAccessReal(result, _) or
n = TIntegerLiteralReal(result) or
n = TKeywordParameter(result) or
n = TLEExpr(result) or
n = TLShiftExprReal(result) or
n = TLTExpr(result) or
n = TLambda(result) or
n = TLEExpr(result) or
n = TLeftAssignmentList(result) or
n = TLine(result) or
n = TLocalVariableAccessReal(result, _) or
n = TLogicalAndExprReal(result) or
n = TLogicalOrExprReal(result) or
n = TLShiftExprReal(result) or
n = TLTExpr(result) or
n = TMethod(result) or
n = TModuleDeclaration(result) or
n = TModuloExprReal(result) or
@@ -425,7 +465,6 @@ private module Cached {
n = TOptionalParameter(result) or
n = TPair(result) or
n = TParenthesizedExpr(result) or
n = TRShiftExprReal(result) or
n = TRangeLiteralReal(result) or
n = TRationalLiteral(result) or
n = TRedoStmt(result) or
@@ -439,6 +478,7 @@ private module Cached {
n = TRescueModifierExpr(result) or
n = TRetryStmt(result) or
n = TReturnStmt(result) or
n = TRShiftExprReal(result) or
n = TScopeResolutionConstantAccess(result, _) or
n = TScopeResolutionMethodCall(result, _) or
n = TSelfReal(result) or
@@ -472,6 +512,7 @@ private module Cached {
n = TUnlessModifierExpr(result) or
n = TUntilExpr(result) or
n = TUntilModifierExpr(result) or
n = TVariableReferencePattern(result) or
n = TWhenExpr(result) or
n = TWhileExpr(result) or
n = TWhileModifierExpr(result) or
@@ -582,6 +623,8 @@ TAstNodeReal fromGenerated(Ruby::AstNode n) { n = toGenerated(result) }
class TCall = TMethodCall or TYieldCall;
class TCase = TCaseExpr or TCaseMatch;
class TMethodCall =
TMethodCallSynth or TIdentifierMethodCall or TScopeResolutionMethodCall or TRegularMethodCall or
TElementReference or TSuperCall or TUnaryOperation or TBinaryOperation;
@@ -591,7 +634,7 @@ class TSuperCall = TTokenSuperCall or TRegularSuperCall;
class TConstantAccess =
TTokenConstantAccess or TScopeResolutionConstantAccess or TNamespace or TConstantReadAccessSynth;
class TControlExpr = TConditionalExpr or TCaseExpr or TLoop;
class TControlExpr = TConditionalExpr or TCaseExpr or TCaseMatch or TLoop;
class TConditionalExpr =
TIfExpr or TUnlessExpr or TIfModifierExpr or TUnlessModifierExpr or TTernaryIfExpr;
@@ -605,10 +648,10 @@ class TLoop = TConditionalLoop or TForExpr;
class TSelf = TSelfReal or TSelfSynth;
class TExpr =
TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or
TCall or TBlockArgument or TConstantAccess or TControlExpr or TWhenExpr or TLiteral or
TCallable or TVariableAccess or TStmtSequence or TOperation or TSimpleParameter or
TForwardArgument;
TSelf or TArgumentList or TInClause or TRescueClause or TRescueModifierExpr or TPair or
TStringConcatenation or TCall or TBlockArgument or TConstantAccess or TControlExpr or
TWhenExpr or TLiteral or TCallable or TVariableAccess or TStmtSequence or TOperation or
TSimpleParameter or TForwardArgument;
class TSplatExpr = TSplatExprReal or TSplatExprSynth;
@@ -619,8 +662,9 @@ class TStmtSequence =
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;
TEncoding or TFile or TLine or 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;
@@ -736,8 +780,8 @@ class TStmt =
class TReturningStmt = TReturnStmt or TBreakStmt or TNextStmt;
class TParameter =
TPatternParameter or TBlockParameter or THashSplatParameter or TKeywordParameter or
TOptionalParameter or TSplatParameter or TForwardParameter;
TPatternParameter or TBlockParameter or THashSplatParameter or THashSplatNilParameter or
TKeywordParameter or TOptionalParameter or TSplatParameter or TForwardParameter;
class TSimpleParameter = TSimpleParameterReal or TSimpleParameterSynth;

View File

@@ -0,0 +1,36 @@
private import TreeSitter
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST
abstract class CaseExprImpl extends ControlExpr, TCase {
abstract Expr getValue();
abstract Expr getBranch(int n);
}
class CaseWhenExpr extends CaseExprImpl, TCaseExpr {
private Ruby::Case g;
CaseWhenExpr() { this = TCaseExpr(g) }
final override Expr getValue() { toGenerated(result) = g.getValue() }
final override Expr getBranch(int n) {
toGenerated(result) = g.getChild(n) or
toGenerated(result) = g.getChild(n)
}
}
class CaseMatch extends CaseExprImpl, TCaseMatch {
private Ruby::CaseMatch g;
CaseMatch() { this = TCaseMatch(g) }
final override Expr getValue() { toGenerated(result) = g.getValue() }
final override Expr getBranch(int n) {
toGenerated(result) = g.getClauses(n)
or
n = count(g.getClauses(_)) and toGenerated(result) = g.getElse()
}
}

View File

@@ -30,3 +30,32 @@ class LeftAssignmentListImpl extends TuplePatternImpl, Ruby::LeftAssignmentList
)
}
}
/**
* Holds if `node` is a case pattern.
*/
predicate casePattern(Ruby::AstNode node) {
node = any(Ruby::InClause parent).getPattern()
or
node = any(Ruby::ArrayPattern parent).getChild(_).(Ruby::UnderscorePatternExpr)
or
node = any(Ruby::FindPattern parent).getChild(_).(Ruby::UnderscorePatternExpr)
or
node = any(Ruby::AlternativePattern parent).getAlternatives(_)
or
node = any(Ruby::AsPattern parent).getValue()
or
node = any(Ruby::KeywordPattern parent).getValue()
}
/**
* Holds if `node` is a class reference used in an
* array, find, or hash pattern.
*/
predicate classReferencePattern(Ruby::AstNode node) {
node = any(Ruby::ArrayPattern p).getClass()
or
node = any(Ruby::FindPattern p).getClass()
or
node = any(Ruby::HashPattern p).getClass()
}

View File

@@ -53,12 +53,26 @@ module Ruby {
class UnderscoreArg extends @ruby_underscore_arg, AstNode { }
class UnderscoreExpression extends @ruby_underscore_expression, AstNode { }
class UnderscoreLhs extends @ruby_underscore_lhs, AstNode { }
class UnderscoreMethodName extends @ruby_underscore_method_name, AstNode { }
class UnderscorePatternConstant extends @ruby_underscore_pattern_constant, AstNode { }
class UnderscorePatternExpr extends @ruby_underscore_pattern_expr, AstNode { }
class UnderscorePatternExprBasic extends @ruby_underscore_pattern_expr_basic, AstNode { }
class UnderscorePatternPrimitive extends @ruby_underscore_pattern_primitive, AstNode { }
class UnderscorePatternTopExprBody extends @ruby_underscore_pattern_top_expr_body, AstNode { }
class UnderscorePrimary extends @ruby_underscore_primary, AstNode { }
class UnderscoreSimpleNumeric extends @ruby_underscore_simple_numeric, AstNode { }
class UnderscoreStatement extends @ruby_underscore_statement, AstNode { }
class UnderscoreVariable extends @ruby_underscore_variable, AstNode { }
@@ -83,6 +97,23 @@ module Ruby {
}
}
/** A class representing `alternative_pattern` nodes. */
class AlternativePattern extends @ruby_alternative_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "AlternativePattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_alternative_pattern_def(this, result) }
/** Gets the node corresponding to the field `alternatives`. */
UnderscorePatternExprBasic getAlternatives(int i) {
ruby_alternative_pattern_alternatives(this, i, result)
}
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() { ruby_alternative_pattern_alternatives(this, _, result) }
}
/** A class representing `argument_list` nodes. */
class ArgumentList extends @ruby_argument_list, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -113,6 +144,46 @@ module Ruby {
override AstNode getAFieldOrChild() { ruby_array_child(this, _, result) }
}
/** A class representing `array_pattern` nodes. */
class ArrayPattern extends @ruby_array_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "ArrayPattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_array_pattern_def(this, result) }
/** Gets the node corresponding to the field `class`. */
UnderscorePatternConstant getClass() { ruby_array_pattern_class(this, result) }
/** Gets the `i`th child of this node. */
AstNode getChild(int i) { ruby_array_pattern_child(this, i, result) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_array_pattern_class(this, result) or ruby_array_pattern_child(this, _, result)
}
}
/** A class representing `as_pattern` nodes. */
class AsPattern extends @ruby_as_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "AsPattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_as_pattern_def(this, _, _, result) }
/** Gets the node corresponding to the field `name`. */
Identifier getName() { ruby_as_pattern_def(this, result, _, _) }
/** Gets the node corresponding to the field `value`. */
UnderscorePatternExpr getValue() { ruby_as_pattern_def(this, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_as_pattern_def(this, result, _, _) or ruby_as_pattern_def(this, _, result, _)
}
}
/** A class representing `assignment` nodes. */
class Assignment extends @ruby_assignment, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -202,7 +273,7 @@ module Ruby {
override L::Location getLocation() { ruby_binary_def(this, _, _, _, result) }
/** Gets the node corresponding to the field `left`. */
AstNode getLeft() { ruby_binary_def(this, result, _, _, _) }
UnderscoreExpression getLeft() { ruby_binary_def(this, result, _, _, _) }
/** Gets the node corresponding to the field `operator`. */
string getOperator() {
@@ -260,7 +331,7 @@ module Ruby {
}
/** Gets the node corresponding to the field `right`. */
AstNode getRight() { ruby_binary_def(this, _, _, result, _) }
UnderscoreExpression getRight() { ruby_binary_def(this, _, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -397,6 +468,31 @@ module Ruby {
}
}
/** A class representing `case_match` nodes. */
class CaseMatch extends @ruby_case_match, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "CaseMatch" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_case_match_def(this, _, result) }
/** Gets the node corresponding to the field `clauses`. */
InClause getClauses(int i) { ruby_case_match_clauses(this, i, result) }
/** Gets the node corresponding to the field `else`. */
Else getElse() { ruby_case_match_else(this, result) }
/** Gets the node corresponding to the field `value`. */
UnderscoreStatement getValue() { ruby_case_match_def(this, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_case_match_clauses(this, _, result) or
ruby_case_match_else(this, result) or
ruby_case_match_def(this, result, _)
}
}
/** A class representing `chained_string` nodes. */
class ChainedString extends @ruby_chained_string, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -638,6 +734,12 @@ module Ruby {
override string getAPrimaryQlClass() { result = "EmptyStatement" }
}
/** A class representing `encoding` tokens. */
class Encoding extends @ruby_token_encoding, Token {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "Encoding" }
}
/** A class representing `end_block` nodes. */
class EndBlock extends @ruby_end_block, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -710,6 +812,32 @@ module Ruby {
override string getAPrimaryQlClass() { result = "False" }
}
/** A class representing `file` tokens. */
class File extends @ruby_token_file, Token {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "File" }
}
/** A class representing `find_pattern` nodes. */
class FindPattern extends @ruby_find_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "FindPattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_find_pattern_def(this, result) }
/** Gets the node corresponding to the field `class`. */
UnderscorePatternConstant getClass() { ruby_find_pattern_class(this, result) }
/** Gets the `i`th child of this node. */
AstNode getChild(int i) { ruby_find_pattern_child(this, i, result) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_find_pattern_class(this, result) or ruby_find_pattern_child(this, _, result)
}
}
/** A class representing `float` tokens. */
class Float extends @ruby_token_float, Token {
/** Gets the name of the primary QL class for this element. */
@@ -780,6 +908,26 @@ module Ruby {
override string getAPrimaryQlClass() { result = "HashKeySymbol" }
}
/** A class representing `hash_pattern` nodes. */
class HashPattern extends @ruby_hash_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "HashPattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_hash_pattern_def(this, result) }
/** Gets the node corresponding to the field `class`. */
UnderscorePatternConstant getClass() { ruby_hash_pattern_class(this, result) }
/** Gets the `i`th child of this node. */
AstNode getChild(int i) { ruby_hash_pattern_child(this, i, result) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_hash_pattern_class(this, result) or ruby_hash_pattern_child(this, _, result)
}
}
/** A class representing `hash_splat_argument` nodes. */
class HashSplatArgument extends @ruby_hash_splat_argument, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -795,6 +943,12 @@ module Ruby {
override AstNode getAFieldOrChild() { ruby_hash_splat_argument_def(this, result, _) }
}
/** A class representing `hash_splat_nil` tokens. */
class HashSplatNil extends @ruby_token_hash_splat_nil, Token {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "HashSplatNil" }
}
/** A class representing `hash_splat_parameter` nodes. */
class HashSplatParameter extends @ruby_hash_splat_parameter, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -874,6 +1028,21 @@ module Ruby {
}
}
/** A class representing `if_guard` nodes. */
class IfGuard extends @ruby_if_guard, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "IfGuard" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_if_guard_def(this, _, result) }
/** Gets the node corresponding to the field `condition`. */
UnderscoreExpression getCondition() { ruby_if_guard_def(this, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() { ruby_if_guard_def(this, result, _) }
}
/** A class representing `if_modifier` nodes. */
class IfModifier extends @ruby_if_modifier, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -886,7 +1055,7 @@ module Ruby {
UnderscoreStatement getBody() { ruby_if_modifier_def(this, result, _, _) }
/** Gets the node corresponding to the field `condition`. */
AstNode getCondition() { ruby_if_modifier_def(this, _, result, _) }
UnderscoreExpression getCondition() { ruby_if_modifier_def(this, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -909,6 +1078,31 @@ module Ruby {
override AstNode getAFieldOrChild() { ruby_in_def(this, result, _) }
}
/** A class representing `in_clause` nodes. */
class InClause extends @ruby_in_clause, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "InClause" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_in_clause_def(this, _, result) }
/** Gets the node corresponding to the field `body`. */
Then getBody() { ruby_in_clause_body(this, result) }
/** Gets the node corresponding to the field `guard`. */
AstNode getGuard() { ruby_in_clause_guard(this, result) }
/** Gets the node corresponding to the field `pattern`. */
UnderscorePatternTopExprBody getPattern() { ruby_in_clause_def(this, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_in_clause_body(this, result) or
ruby_in_clause_guard(this, result) or
ruby_in_clause_def(this, result, _)
}
}
/** A class representing `instance_variable` tokens. */
class InstanceVariable extends @ruby_token_instance_variable, Token {
/** Gets the name of the primary QL class for this element. */
@@ -956,6 +1150,26 @@ module Ruby {
}
}
/** A class representing `keyword_pattern` nodes. */
class KeywordPattern extends @ruby_keyword_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "KeywordPattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_keyword_pattern_def(this, _, result) }
/** Gets the node corresponding to the field `key`. */
AstNode getKey() { ruby_keyword_pattern_def(this, result, _) }
/** Gets the node corresponding to the field `value`. */
UnderscorePatternExpr getValue() { ruby_keyword_pattern_value(this, result) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
ruby_keyword_pattern_def(this, result, _) or ruby_keyword_pattern_value(this, result)
}
}
/** A class representing `lambda` nodes. */
class Lambda extends @ruby_lambda, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -1006,6 +1220,12 @@ module Ruby {
override AstNode getAFieldOrChild() { ruby_left_assignment_list_child(this, _, result) }
}
/** A class representing `line` tokens. */
class Line extends @ruby_token_line, Token {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "Line" }
}
/** A class representing `method` nodes. */
class Method extends @ruby_method, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -1136,7 +1356,7 @@ module Ruby {
}
/** Gets the node corresponding to the field `right`. */
AstNode getRight() { ruby_operator_assignment_def(this, _, _, result, _) }
UnderscoreExpression getRight() { ruby_operator_assignment_def(this, _, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -1240,10 +1460,10 @@ module Ruby {
override L::Location getLocation() { ruby_range_def(this, _, result) }
/** Gets the node corresponding to the field `begin`. */
UnderscoreArg getBegin() { ruby_range_begin(this, result) }
AstNode getBegin() { ruby_range_begin(this, result) }
/** Gets the node corresponding to the field `end`. */
UnderscoreArg getEnd() { ruby_range_end(this, result) }
AstNode getEnd() { ruby_range_end(this, result) }
/** Gets the node corresponding to the field `operator`. */
string getOperator() {
@@ -1339,10 +1559,10 @@ module Ruby {
override L::Location getLocation() { ruby_rescue_modifier_def(this, _, _, result) }
/** Gets the node corresponding to the field `body`. */
UnderscoreStatement getBody() { ruby_rescue_modifier_def(this, result, _, _) }
AstNode getBody() { ruby_rescue_modifier_def(this, result, _, _) }
/** Gets the node corresponding to the field `handler`. */
AstNode getHandler() { ruby_rescue_modifier_def(this, _, result, _) }
UnderscoreExpression getHandler() { ruby_rescue_modifier_def(this, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -1422,7 +1642,7 @@ module Ruby {
AstNode getName() { ruby_scope_resolution_def(this, result, _) }
/** Gets the node corresponding to the field `scope`. */
UnderscorePrimary getScope() { ruby_scope_resolution_scope(this, result) }
AstNode getScope() { ruby_scope_resolution_scope(this, result) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -1602,7 +1822,7 @@ module Ruby {
override L::Location getLocation() { ruby_superclass_def(this, _, result) }
/** Gets the child of this node. */
AstNode getChild() { ruby_superclass_def(this, result, _) }
UnderscoreExpression getChild() { ruby_superclass_def(this, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() { ruby_superclass_def(this, result, _) }
@@ -1722,6 +1942,21 @@ module Ruby {
}
}
/** A class representing `unless_guard` nodes. */
class UnlessGuard extends @ruby_unless_guard, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "UnlessGuard" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_unless_guard_def(this, _, result) }
/** Gets the node corresponding to the field `condition`. */
UnderscoreExpression getCondition() { ruby_unless_guard_def(this, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() { ruby_unless_guard_def(this, result, _) }
}
/** A class representing `unless_modifier` nodes. */
class UnlessModifier extends @ruby_unless_modifier, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -1734,7 +1969,7 @@ module Ruby {
UnderscoreStatement getBody() { ruby_unless_modifier_def(this, result, _, _) }
/** Gets the node corresponding to the field `condition`. */
AstNode getCondition() { ruby_unless_modifier_def(this, _, result, _) }
UnderscoreExpression getCondition() { ruby_unless_modifier_def(this, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -1774,7 +2009,7 @@ module Ruby {
UnderscoreStatement getBody() { ruby_until_modifier_def(this, result, _, _) }
/** Gets the node corresponding to the field `condition`. */
AstNode getCondition() { ruby_until_modifier_def(this, _, result, _) }
UnderscoreExpression getCondition() { ruby_until_modifier_def(this, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {
@@ -1782,6 +2017,21 @@ module Ruby {
}
}
/** A class representing `variable_reference_pattern` nodes. */
class VariableReferencePattern extends @ruby_variable_reference_pattern, AstNode {
/** Gets the name of the primary QL class for this element. */
override string getAPrimaryQlClass() { result = "VariableReferencePattern" }
/** Gets the location of this element. */
override L::Location getLocation() { ruby_variable_reference_pattern_def(this, _, result) }
/** Gets the node corresponding to the field `name`. */
Identifier getName() { ruby_variable_reference_pattern_def(this, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() { ruby_variable_reference_pattern_def(this, result, _) }
}
/** A class representing `when` nodes. */
class When extends @ruby_when, AstNode {
/** Gets the name of the primary QL class for this element. */
@@ -1834,7 +2084,7 @@ module Ruby {
UnderscoreStatement getBody() { ruby_while_modifier_def(this, result, _, _) }
/** Gets the node corresponding to the field `condition`. */
AstNode getCondition() { ruby_while_modifier_def(this, _, result, _) }
UnderscoreExpression getCondition() { ruby_while_modifier_def(this, _, result, _) }
/** Gets a field or child node of this node. */
override AstNode getAFieldOrChild() {

View File

@@ -3,6 +3,7 @@ private import codeql.Locations
private import codeql.ruby.AST
private import codeql.ruby.ast.internal.AST
private import codeql.ruby.ast.internal.Parameter
private import codeql.ruby.ast.internal.Pattern
private import codeql.ruby.ast.internal.Scope
private import codeql.ruby.ast.internal.Synthesis
@@ -28,6 +29,16 @@ predicate explicitAssignmentNode(Ruby::AstNode n, Ruby::AstNode assignment) {
/** Holds if `n` is inside an implicit assignment. */
predicate implicitAssignmentNode(Ruby::AstNode n) {
casePattern(n) and n instanceof Ruby::Identifier
or
n = any(Ruby::AsPattern p).getName()
or
n = any(Ruby::ArrayPattern parent).getChild(_).(Ruby::SplatParameter).getName()
or
n = any(Ruby::FindPattern parent).getChild(_).(Ruby::SplatParameter).getName()
or
n = any(Ruby::HashPattern parent).getChild(_).(Ruby::HashSplatParameter).getName()
or
n = any(Ruby::ExceptionVariable ev).getChild()
or
n = any(Ruby::For for).getPattern()
@@ -177,6 +188,8 @@ private module Cached {
or
i = any(Ruby::Case x).getValue()
or
i = any(Ruby::CaseMatch x).getValue()
or
i = any(Ruby::Class x).getChild(_)
or
i = any(Ruby::Conditional x).getCondition()
@@ -498,11 +511,10 @@ module LocalVariableAccess {
predicate range(Ruby::Identifier id, TLocalVariableReal v) {
access(id, v) and
(
explicitWriteAccess(id, _)
or
implicitWriteAccess(id)
or
vcall(id)
explicitWriteAccess(id, _) or
implicitWriteAccess(id) or
vcall(id) or
id = any(Ruby::VariableReferencePattern vr).getName()
)
}
}

View File

@@ -192,7 +192,7 @@ private predicate inBooleanContext(AstNode n) {
or
exists(CaseExpr c, WhenExpr w |
not exists(c.getValue()) and
c.getAWhenBranch() = w and
c.getABranch() = w and
w.getPattern(_) = n
)
}
@@ -214,7 +214,7 @@ private predicate inMatchingContext(AstNode n) {
or
exists(CaseExpr c, WhenExpr w |
exists(c.getValue()) and
c.getAWhenBranch() = w and
c.getABranch() = w and
w.getPattern(_) = n
)
or

View File

@@ -378,7 +378,7 @@ module Trees {
override ControlFlowTree getChildElement(int i) { result = this.getArgument(i) }
}
private class CaseTree extends PreOrderTree, CaseExpr {
private class CaseTree extends PreOrderTree, CaseExpr, ASTInternal::TCaseExpr {
final override predicate propagatesAbnormal(AstNode child) {
child = this.getValue() or child = this.getABranch()
}
@@ -386,7 +386,7 @@ module Trees {
final override predicate last(AstNode last, Completion c) {
last(this.getValue(), last, c) and not exists(this.getABranch())
or
last(this.getAWhenBranch().getBody(), last, c)
last(this.getABranch().(WhenExpr).getBody(), last, c)
or
exists(int i, ControlFlowTree lastBranch |
lastBranch = this.getBranch(i) and
@@ -603,6 +603,8 @@ module Trees {
final override ControlFlowTree getChildElement(int i) { result = this.getElement(i) }
}
private class HashSplatNilParameterTree extends LeafTree, HashSplatNilParameter { }
private class HashSplatParameterTree extends NonDefaultValueParameterTree, HashSplatParameter { }
private class HereDocTree extends StandardPreOrderTree, HereDoc {

View File

@@ -52,13 +52,27 @@ case @diagnostic.severity of
@ruby_underscore_arg = @ruby_assignment | @ruby_binary | @ruby_conditional | @ruby_operator_assignment | @ruby_range | @ruby_unary | @ruby_underscore_primary
@ruby_underscore_expression = @ruby_assignment | @ruby_binary | @ruby_break | @ruby_call | @ruby_next | @ruby_operator_assignment | @ruby_return | @ruby_unary | @ruby_underscore_arg | @ruby_yield
@ruby_underscore_lhs = @ruby_call | @ruby_element_reference | @ruby_scope_resolution | @ruby_token_false | @ruby_token_nil | @ruby_token_true | @ruby_underscore_variable
@ruby_underscore_method_name = @ruby_delimited_symbol | @ruby_setter | @ruby_token_class_variable | @ruby_token_constant | @ruby_token_global_variable | @ruby_token_identifier | @ruby_token_instance_variable | @ruby_token_operator | @ruby_token_simple_symbol
@ruby_underscore_primary = @ruby_array | @ruby_begin | @ruby_break | @ruby_case__ | @ruby_chained_string | @ruby_class | @ruby_delimited_symbol | @ruby_for | @ruby_hash | @ruby_if | @ruby_lambda | @ruby_method | @ruby_module | @ruby_next | @ruby_parenthesized_statements | @ruby_rational | @ruby_redo | @ruby_regex | @ruby_retry | @ruby_return | @ruby_singleton_class | @ruby_singleton_method | @ruby_string__ | @ruby_string_array | @ruby_subshell | @ruby_symbol_array | @ruby_token_character | @ruby_token_complex | @ruby_token_float | @ruby_token_heredoc_beginning | @ruby_token_integer | @ruby_token_simple_symbol | @ruby_unary | @ruby_underscore_lhs | @ruby_unless | @ruby_until | @ruby_while | @ruby_yield
@ruby_underscore_pattern_constant = @ruby_scope_resolution | @ruby_token_constant
@ruby_underscore_statement = @ruby_alias | @ruby_assignment | @ruby_begin_block | @ruby_binary | @ruby_break | @ruby_call | @ruby_end_block | @ruby_if_modifier | @ruby_next | @ruby_operator_assignment | @ruby_rescue_modifier | @ruby_return | @ruby_unary | @ruby_undef | @ruby_underscore_arg | @ruby_unless_modifier | @ruby_until_modifier | @ruby_while_modifier | @ruby_yield
@ruby_underscore_pattern_expr = @ruby_alternative_pattern | @ruby_as_pattern | @ruby_underscore_pattern_expr_basic
@ruby_underscore_pattern_expr_basic = @ruby_array_pattern | @ruby_find_pattern | @ruby_hash_pattern | @ruby_range | @ruby_token_identifier | @ruby_underscore_pattern_constant | @ruby_underscore_pattern_primitive | @ruby_variable_reference_pattern
@ruby_underscore_pattern_primitive = @ruby_delimited_symbol | @ruby_lambda | @ruby_regex | @ruby_string__ | @ruby_string_array | @ruby_symbol_array | @ruby_token_encoding | @ruby_token_false | @ruby_token_file | @ruby_token_line | @ruby_token_nil | @ruby_token_self | @ruby_token_simple_symbol | @ruby_token_true | @ruby_unary | @ruby_underscore_simple_numeric
@ruby_underscore_pattern_top_expr_body = @ruby_array_pattern | @ruby_find_pattern | @ruby_hash_pattern | @ruby_underscore_pattern_expr
@ruby_underscore_primary = @ruby_array | @ruby_begin | @ruby_break | @ruby_case__ | @ruby_case_match | @ruby_chained_string | @ruby_class | @ruby_delimited_symbol | @ruby_for | @ruby_hash | @ruby_if | @ruby_lambda | @ruby_method | @ruby_module | @ruby_next | @ruby_parenthesized_statements | @ruby_redo | @ruby_regex | @ruby_retry | @ruby_return | @ruby_singleton_class | @ruby_singleton_method | @ruby_string__ | @ruby_string_array | @ruby_subshell | @ruby_symbol_array | @ruby_token_character | @ruby_token_heredoc_beginning | @ruby_token_simple_symbol | @ruby_unary | @ruby_underscore_lhs | @ruby_underscore_simple_numeric | @ruby_unless | @ruby_until | @ruby_while | @ruby_yield
@ruby_underscore_simple_numeric = @ruby_rational | @ruby_token_complex | @ruby_token_float | @ruby_token_integer
@ruby_underscore_statement = @ruby_alias | @ruby_begin_block | @ruby_end_block | @ruby_if_modifier | @ruby_rescue_modifier | @ruby_undef | @ruby_underscore_expression | @ruby_unless_modifier | @ruby_until_modifier | @ruby_while_modifier
@ruby_underscore_variable = @ruby_token_class_variable | @ruby_token_constant | @ruby_token_global_variable | @ruby_token_identifier | @ruby_token_instance_variable | @ruby_token_self | @ruby_token_super
@@ -69,7 +83,19 @@ ruby_alias_def(
int loc: @location ref
);
@ruby_argument_list_child_type = @ruby_block_argument | @ruby_break | @ruby_call | @ruby_hash_splat_argument | @ruby_next | @ruby_pair | @ruby_return | @ruby_splat_argument | @ruby_token_forward_argument | @ruby_underscore_arg | @ruby_yield
#keyset[ruby_alternative_pattern, index]
ruby_alternative_pattern_alternatives(
int ruby_alternative_pattern: @ruby_alternative_pattern ref,
int index: int ref,
unique int alternatives: @ruby_underscore_pattern_expr_basic ref
);
ruby_alternative_pattern_def(
unique int id: @ruby_alternative_pattern,
int loc: @location ref
);
@ruby_argument_list_child_type = @ruby_block_argument | @ruby_hash_splat_argument | @ruby_pair | @ruby_splat_argument | @ruby_token_forward_argument | @ruby_underscore_expression
#keyset[ruby_argument_list, index]
ruby_argument_list_child(
@@ -83,7 +109,7 @@ ruby_argument_list_def(
int loc: @location ref
);
@ruby_array_child_type = @ruby_block_argument | @ruby_break | @ruby_call | @ruby_hash_splat_argument | @ruby_next | @ruby_pair | @ruby_return | @ruby_splat_argument | @ruby_token_forward_argument | @ruby_underscore_arg | @ruby_yield
@ruby_array_child_type = @ruby_block_argument | @ruby_hash_splat_argument | @ruby_pair | @ruby_splat_argument | @ruby_token_forward_argument | @ruby_underscore_expression
#keyset[ruby_array, index]
ruby_array_child(
@@ -97,9 +123,35 @@ ruby_array_def(
int loc: @location ref
);
ruby_array_pattern_class(
unique int ruby_array_pattern: @ruby_array_pattern ref,
unique int class: @ruby_underscore_pattern_constant ref
);
@ruby_array_pattern_child_type = @ruby_splat_parameter | @ruby_underscore_pattern_expr
#keyset[ruby_array_pattern, index]
ruby_array_pattern_child(
int ruby_array_pattern: @ruby_array_pattern ref,
int index: int ref,
unique int child: @ruby_array_pattern_child_type ref
);
ruby_array_pattern_def(
unique int id: @ruby_array_pattern,
int loc: @location ref
);
ruby_as_pattern_def(
unique int id: @ruby_as_pattern,
int name: @ruby_token_identifier ref,
int value: @ruby_underscore_pattern_expr ref,
int loc: @location ref
);
@ruby_assignment_left_type = @ruby_left_assignment_list | @ruby_underscore_lhs
@ruby_assignment_right_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_right_assignment_list | @ruby_splat_argument | @ruby_underscore_arg | @ruby_yield
@ruby_assignment_right_type = @ruby_right_assignment_list | @ruby_splat_argument | @ruby_underscore_expression
ruby_assignment_def(
unique int id: @ruby_assignment,
@@ -164,8 +216,6 @@ ruby_begin_block_def(
int loc: @location ref
);
@ruby_binary_left_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
case @ruby_binary.operator of
0 = @ruby_binary_bangequal
| 1 = @ruby_binary_bangtilde
@@ -195,13 +245,11 @@ case @ruby_binary.operator of
;
@ruby_binary_right_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_binary_def(
unique int id: @ruby_binary,
int left: @ruby_binary_left_type ref,
int left: @ruby_underscore_expression ref,
int operator: int ref,
int right: @ruby_binary_right_type ref,
int right: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -236,7 +284,7 @@ ruby_block_parameter_def(
int loc: @location ref
);
@ruby_block_parameters_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_identifier
@ruby_block_parameters_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_hash_splat_nil | @ruby_token_identifier
#keyset[ruby_block_parameters, index]
ruby_block_parameters_child(
@@ -306,6 +354,24 @@ ruby_case_def(
int loc: @location ref
);
#keyset[ruby_case_match, index]
ruby_case_match_clauses(
int ruby_case_match: @ruby_case_match ref,
int index: int ref,
unique int clauses: @ruby_in_clause ref
);
ruby_case_match_else(
unique int ruby_case_match: @ruby_case_match ref,
unique int else: @ruby_else ref
);
ruby_case_match_def(
unique int id: @ruby_case_match,
int value: @ruby_underscore_statement ref,
int loc: @location ref
);
#keyset[ruby_chained_string, index]
ruby_chained_string_child(
int ruby_chained_string: @ruby_chained_string ref,
@@ -376,7 +442,7 @@ ruby_destructured_left_assignment_def(
int loc: @location ref
);
@ruby_destructured_parameter_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_identifier
@ruby_destructured_parameter_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_hash_splat_nil | @ruby_token_identifier
#keyset[ruby_destructured_parameter, index]
ruby_destructured_parameter_child(
@@ -423,7 +489,7 @@ ruby_do_block_def(
int loc: @location ref
);
@ruby_element_reference_child_type = @ruby_block_argument | @ruby_break | @ruby_call | @ruby_hash_splat_argument | @ruby_next | @ruby_pair | @ruby_return | @ruby_splat_argument | @ruby_token_forward_argument | @ruby_underscore_arg | @ruby_yield
@ruby_element_reference_child_type = @ruby_block_argument | @ruby_hash_splat_argument | @ruby_pair | @ruby_splat_argument | @ruby_token_forward_argument | @ruby_underscore_expression
#keyset[ruby_element_reference, index]
ruby_element_reference_child(
@@ -518,6 +584,25 @@ ruby_exceptions_def(
int loc: @location ref
);
ruby_find_pattern_class(
unique int ruby_find_pattern: @ruby_find_pattern ref,
unique int class: @ruby_underscore_pattern_constant ref
);
@ruby_find_pattern_child_type = @ruby_splat_parameter | @ruby_underscore_pattern_expr
#keyset[ruby_find_pattern, index]
ruby_find_pattern_child(
int ruby_find_pattern: @ruby_find_pattern ref,
int index: int ref,
unique int child: @ruby_find_pattern_child_type ref
);
ruby_find_pattern_def(
unique int id: @ruby_find_pattern,
int loc: @location ref
);
@ruby_for_pattern_type = @ruby_left_assignment_list | @ruby_underscore_lhs
ruby_for_def(
@@ -542,6 +627,25 @@ ruby_hash_def(
int loc: @location ref
);
ruby_hash_pattern_class(
unique int ruby_hash_pattern: @ruby_hash_pattern ref,
unique int class: @ruby_underscore_pattern_constant ref
);
@ruby_hash_pattern_child_type = @ruby_hash_splat_parameter | @ruby_keyword_pattern | @ruby_token_hash_splat_nil
#keyset[ruby_hash_pattern, index]
ruby_hash_pattern_child(
int ruby_hash_pattern: @ruby_hash_pattern ref,
int index: int ref,
unique int child: @ruby_hash_pattern_child_type ref
);
ruby_hash_pattern_def(
unique int id: @ruby_hash_pattern,
int loc: @location ref
);
ruby_hash_splat_argument_def(
unique int id: @ruby_hash_splat_argument,
int child: @ruby_underscore_arg ref,
@@ -590,12 +694,16 @@ ruby_if_def(
int loc: @location ref
);
@ruby_if_modifier_condition_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_if_guard_def(
unique int id: @ruby_if_guard,
int condition: @ruby_underscore_expression ref,
int loc: @location ref
);
ruby_if_modifier_def(
unique int id: @ruby_if_modifier,
int body: @ruby_underscore_statement ref,
int condition: @ruby_if_modifier_condition_type ref,
int condition: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -605,6 +713,24 @@ ruby_in_def(
int loc: @location ref
);
ruby_in_clause_body(
unique int ruby_in_clause: @ruby_in_clause ref,
unique int body: @ruby_then ref
);
@ruby_in_clause_guard_type = @ruby_if_guard | @ruby_unless_guard
ruby_in_clause_guard(
unique int ruby_in_clause: @ruby_in_clause ref,
unique int guard: @ruby_in_clause_guard_type ref
);
ruby_in_clause_def(
unique int id: @ruby_in_clause,
int pattern: @ruby_underscore_pattern_top_expr_body ref,
int loc: @location ref
);
@ruby_interpolation_child_type = @ruby_token_empty_statement | @ruby_underscore_statement
#keyset[ruby_interpolation, index]
@@ -630,6 +756,19 @@ ruby_keyword_parameter_def(
int loc: @location ref
);
@ruby_keyword_pattern_key_type = @ruby_string__ | @ruby_token_hash_key_symbol
ruby_keyword_pattern_value(
unique int ruby_keyword_pattern: @ruby_keyword_pattern ref,
unique int value: @ruby_underscore_pattern_expr ref
);
ruby_keyword_pattern_def(
unique int id: @ruby_keyword_pattern,
int key__: @ruby_keyword_pattern_key_type ref,
int loc: @location ref
);
@ruby_lambda_body_type = @ruby_block | @ruby_do_block
ruby_lambda_parameters(
@@ -643,7 +782,7 @@ ruby_lambda_def(
int loc: @location ref
);
@ruby_lambda_parameters_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_identifier
@ruby_lambda_parameters_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_hash_splat_nil | @ruby_token_identifier
#keyset[ruby_lambda_parameters, index]
ruby_lambda_parameters_child(
@@ -676,7 +815,7 @@ ruby_method_parameters(
unique int parameters: @ruby_method_parameters ref
);
@ruby_method_child_type = @ruby_else | @ruby_ensure | @ruby_rescue | @ruby_token_empty_statement | @ruby_underscore_statement
@ruby_method_child_type = @ruby_else | @ruby_ensure | @ruby_rescue | @ruby_token_empty_statement | @ruby_underscore_arg | @ruby_underscore_statement
#keyset[ruby_method, index]
ruby_method_child(
@@ -691,7 +830,7 @@ ruby_method_def(
int loc: @location ref
);
@ruby_method_parameters_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_identifier
@ruby_method_parameters_child_type = @ruby_block_parameter | @ruby_destructured_parameter | @ruby_hash_splat_parameter | @ruby_keyword_parameter | @ruby_optional_parameter | @ruby_splat_parameter | @ruby_token_forward_parameter | @ruby_token_hash_splat_nil | @ruby_token_identifier
#keyset[ruby_method_parameters, index]
ruby_method_parameters_child(
@@ -749,13 +888,11 @@ case @ruby_operator_assignment.operator of
;
@ruby_operator_assignment_right_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_operator_assignment_def(
unique int id: @ruby_operator_assignment,
int left: @ruby_underscore_lhs ref,
int operator: int ref,
int right: @ruby_operator_assignment_right_type ref,
int right: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -811,14 +948,18 @@ ruby_program_def(
int loc: @location ref
);
@ruby_range_begin_type = @ruby_underscore_arg | @ruby_underscore_pattern_primitive
ruby_range_begin(
unique int ruby_range: @ruby_range ref,
unique int begin: @ruby_underscore_arg ref
unique int begin: @ruby_range_begin_type ref
);
@ruby_range_end_type = @ruby_underscore_arg | @ruby_underscore_pattern_primitive
ruby_range_end(
unique int ruby_range: @ruby_range ref,
unique int end: @ruby_underscore_arg ref
unique int end: @ruby_range_end_type ref
);
case @ruby_range.operator of
@@ -885,12 +1026,12 @@ ruby_rescue_def(
int loc: @location ref
);
@ruby_rescue_modifier_handler_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
@ruby_rescue_modifier_body_type = @ruby_underscore_arg | @ruby_underscore_statement
ruby_rescue_modifier_def(
unique int id: @ruby_rescue_modifier,
int body: @ruby_underscore_statement ref,
int handler: @ruby_rescue_modifier_handler_type ref,
int body: @ruby_rescue_modifier_body_type ref,
int handler: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -940,9 +1081,11 @@ ruby_right_assignment_list_def(
@ruby_scope_resolution_name_type = @ruby_token_constant | @ruby_token_identifier
@ruby_scope_resolution_scope_type = @ruby_underscore_pattern_constant | @ruby_underscore_primary
ruby_scope_resolution_scope(
unique int ruby_scope_resolution: @ruby_scope_resolution ref,
unique int scope: @ruby_underscore_primary ref
unique int scope: @ruby_scope_resolution_scope_type ref
);
ruby_scope_resolution_def(
@@ -979,7 +1122,7 @@ ruby_singleton_method_parameters(
unique int parameters: @ruby_method_parameters ref
);
@ruby_singleton_method_child_type = @ruby_else | @ruby_ensure | @ruby_rescue | @ruby_token_empty_statement | @ruby_underscore_statement
@ruby_singleton_method_child_type = @ruby_else | @ruby_ensure | @ruby_rescue | @ruby_token_empty_statement | @ruby_underscore_arg | @ruby_underscore_statement
#keyset[ruby_singleton_method, index]
ruby_singleton_method_child(
@@ -1051,11 +1194,9 @@ ruby_subshell_def(
int loc: @location ref
);
@ruby_superclass_child_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_superclass_def(
unique int id: @ruby_superclass,
int child: @ruby_superclass_child_type ref,
int child: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -1085,7 +1226,7 @@ ruby_then_def(
int loc: @location ref
);
@ruby_unary_operand_type = @ruby_break | @ruby_call | @ruby_next | @ruby_parenthesized_statements | @ruby_return | @ruby_token_float | @ruby_token_integer | @ruby_underscore_arg | @ruby_yield
@ruby_unary_operand_type = @ruby_parenthesized_statements | @ruby_underscore_expression | @ruby_underscore_simple_numeric
case @ruby_unary.operator of
0 = @ruby_unary_bang
@@ -1134,12 +1275,16 @@ ruby_unless_def(
int loc: @location ref
);
@ruby_unless_modifier_condition_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_unless_guard_def(
unique int id: @ruby_unless_guard,
int condition: @ruby_underscore_expression ref,
int loc: @location ref
);
ruby_unless_modifier_def(
unique int id: @ruby_unless_modifier,
int body: @ruby_underscore_statement ref,
int condition: @ruby_unless_modifier_condition_type ref,
int condition: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -1150,12 +1295,16 @@ ruby_until_def(
int loc: @location ref
);
@ruby_until_modifier_condition_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_until_modifier_def(
unique int id: @ruby_until_modifier,
int body: @ruby_underscore_statement ref,
int condition: @ruby_until_modifier_condition_type ref,
int condition: @ruby_underscore_expression ref,
int loc: @location ref
);
ruby_variable_reference_pattern_def(
unique int id: @ruby_variable_reference_pattern,
int name: @ruby_token_identifier ref,
int loc: @location ref
);
@@ -1183,12 +1332,10 @@ ruby_while_def(
int loc: @location ref
);
@ruby_while_modifier_condition_type = @ruby_break | @ruby_call | @ruby_next | @ruby_return | @ruby_underscore_arg | @ruby_yield
ruby_while_modifier_def(
unique int id: @ruby_while_modifier,
int body: @ruby_underscore_statement ref,
int condition: @ruby_while_modifier_condition_type ref,
int condition: @ruby_underscore_expression ref,
int loc: @location ref
);
@@ -1217,31 +1364,35 @@ case @ruby_token.kind of
| 4 = @ruby_token_complex
| 5 = @ruby_token_constant
| 6 = @ruby_token_empty_statement
| 7 = @ruby_token_escape_sequence
| 8 = @ruby_token_false
| 9 = @ruby_token_float
| 10 = @ruby_token_forward_argument
| 11 = @ruby_token_forward_parameter
| 12 = @ruby_token_global_variable
| 13 = @ruby_token_hash_key_symbol
| 14 = @ruby_token_heredoc_beginning
| 15 = @ruby_token_heredoc_content
| 16 = @ruby_token_heredoc_end
| 17 = @ruby_token_identifier
| 18 = @ruby_token_instance_variable
| 19 = @ruby_token_integer
| 20 = @ruby_token_nil
| 21 = @ruby_token_operator
| 22 = @ruby_token_self
| 23 = @ruby_token_simple_symbol
| 24 = @ruby_token_string_content
| 25 = @ruby_token_super
| 26 = @ruby_token_true
| 27 = @ruby_token_uninterpreted
| 7 = @ruby_token_encoding
| 8 = @ruby_token_escape_sequence
| 9 = @ruby_token_false
| 10 = @ruby_token_file
| 11 = @ruby_token_float
| 12 = @ruby_token_forward_argument
| 13 = @ruby_token_forward_parameter
| 14 = @ruby_token_global_variable
| 15 = @ruby_token_hash_key_symbol
| 16 = @ruby_token_hash_splat_nil
| 17 = @ruby_token_heredoc_beginning
| 18 = @ruby_token_heredoc_content
| 19 = @ruby_token_heredoc_end
| 20 = @ruby_token_identifier
| 21 = @ruby_token_instance_variable
| 22 = @ruby_token_integer
| 23 = @ruby_token_line
| 24 = @ruby_token_nil
| 25 = @ruby_token_operator
| 26 = @ruby_token_self
| 27 = @ruby_token_simple_symbol
| 28 = @ruby_token_string_content
| 29 = @ruby_token_super
| 30 = @ruby_token_true
| 31 = @ruby_token_uninterpreted
;
@ruby_ast_node = @ruby_alias | @ruby_argument_list | @ruby_array | @ruby_assignment | @ruby_bare_string | @ruby_bare_symbol | @ruby_begin | @ruby_begin_block | @ruby_binary | @ruby_block | @ruby_block_argument | @ruby_block_parameter | @ruby_block_parameters | @ruby_break | @ruby_call | @ruby_case__ | @ruby_chained_string | @ruby_class | @ruby_conditional | @ruby_delimited_symbol | @ruby_destructured_left_assignment | @ruby_destructured_parameter | @ruby_do | @ruby_do_block | @ruby_element_reference | @ruby_else | @ruby_elsif | @ruby_end_block | @ruby_ensure | @ruby_exception_variable | @ruby_exceptions | @ruby_for | @ruby_hash | @ruby_hash_splat_argument | @ruby_hash_splat_parameter | @ruby_heredoc_body | @ruby_if | @ruby_if_modifier | @ruby_in | @ruby_interpolation | @ruby_keyword_parameter | @ruby_lambda | @ruby_lambda_parameters | @ruby_left_assignment_list | @ruby_method | @ruby_method_parameters | @ruby_module | @ruby_next | @ruby_operator_assignment | @ruby_optional_parameter | @ruby_pair | @ruby_parenthesized_statements | @ruby_pattern | @ruby_program | @ruby_range | @ruby_rational | @ruby_redo | @ruby_regex | @ruby_rescue | @ruby_rescue_modifier | @ruby_rest_assignment | @ruby_retry | @ruby_return | @ruby_right_assignment_list | @ruby_scope_resolution | @ruby_setter | @ruby_singleton_class | @ruby_singleton_method | @ruby_splat_argument | @ruby_splat_parameter | @ruby_string__ | @ruby_string_array | @ruby_subshell | @ruby_superclass | @ruby_symbol_array | @ruby_then | @ruby_token | @ruby_unary | @ruby_undef | @ruby_unless | @ruby_unless_modifier | @ruby_until | @ruby_until_modifier | @ruby_when | @ruby_while | @ruby_while_modifier | @ruby_yield
@ruby_ast_node = @ruby_alias | @ruby_alternative_pattern | @ruby_argument_list | @ruby_array | @ruby_array_pattern | @ruby_as_pattern | @ruby_assignment | @ruby_bare_string | @ruby_bare_symbol | @ruby_begin | @ruby_begin_block | @ruby_binary | @ruby_block | @ruby_block_argument | @ruby_block_parameter | @ruby_block_parameters | @ruby_break | @ruby_call | @ruby_case__ | @ruby_case_match | @ruby_chained_string | @ruby_class | @ruby_conditional | @ruby_delimited_symbol | @ruby_destructured_left_assignment | @ruby_destructured_parameter | @ruby_do | @ruby_do_block | @ruby_element_reference | @ruby_else | @ruby_elsif | @ruby_end_block | @ruby_ensure | @ruby_exception_variable | @ruby_exceptions | @ruby_find_pattern | @ruby_for | @ruby_hash | @ruby_hash_pattern | @ruby_hash_splat_argument | @ruby_hash_splat_parameter | @ruby_heredoc_body | @ruby_if | @ruby_if_guard | @ruby_if_modifier | @ruby_in | @ruby_in_clause | @ruby_interpolation | @ruby_keyword_parameter | @ruby_keyword_pattern | @ruby_lambda | @ruby_lambda_parameters | @ruby_left_assignment_list | @ruby_method | @ruby_method_parameters | @ruby_module | @ruby_next | @ruby_operator_assignment | @ruby_optional_parameter | @ruby_pair | @ruby_parenthesized_statements | @ruby_pattern | @ruby_program | @ruby_range | @ruby_rational | @ruby_redo | @ruby_regex | @ruby_rescue | @ruby_rescue_modifier | @ruby_rest_assignment | @ruby_retry | @ruby_return | @ruby_right_assignment_list | @ruby_scope_resolution | @ruby_setter | @ruby_singleton_class | @ruby_singleton_method | @ruby_splat_argument | @ruby_splat_parameter | @ruby_string__ | @ruby_string_array | @ruby_subshell | @ruby_superclass | @ruby_symbol_array | @ruby_then | @ruby_token | @ruby_unary | @ruby_undef | @ruby_unless | @ruby_unless_guard | @ruby_unless_modifier | @ruby_until | @ruby_until_modifier | @ruby_variable_reference_pattern | @ruby_when | @ruby_while | @ruby_while_modifier | @ruby_yield
@ruby_ast_node_parent = @file | @ruby_ast_node

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,79 @@
private class RubyToken extends @ruby_token {
string toString() { none() }
}
private class Location extends @location {
string toString() { none() }
}
bindingset[old]
private int newKind(int old) {
old in [0 .. 6] and result = old
or
// @ruby_token_escape_sequence
old = 7 and result = 8
or
// @ruby_token_false
old = 8 and result = 9
or
// @ruby_token_float
old = 9 and result = 11
or
// @ruby_token_forward_argument
old = 10 and result = 12
or
// @ruby_token_forward_parameter
old = 11 and result = 13
or
// @ruby_token_global_variable
old = 12 and result = 14
or
// @ruby_token_hash_key_symbol
old = 13 and result = 15
or
// @ruby_token_heredoc_beginning
old = 14 and result = 17
or
// @ruby_token_heredoc_content
old = 15 and result = 18
or
// @ruby_token_heredoc_end
old = 16 and result = 19
or
// @ruby_token_identifier
old = 17 and result = 20
or
// @ruby_token_instance_variable
old = 18 and result = 21
or
// @ruby_token_integer
old = 19 and result = 22
or
// @ruby_token_nil
old = 20 and result = 24
or
// @ruby_token_operator
old = 21 and result = 25
or
// @ruby_token_self
old = 22 and result = 26
or
// @ruby_token_simple_symbol
old = 23 and result = 27
or
// @ruby_token_string_content
old = 24 and result = 28
or
// @ruby_token_super
old = 25 and result = 29
or
// @ruby_token_true
old = 26 and result = 30
or
// @ruby_token_uninterpreted
old = 27 and result = 31
}
from RubyToken id, int kind, string value, Location loc
where ruby_tokeninfo(id, kind, value, loc)
select id, newKind(kind), value, loc

View File

@@ -0,0 +1,3 @@
description: Re-number @ruby_token.kind
compatibility: full
ruby_tokeninfo.rel: run ruby_tokeninfo.qlo

View File

@@ -698,7 +698,7 @@ control/cases.rb:
# 11| getPattern: [LocalVariableAccess] d
# 11| getBody: [StmtSequence] then ...
# 12| getStmt: [IntegerLiteral] 200
# 13| getBranch: [StmtSequence] else ...
# 13| getBranch/getElseBranch: [StmtSequence] else ...
# 14| getStmt: [IntegerLiteral] 300
# 18| getStmt: [CaseExpr] case ...
# 19| getBranch: [WhenExpr] when ...
@@ -719,6 +719,376 @@ control/cases.rb:
# 21| getAnOperand/getArgument/getGreaterOperand/getRightOperand: [LocalVariableAccess] b
# 21| getBody: [StmtSequence] then ...
# 21| getStmt: [IntegerLiteral] 30
# 26| getStmt: [CaseExpr] case ...
# 26| getValue: [MethodCall] call to expr
# 26| getReceiver: [Self, SelfVariableAccess] self
# 27| getBranch: [InClause] in ... then ...
# 27| getPattern: [IntegerLiteral] 5
# 27| getBody: [StmtSequence] then ...
# 27| getStmt: [BooleanLiteral] true
# 28| getBranch/getElseBranch: [StmtSequence] else ...
# 28| getStmt: [BooleanLiteral] false
# 31| getStmt: [CaseExpr] case ...
# 31| getValue: [MethodCall] call to expr
# 31| getReceiver: [Self, SelfVariableAccess] self
# 32| getBranch: [InClause] in ... then ...
# 32| getPattern: [LocalVariableAccess] x
# 32| getCondition: [LTExpr] ... < ...
# 32| getAnOperand/getLeftOperand/getLesserOperand/getReceiver: [LocalVariableAccess] x
# 32| getAnOperand/getArgument/getGreaterOperand/getRightOperand: [IntegerLiteral] 0
# 32| getBody: [StmtSequence] then ...
# 33| getStmt: [BooleanLiteral] true
# 34| getBranch: [InClause] in ... then ...
# 34| getPattern: [LocalVariableAccess] x
# 34| getCondition: [LTExpr] ... < ...
# 34| getAnOperand/getLeftOperand/getLesserOperand/getReceiver: [LocalVariableAccess] x
# 34| getAnOperand/getArgument/getGreaterOperand/getRightOperand: [IntegerLiteral] 0
# 34| getBody: [StmtSequence] then ...
# 35| getStmt: [BooleanLiteral] true
# 36| getBranch/getElseBranch: [StmtSequence] else ...
# 36| getStmt: [BooleanLiteral] false
# 39| getStmt: [CaseExpr] case ...
# 39| getValue: [MethodCall] call to expr
# 39| getReceiver: [Self, SelfVariableAccess] self
# 40| getBranch: [InClause] in ... then ...
# 40| getPattern: [IntegerLiteral] 5
# 41| getBranch: [InClause] in ... then ...
# 41| getPattern: [ArrayPattern] [ ..., * ]
# 41| getPrefixElement/getSuffixElement: [IntegerLiteral] 5
# 42| getBranch: [InClause] in ... then ...
# 42| getPattern: [ArrayPattern] [ ..., * ]
# 42| getPrefixElement: [IntegerLiteral] 1
# 42| getPrefixElement: [IntegerLiteral] 2
# 43| getBranch: [InClause] in ... then ...
# 43| getPattern: [ArrayPattern] [ ..., * ]
# 43| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 43| getPrefixElement/getSuffixElement: [IntegerLiteral] 2
# 44| getBranch: [InClause] in ... then ...
# 44| getPattern: [ArrayPattern] [ ..., * ]
# 44| getPrefixElement: [IntegerLiteral] 1
# 44| getPrefixElement: [IntegerLiteral] 2
# 44| getPrefixElement: [IntegerLiteral] 3
# 45| getBranch: [InClause] in ... then ...
# 45| getPattern: [ArrayPattern] [ ..., * ]
# 45| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 45| getPrefixElement/getSuffixElement: [IntegerLiteral] 2
# 45| getPrefixElement/getSuffixElement: [IntegerLiteral] 3
# 46| getBranch: [InClause] in ... then ...
# 46| getPattern: [ArrayPattern] [ ..., * ]
# 46| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 46| getPrefixElement/getSuffixElement: [IntegerLiteral] 2
# 46| getPrefixElement/getSuffixElement: [IntegerLiteral] 3
# 47| getBranch: [InClause] in ... then ...
# 47| getPattern: [ArrayPattern] [ ..., * ]
# 47| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 47| getRestVariableAccess: [LocalVariableAccess] x
# 47| getSuffixElement: [IntegerLiteral] 3
# 48| getBranch: [InClause] in ... then ...
# 48| getPattern: [ArrayPattern] [ ..., * ]
# 49| getBranch: [InClause] in ... then ...
# 49| getPattern: [ArrayPattern] [ ..., * ]
# 49| getSuffixElement: [IntegerLiteral] 3
# 49| getSuffixElement: [IntegerLiteral] 4
# 50| getBranch: [InClause] in ... then ...
# 50| getPattern: [FindPattern] [ *,...,* ]
# 50| getElement: [IntegerLiteral] 3
# 51| getBranch: [InClause] in ... then ...
# 51| getPattern: [FindPattern] [ *,...,* ]
# 51| getPrefixVariableAccess: [LocalVariableAccess] a
# 51| getElement: [IntegerLiteral] 3
# 51| getSuffixVariableAccess: [LocalVariableAccess] b
# 52| getBranch: [InClause] in ... then ...
# 52| getPattern: [HashPattern] { ..., ** }
# 52| getKey: [SymbolLiteral] :a
# 53| getBranch: [InClause] in ... then ...
# 53| getPattern: [HashPattern] { ..., ** }
# 53| getKey: [SymbolLiteral] :a
# 53| getValue: [IntegerLiteral] 5
# 54| getBranch: [InClause] in ... then ...
# 54| getPattern: [HashPattern] { ..., ** }
# 54| getKey: [SymbolLiteral] :a
# 54| getValue: [IntegerLiteral] 5
# 55| getBranch: [InClause] in ... then ...
# 55| getPattern: [HashPattern] { ..., ** }
# 55| getKey: [SymbolLiteral] :a
# 55| getValue: [IntegerLiteral] 5
# 55| getKey: [SymbolLiteral] :b
# 56| getBranch: [InClause] in ... then ...
# 56| getPattern: [HashPattern] { ..., ** }
# 56| getKey: [SymbolLiteral] :a
# 56| getValue: [IntegerLiteral] 5
# 56| getKey: [SymbolLiteral] :b
# 56| getRestVariableAccess: [LocalVariableAccess] map
# 57| getBranch: [InClause] in ... then ...
# 57| getPattern: [HashPattern] { ..., ** }
# 57| getKey: [SymbolLiteral] :a
# 57| getValue: [IntegerLiteral] 5
# 57| getKey: [SymbolLiteral] :b
# 58| getBranch: [InClause] in ... then ...
# 58| getPattern: [HashPattern] { ..., ** }
# 59| getBranch: [InClause] in ... then ...
# 59| getPattern: [ArrayPattern] [ ..., * ]
# 59| getPrefixElement: [IntegerLiteral] 5
# 60| getBranch: [InClause] in ... then ...
# 60| getPattern: [ArrayPattern] [ ..., * ]
# 60| getPrefixElement/getSuffixElement: [IntegerLiteral] 5
# 61| getBranch: [InClause] in ... then ...
# 61| getPattern: [ArrayPattern] [ ..., * ]
# 61| getPrefixElement: [IntegerLiteral] 1
# 61| getPrefixElement: [IntegerLiteral] 2
# 62| getBranch: [InClause] in ... then ...
# 62| getPattern: [ArrayPattern] [ ..., * ]
# 62| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 62| getPrefixElement/getSuffixElement: [IntegerLiteral] 2
# 63| getBranch: [InClause] in ... then ...
# 63| getPattern: [ArrayPattern] [ ..., * ]
# 63| getPrefixElement: [IntegerLiteral] 1
# 63| getPrefixElement: [IntegerLiteral] 2
# 63| getPrefixElement: [IntegerLiteral] 3
# 64| getBranch: [InClause] in ... then ...
# 64| getPattern: [ArrayPattern] [ ..., * ]
# 64| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 64| getPrefixElement/getSuffixElement: [IntegerLiteral] 2
# 64| getPrefixElement/getSuffixElement: [IntegerLiteral] 3
# 65| getBranch: [InClause] in ... then ...
# 65| getPattern: [ArrayPattern] [ ..., * ]
# 65| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 65| getPrefixElement/getSuffixElement: [IntegerLiteral] 2
# 65| getPrefixElement/getSuffixElement: [IntegerLiteral] 3
# 66| getBranch: [InClause] in ... then ...
# 66| getPattern: [ArrayPattern] [ ..., * ]
# 66| getPrefixElement/getSuffixElement: [IntegerLiteral] 1
# 66| getRestVariableAccess: [LocalVariableAccess] x
# 66| getSuffixElement: [IntegerLiteral] 3
# 67| getBranch: [InClause] in ... then ...
# 67| getPattern: [ArrayPattern] [ ..., * ]
# 68| getBranch: [InClause] in ... then ...
# 68| getPattern: [ArrayPattern] [ ..., * ]
# 68| getSuffixElement: [IntegerLiteral] 3
# 68| getSuffixElement: [IntegerLiteral] 4
# 69| getBranch: [InClause] in ... then ...
# 69| getPattern: [FindPattern] [ *,...,* ]
# 69| getElement: [IntegerLiteral] 3
# 70| getBranch: [InClause] in ... then ...
# 70| getPattern: [FindPattern] [ *,...,* ]
# 70| getPrefixVariableAccess: [LocalVariableAccess] a
# 70| getElement: [IntegerLiteral] 3
# 70| getSuffixVariableAccess: [LocalVariableAccess] b
# 71| getBranch: [InClause] in ... then ...
# 71| getPattern: [HashPattern] { ..., ** }
# 71| getKey: [SymbolLiteral] :a
# 72| getBranch: [InClause] in ... then ...
# 72| getPattern: [HashPattern] { ..., ** }
# 72| getKey: [SymbolLiteral] :a
# 72| getValue: [IntegerLiteral] 5
# 73| getBranch: [InClause] in ... then ...
# 73| getPattern: [HashPattern] { ..., ** }
# 73| getKey: [SymbolLiteral] :a
# 73| getValue: [IntegerLiteral] 5
# 74| getBranch: [InClause] in ... then ...
# 74| getPattern: [HashPattern] { ..., ** }
# 74| getKey: [SymbolLiteral] :a
# 74| getValue: [IntegerLiteral] 5
# 74| getKey: [SymbolLiteral] :b
# 75| getBranch: [InClause] in ... then ...
# 75| getPattern: [HashPattern] { ..., ** }
# 75| getKey: [SymbolLiteral] :a
# 75| getValue: [IntegerLiteral] 5
# 75| getKey: [SymbolLiteral] :b
# 75| getRestVariableAccess: [LocalVariableAccess] map
# 76| getBranch: [InClause] in ... then ...
# 76| getPattern: [HashPattern] { ..., ** }
# 76| getKey: [SymbolLiteral] :a
# 76| getValue: [IntegerLiteral] 5
# 76| getKey: [SymbolLiteral] :b
# 77| getBranch: [InClause] in ... then ...
# 77| getPattern: [HashPattern] { ..., ** }
# 78| getBranch: [InClause] in ... then ...
# 78| getPattern: [HashPattern] { ..., ** }
# 79| getBranch: [InClause] in ... then ...
# 79| getPattern: [ArrayPattern] [ ..., * ]
# 84| getStmt: [AssignExpr] ... = ...
# 84| getAnOperand/getLeftOperand: [LocalVariableAccess] foo
# 84| getAnOperand/getRightOperand: [IntegerLiteral] 42
# 86| getStmt: [CaseExpr] case ...
# 86| getValue: [MethodCall] call to expr
# 86| getReceiver: [Self, SelfVariableAccess] self
# 87| getBranch: [InClause] in ... then ...
# 87| getPattern: [IntegerLiteral] 5
# 88| getBranch: [InClause] in ... then ...
# 88| getPattern: [VariableReferencePattern] ^...
# 88| getVariableAccess: [LocalVariableAccess] foo
# 89| getBranch: [InClause] in ... then ...
# 89| getPattern: [LocalVariableAccess] var
# 90| getBranch: [InClause] in ... then ...
# 90| getPattern: [StringLiteral] "string"
# 90| getComponent: [StringTextComponent] string
# 91| getBranch: [InClause] in ... then ...
# 91| getPattern: [ArrayLiteral] %w(...)
# 91| getElement: [StringLiteral] "foo"
# 91| getComponent: [StringTextComponent] foo
# 91| getElement: [StringLiteral] "bar"
# 91| getComponent: [StringTextComponent] bar
# 92| getBranch: [InClause] in ... then ...
# 92| getPattern: [ArrayLiteral] %i(...)
# 92| getElement: [SymbolLiteral] :"foo"
# 92| getComponent: [StringTextComponent] foo
# 92| getElement: [SymbolLiteral] :"bar"
# 92| getComponent: [StringTextComponent] bar
# 93| getBranch: [InClause] in ... then ...
# 93| getPattern: [RegExpLiteral] /.*abc[0-9]/
# 93| getParsed: [RegExpSequence] .*abc[0-9]
# 93| 0: [RegExpStar] .*
# 93| 0: [RegExpDot] .
# 93| 1: [RegExpConstant, RegExpNormalChar] a
# 93| 2: [RegExpConstant, RegExpNormalChar] b
# 93| 3: [RegExpConstant, RegExpNormalChar] c
# 93| 4: [RegExpCharacterClass] [0-9]
# 93| 0: [RegExpCharacterRange] 0-9
# 93| 0: [RegExpConstant, RegExpNormalChar] 0
# 93| 1: [RegExpConstant, RegExpNormalChar] 9
# 93| getComponent: [StringTextComponent] .*abc[0-9]
# 94| getBranch: [InClause] in ... then ...
# 94| getPattern: [RangeLiteral] _ .. _
# 94| getBegin: [IntegerLiteral] 5
# 94| getEnd: [IntegerLiteral] 10
# 95| getBranch: [InClause] in ... then ...
# 95| getPattern: [RangeLiteral] _ .. _
# 95| getEnd: [IntegerLiteral] 10
# 96| getBranch: [InClause] in ... then ...
# 96| getPattern: [RangeLiteral] _ .. _
# 96| getBegin: [IntegerLiteral] 5
# 97| getBranch: [InClause] in ... then ...
# 97| getPattern: [AsPattern] ... => ...
# 97| getPattern: [IntegerLiteral] 5
# 97| getVariableAccess: [LocalVariableAccess] x
# 98| getBranch: [InClause] in ... then ...
# 98| getPattern: [AlternativePattern] ... | ...
# 98| getAlternative: [IntegerLiteral] 5
# 98| getAlternative: [VariableReferencePattern] ^...
# 98| getVariableAccess: [LocalVariableAccess] foo
# 98| getAlternative: [LocalVariableAccess] var
# 98| getAlternative: [StringLiteral] "string"
# 98| getComponent: [StringTextComponent] string
# 99| getBranch: [InClause] in ... then ...
# 99| getPattern: [ConstantReadAccess] Foo
# 100| getBranch: [InClause] in ... then ...
# 100| getPattern: [ConstantReadAccess] Bar
# 100| getScopeExpr: [ConstantReadAccess] Foo
# 101| getBranch: [InClause] in ... then ...
# 101| getPattern: [ConstantReadAccess] Bar
# 101| getScopeExpr: [ConstantReadAccess] Foo
# 102| getBranch: [InClause] in ... then ...
# 102| getPattern: [AlternativePattern] ... | ...
# 102| getAlternative: [NilLiteral] nil
# 102| getAlternative: [Self, SelfVariableAccess] self
# 102| getAlternative: [BooleanLiteral] true
# 102| getAlternative: [BooleanLiteral] false
# 102| getAlternative: [LineLiteral] __LINE__
# 102| getAlternative: [FileLiteral] __FILE__
# 102| getAlternative: [EncodingLiteral] __ENCODING__
# 103| getBranch: [InClause] in ... then ...
# 103| getPattern: [Lambda] -> { ... }
# 103| getParameter: [SimpleParameter] x
# 103| getDefiningAccess: [LocalVariableAccess] x
# 103| getStmt: [EqExpr] ... == ...
# 103| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
# 103| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 10
# 104| getBranch: [InClause] in ... then ...
# 104| getPattern: [SymbolLiteral] :foo
# 105| getBranch: [InClause] in ... then ...
# 105| getPattern: [SymbolLiteral] :"foo bar"
# 105| getComponent: [StringTextComponent] foo bar
# 106| getBranch: [InClause] in ... then ...
# 106| getPattern: [AlternativePattern] ... | ...
# 106| getAlternative: [UnaryMinusExpr] - ...
# 106| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 5
# 106| getAlternative: [UnaryPlusExpr] + ...
# 106| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 10
# 111| getStmt: [CaseExpr] case ...
# 111| getValue: [MethodCall] call to expr
# 111| getReceiver: [Self, SelfVariableAccess] self
# 112| getBranch: [InClause] in ... then ...
# 112| getPattern: [ArrayPattern] [ ..., * ]
# 113| getBranch: [InClause] in ... then ...
# 113| getPattern: [ArrayPattern] [ ..., * ]
# 113| getPrefixElement: [LocalVariableAccess] x
# 114| getBranch: [InClause] in ... then ...
# 114| getPattern: [ArrayPattern] [ ..., * ]
# 114| getPrefixElement/getSuffixElement: [LocalVariableAccess] x
# 115| getBranch: [InClause] in ... then ...
# 115| getPattern: [ArrayPattern] [ ..., * ]
# 115| getClass: [ConstantReadAccess] Bar
# 115| getScopeExpr: [ConstantReadAccess] Foo
# 116| getBranch: [InClause] in ... then ...
# 116| getPattern: [ArrayPattern] [ ..., * ]
# 116| getClass: [ConstantReadAccess] Foo
# 117| getBranch: [InClause] in ... then ...
# 117| getPattern: [ArrayPattern] [ ..., * ]
# 117| getClass: [ConstantReadAccess] Bar
# 118| getBranch: [InClause] in ... then ...
# 118| getPattern: [ArrayPattern] [ ..., * ]
# 118| getClass: [ConstantReadAccess] Bar
# 118| getPrefixElement/getSuffixElement: [LocalVariableAccess] a
# 118| getPrefixElement/getSuffixElement: [LocalVariableAccess] b
# 118| getRestVariableAccess: [LocalVariableAccess] c
# 118| getSuffixElement: [LocalVariableAccess] d
# 118| getSuffixElement: [LocalVariableAccess] e
# 123| getStmt: [CaseExpr] case ...
# 123| getValue: [MethodCall] call to expr
# 123| getReceiver: [Self, SelfVariableAccess] self
# 124| getBranch: [InClause] in ... then ...
# 124| getPattern: [FindPattern] [ *,...,* ]
# 124| getElement: [LocalVariableAccess] x
# 125| getBranch: [InClause] in ... then ...
# 125| getPattern: [FindPattern] [ *,...,* ]
# 125| getPrefixVariableAccess: [LocalVariableAccess] x
# 125| getElement: [IntegerLiteral] 1
# 125| getElement: [IntegerLiteral] 2
# 125| getSuffixVariableAccess: [LocalVariableAccess] y
# 126| getBranch: [InClause] in ... then ...
# 126| getPattern: [FindPattern] [ *,...,* ]
# 126| getClass: [ConstantReadAccess] Bar
# 126| getScopeExpr: [ConstantReadAccess] Foo
# 126| getElement: [IntegerLiteral] 1
# 127| getBranch: [InClause] in ... then ...
# 127| getPattern: [FindPattern] [ *,...,* ]
# 127| getClass: [ConstantReadAccess] Foo
# 127| getElement: [ConstantReadAccess] Bar
# 132| getStmt: [CaseExpr] case ...
# 132| getValue: [MethodCall] call to expr
# 132| getReceiver: [Self, SelfVariableAccess] self
# 133| getBranch: [InClause] in ... then ...
# 133| getPattern: [HashPattern] { ..., ** }
# 134| getBranch: [InClause] in ... then ...
# 134| getPattern: [HashPattern] { ..., ** }
# 134| getKey: [SymbolLiteral] :x
# 135| getBranch: [InClause] in ... then ...
# 135| getPattern: [HashPattern] { ..., ** }
# 135| getClass: [ConstantReadAccess] Bar
# 135| getScopeExpr: [ConstantReadAccess] Foo
# 135| getKey: [SymbolLiteral] :x
# 135| getValue: [IntegerLiteral] 1
# 136| getBranch: [InClause] in ... then ...
# 136| getPattern: [HashPattern] { ..., ** }
# 136| getClass: [ConstantReadAccess] Bar
# 136| getScopeExpr: [ConstantReadAccess] Foo
# 136| getKey: [SymbolLiteral] :x
# 136| getValue: [IntegerLiteral] 1
# 136| getKey: [SymbolLiteral] :a
# 136| getRestVariableAccess: [LocalVariableAccess] rest
# 137| getBranch: [InClause] in ... then ...
# 137| getPattern: [HashPattern] { ..., ** }
# 137| getClass: [ConstantReadAccess] Foo
# 137| getKey: [SymbolLiteral] :y
# 138| getBranch: [InClause] in ... then ...
# 138| getPattern: [HashPattern] { ..., ** }
# 138| getClass: [ConstantReadAccess] Bar
# 139| getBranch: [InClause] in ... then ...
# 139| getPattern: [HashPattern] { ..., ** }
# 139| getClass: [ConstantReadAccess] Bar
# 139| getKey: [SymbolLiteral] :a
# 139| getValue: [IntegerLiteral] 1
modules/classes.rb:
# 2| [Toplevel] classes.rb
# 3| getStmt: [ClassDeclaration] Foo
@@ -2145,6 +2515,16 @@ params/params.rb:
# 70| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] a
# 70| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] b
# 70| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] c
# 73| getStmt: [Method] method_with_nil_splat
# 73| getParameter: [SimpleParameter] wibble
# 73| getDefiningAccess: [LocalVariableAccess] wibble
# 73| getParameter: [HashSplatNilParameter] **nil
# 77| getStmt: [MethodCall] call to each
# 77| getReceiver: [LocalVariableAccess] array
# 77| getBlock: [DoBlock] do ... end
# 77| getParameter: [SimpleParameter] val
# 77| getDefiningAccess: [LocalVariableAccess] val
# 77| getParameter: [HashSplatNilParameter] **nil
erb/template.html.erb:
# 19| [Toplevel] template.html.erb
# 19| getStmt: [StringLiteral] "hello world"

View File

@@ -266,6 +266,21 @@ calls/calls.rb:
# 340| getArgument: [IntegerLiteral] 4
# 340| getArgument: [IntegerLiteral] 5
# 340| getArgument: [IntegerLiteral] 6
control/cases.rb:
# 91| [ArrayLiteral] %w(...)
# 91| getDesugared: [MethodCall] call to []
# 91| getReceiver: [ConstantReadAccess] Array
# 91| getArgument: [StringLiteral] "foo"
# 91| getComponent: [StringTextComponent] foo
# 91| getArgument: [StringLiteral] "bar"
# 91| getComponent: [StringTextComponent] bar
# 92| [ArrayLiteral] %i(...)
# 92| getDesugared: [MethodCall] call to []
# 92| getReceiver: [ConstantReadAccess] Array
# 92| getArgument: [SymbolLiteral] :"foo"
# 92| getComponent: [StringTextComponent] foo
# 92| getArgument: [SymbolLiteral] :"bar"
# 92| getComponent: [StringTextComponent] bar
constants/constants.rb:
# 20| [ArrayLiteral] [...]
# 20| getDesugared: [MethodCall] call to []

View File

@@ -0,0 +1,4 @@
deadEnd
| control/cases.rb:19:13:19:19 | then ... |
| control/cases.rb:20:13:20:19 | then ... |
| control/cases.rb:21:13:21:19 | then ... |

View File

@@ -96,6 +96,122 @@
| control/cases.rb:21:6:21:6 | a | 0 |
| control/cases.rb:21:10:21:10 | b | 0 |
| control/cases.rb:21:18:21:19 | 30 | 30 |
| control/cases.rb:27:6:27:6 | 5 | 5 |
| control/cases.rb:27:13:27:16 | true | true |
| control/cases.rb:28:8:28:12 | false | false |
| control/cases.rb:32:19:32:19 | 0 | 0 |
| control/cases.rb:33:8:33:11 | true | true |
| control/cases.rb:34:15:34:15 | 0 | 0 |
| control/cases.rb:35:8:35:11 | true | true |
| control/cases.rb:36:8:36:12 | false | false |
| control/cases.rb:40:6:40:6 | 5 | 5 |
| control/cases.rb:41:6:41:6 | 5 | 5 |
| control/cases.rb:42:6:42:6 | 1 | 1 |
| control/cases.rb:42:9:42:9 | 2 | 2 |
| control/cases.rb:43:6:43:6 | 1 | 1 |
| control/cases.rb:43:9:43:9 | 2 | 2 |
| control/cases.rb:44:6:44:6 | 1 | 1 |
| control/cases.rb:44:9:44:9 | 2 | 2 |
| control/cases.rb:44:12:44:12 | 3 | 3 |
| control/cases.rb:45:6:45:6 | 1 | 1 |
| control/cases.rb:45:9:45:9 | 2 | 2 |
| control/cases.rb:45:12:45:12 | 3 | 3 |
| control/cases.rb:46:6:46:6 | 1 | 1 |
| control/cases.rb:46:9:46:9 | 2 | 2 |
| control/cases.rb:46:12:46:12 | 3 | 3 |
| control/cases.rb:47:6:47:6 | 1 | 1 |
| control/cases.rb:47:13:47:13 | 3 | 3 |
| control/cases.rb:49:9:49:9 | 3 | 3 |
| control/cases.rb:49:12:49:12 | 4 | 4 |
| control/cases.rb:50:9:50:9 | 3 | 3 |
| control/cases.rb:51:10:51:10 | 3 | 3 |
| control/cases.rb:52:6:52:6 | :a | a |
| control/cases.rb:53:6:53:6 | :a | a |
| control/cases.rb:53:9:53:9 | 5 | 5 |
| control/cases.rb:54:6:54:6 | :a | a |
| control/cases.rb:54:9:54:9 | 5 | 5 |
| control/cases.rb:55:6:55:6 | :a | a |
| control/cases.rb:55:9:55:9 | 5 | 5 |
| control/cases.rb:55:12:55:12 | :b | b |
| control/cases.rb:56:6:56:6 | :a | a |
| control/cases.rb:56:9:56:9 | 5 | 5 |
| control/cases.rb:56:12:56:12 | :b | b |
| control/cases.rb:57:6:57:6 | :a | a |
| control/cases.rb:57:9:57:9 | 5 | 5 |
| control/cases.rb:57:12:57:12 | :b | b |
| control/cases.rb:59:7:59:7 | 5 | 5 |
| control/cases.rb:60:7:60:7 | 5 | 5 |
| control/cases.rb:61:7:61:7 | 1 | 1 |
| control/cases.rb:61:10:61:10 | 2 | 2 |
| control/cases.rb:62:7:62:7 | 1 | 1 |
| control/cases.rb:62:10:62:10 | 2 | 2 |
| control/cases.rb:63:7:63:7 | 1 | 1 |
| control/cases.rb:63:10:63:10 | 2 | 2 |
| control/cases.rb:63:13:63:13 | 3 | 3 |
| control/cases.rb:64:7:64:7 | 1 | 1 |
| control/cases.rb:64:10:64:10 | 2 | 2 |
| control/cases.rb:64:13:64:13 | 3 | 3 |
| control/cases.rb:65:7:65:7 | 1 | 1 |
| control/cases.rb:65:10:65:10 | 2 | 2 |
| control/cases.rb:65:13:65:13 | 3 | 3 |
| control/cases.rb:66:7:66:7 | 1 | 1 |
| control/cases.rb:66:14:66:14 | 3 | 3 |
| control/cases.rb:68:10:68:10 | 3 | 3 |
| control/cases.rb:68:13:68:13 | 4 | 4 |
| control/cases.rb:69:10:69:10 | 3 | 3 |
| control/cases.rb:70:11:70:11 | 3 | 3 |
| control/cases.rb:71:7:71:7 | :a | a |
| control/cases.rb:72:7:72:7 | :a | a |
| control/cases.rb:72:10:72:10 | 5 | 5 |
| control/cases.rb:73:7:73:7 | :a | a |
| control/cases.rb:73:10:73:10 | 5 | 5 |
| control/cases.rb:74:7:74:7 | :a | a |
| control/cases.rb:74:10:74:10 | 5 | 5 |
| control/cases.rb:74:13:74:13 | :b | b |
| control/cases.rb:75:7:75:7 | :a | a |
| control/cases.rb:75:10:75:10 | 5 | 5 |
| control/cases.rb:75:13:75:13 | :b | b |
| control/cases.rb:76:7:76:7 | :a | a |
| control/cases.rb:76:10:76:10 | 5 | 5 |
| control/cases.rb:76:13:76:13 | :b | b |
| control/cases.rb:84:7:84:8 | 42 | 42 |
| control/cases.rb:87:6:87:6 | 5 | 5 |
| control/cases.rb:90:6:90:13 | "string" | string |
| control/cases.rb:91:9:91:11 | "foo" | foo |
| control/cases.rb:91:13:91:15 | "bar" | bar |
| control/cases.rb:92:9:92:11 | :"foo" | foo |
| control/cases.rb:92:13:92:15 | :"bar" | bar |
| control/cases.rb:93:6:93:17 | /.*abc[0-9]/ | .*abc[0-9] |
| control/cases.rb:94:6:94:6 | 5 | 5 |
| control/cases.rb:94:11:94:12 | 10 | 10 |
| control/cases.rb:95:9:95:10 | 10 | 10 |
| control/cases.rb:96:6:96:6 | 5 | 5 |
| control/cases.rb:97:6:97:6 | 5 | 5 |
| control/cases.rb:98:6:98:6 | 5 | 5 |
| control/cases.rb:98:23:98:30 | "string" | string |
| control/cases.rb:102:6:102:8 | nil | nil |
| control/cases.rb:102:19:102:22 | true | true |
| control/cases.rb:102:26:102:30 | false | false |
| control/cases.rb:102:34:102:41 | __LINE__ | 102 |
| control/cases.rb:102:45:102:52 | __FILE__ | control/cases.rb |
| control/cases.rb:102:56:102:67 | __ENCODING__ | UTF-8 |
| control/cases.rb:103:18:103:19 | 10 | 10 |
| control/cases.rb:104:6:104:9 | :foo | foo |
| control/cases.rb:105:6:105:15 | :"foo bar" | foo bar |
| control/cases.rb:106:7:106:7 | 5 | 5 |
| control/cases.rb:106:12:106:13 | 10 | 10 |
| control/cases.rb:125:11:125:11 | 1 | 1 |
| control/cases.rb:125:14:125:14 | 2 | 2 |
| control/cases.rb:126:18:126:18 | 1 | 1 |
| control/cases.rb:134:7:134:7 | :x | x |
| control/cases.rb:135:16:135:16 | :x | x |
| control/cases.rb:135:18:135:18 | 1 | 1 |
| control/cases.rb:136:16:136:16 | :x | x |
| control/cases.rb:136:18:136:18 | 1 | 1 |
| control/cases.rb:136:21:136:21 | :a | a |
| control/cases.rb:137:11:137:11 | :y | y |
| control/cases.rb:139:11:139:11 | :a | a |
| control/cases.rb:139:14:139:14 | 1 | 1 |
| control/conditionals.rb:2:5:2:5 | 0 | 0 |
| control/conditionals.rb:3:5:3:5 | 0 | 0 |
| control/conditionals.rb:4:5:4:5 | 0 | 0 |

View File

@@ -0,0 +1,4 @@
deadEnd
| cases.rb:19:13:19:19 | then ... |
| cases.rb:20:13:20:19 | then ... |
| cases.rb:21:13:21:19 | then ... |

View File

@@ -1,11 +1,25 @@
caseValues
| cases.rb:8:1:15:3 | case ... | cases.rb:8:6:8:6 | a |
| cases.rb:26:1:29:3 | case ... | cases.rb:26:6:26:9 | call to expr |
| cases.rb:31:1:37:3 | case ... | cases.rb:31:6:31:9 | call to expr |
| cases.rb:39:1:80:3 | case ... | cases.rb:39:6:39:9 | call to expr |
| cases.rb:86:1:107:3 | case ... | cases.rb:86:6:86:9 | call to expr |
| cases.rb:111:1:119:3 | case ... | cases.rb:111:6:111:9 | call to expr |
| cases.rb:123:1:128:3 | case ... | cases.rb:123:6:123:9 | call to expr |
| cases.rb:132:1:140:3 | case ... | cases.rb:132:6:132:9 | call to expr |
caseNoValues
| cases.rb:18:1:22:3 | case ... |
caseElseBranches
| cases.rb:8:1:15:3 | case ... | cases.rb:13:1:14:7 | else ... |
| cases.rb:26:1:29:3 | case ... | cases.rb:28:3:28:12 | else ... |
| cases.rb:31:1:37:3 | case ... | cases.rb:36:3:36:12 | else ... |
caseNoElseBranches
| cases.rb:18:1:22:3 | case ... |
| cases.rb:39:1:80:3 | case ... |
| cases.rb:86:1:107:3 | case ... |
| cases.rb:111:1:119:3 | case ... |
| cases.rb:123:1:128:3 | case ... |
| cases.rb:132:1:140:3 | case ... |
caseWhenBranches
| cases.rb:8:1:15:3 | case ... | cases.rb:9:1:10:7 | when ... | 0 | cases.rb:9:6:9:6 | b | cases.rb:9:7:10:7 | then ... |
| cases.rb:8:1:15:3 | case ... | cases.rb:11:1:12:7 | when ... | 0 | cases.rb:11:6:11:6 | c | cases.rb:11:10:12:7 | then ... |
@@ -20,3 +34,86 @@ caseAllBranches
| cases.rb:18:1:22:3 | case ... | 0 | cases.rb:19:1:19:19 | when ... |
| cases.rb:18:1:22:3 | case ... | 1 | cases.rb:20:1:20:19 | when ... |
| cases.rb:18:1:22:3 | case ... | 2 | cases.rb:21:1:21:19 | when ... |
| cases.rb:26:1:29:3 | case ... | 0 | cases.rb:27:3:27:16 | in ... then ... |
| cases.rb:26:1:29:3 | case ... | 1 | cases.rb:28:3:28:12 | else ... |
| cases.rb:31:1:37:3 | case ... | 0 | cases.rb:32:3:33:11 | in ... then ... |
| cases.rb:31:1:37:3 | case ... | 1 | cases.rb:34:3:35:11 | in ... then ... |
| cases.rb:31:1:37:3 | case ... | 2 | cases.rb:36:3:36:12 | else ... |
| cases.rb:39:1:80:3 | case ... | 0 | cases.rb:40:3:40:6 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 1 | cases.rb:41:3:41:8 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 2 | cases.rb:42:3:42:10 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 3 | cases.rb:43:3:43:11 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 4 | cases.rb:44:3:44:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 5 | cases.rb:45:3:45:14 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 6 | cases.rb:46:3:46:16 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 7 | cases.rb:47:3:47:14 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 8 | cases.rb:48:3:48:7 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 9 | cases.rb:49:3:49:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 10 | cases.rb:50:3:50:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 11 | cases.rb:51:3:51:15 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 12 | cases.rb:52:3:52:8 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 13 | cases.rb:53:3:53:10 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 14 | cases.rb:54:3:54:11 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 15 | cases.rb:55:3:55:18 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 16 | cases.rb:56:3:56:21 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 17 | cases.rb:57:3:57:21 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 18 | cases.rb:58:3:58:11 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 19 | cases.rb:59:3:59:9 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 20 | cases.rb:60:3:60:10 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 21 | cases.rb:61:3:61:12 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 22 | cases.rb:62:3:62:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 23 | cases.rb:63:3:63:15 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 24 | cases.rb:64:3:64:16 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 25 | cases.rb:65:3:65:18 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 26 | cases.rb:66:3:66:16 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 27 | cases.rb:67:3:67:9 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 28 | cases.rb:68:3:68:15 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 29 | cases.rb:69:3:69:15 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 30 | cases.rb:70:3:70:17 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 31 | cases.rb:71:3:71:10 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 32 | cases.rb:72:3:72:12 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 33 | cases.rb:73:3:73:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 34 | cases.rb:74:3:74:20 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 35 | cases.rb:75:3:75:23 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 36 | cases.rb:76:3:76:23 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 37 | cases.rb:77:3:77:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 38 | cases.rb:78:3:78:8 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 39 | cases.rb:79:3:79:8 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 0 | cases.rb:87:3:87:6 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 1 | cases.rb:88:3:88:9 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 2 | cases.rb:89:3:89:8 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 3 | cases.rb:90:3:90:13 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 4 | cases.rb:91:3:91:16 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 5 | cases.rb:92:3:92:16 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 6 | cases.rb:93:3:93:17 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 7 | cases.rb:94:3:94:12 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 8 | cases.rb:95:3:95:10 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 9 | cases.rb:96:3:96:9 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 10 | cases.rb:97:3:97:11 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 11 | cases.rb:98:3:98:30 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 12 | cases.rb:99:3:99:8 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 13 | cases.rb:100:3:100:13 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 14 | cases.rb:101:3:101:15 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 15 | cases.rb:102:3:102:67 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 16 | cases.rb:103:3:103:21 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 17 | cases.rb:104:3:104:9 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 18 | cases.rb:105:3:105:15 | in ... then ... |
| cases.rb:86:1:107:3 | case ... | 19 | cases.rb:106:3:106:13 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 0 | cases.rb:112:3:112:8 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 1 | cases.rb:113:3:113:9 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 2 | cases.rb:114:3:114:11 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 3 | cases.rb:115:3:115:16 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 4 | cases.rb:116:3:116:11 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 5 | cases.rb:117:3:117:12 | in ... then ... |
| cases.rb:111:1:119:3 | case ... | 6 | cases.rb:118:3:118:25 | in ... then ... |
| cases.rb:123:1:128:3 | case ... | 0 | cases.rb:124:3:124:15 | in ... then ... |
| cases.rb:123:1:128:3 | case ... | 1 | cases.rb:125:3:125:20 | in ... then ... |
| cases.rb:123:1:128:3 | case ... | 2 | cases.rb:126:3:126:23 | in ... then ... |
| cases.rb:123:1:128:3 | case ... | 3 | cases.rb:127:3:127:20 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 0 | cases.rb:133:3:133:8 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 1 | cases.rb:134:3:134:10 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 2 | cases.rb:135:3:135:21 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 3 | cases.rb:136:3:136:33 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 4 | cases.rb:137:3:137:14 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 5 | cases.rb:138:3:138:15 | in ... then ... |
| cases.rb:132:1:140:3 | case ... | 6 | cases.rb:139:3:139:23 | in ... then ... |

View File

@@ -11,7 +11,7 @@ query predicate caseElseBranches(CaseExpr c, StmtSequence elseBranch) {
query predicate caseNoElseBranches(CaseExpr c) { not exists(c.getElseBranch()) }
query predicate caseWhenBranches(CaseExpr c, WhenExpr when, int pIndex, Expr p, StmtSequence body) {
when = c.getAWhenBranch() and
when = c.getABranch() and
p = when.getPattern(pIndex) and
body = when.getBody()
}

View File

@@ -1,5 +1,12 @@
| cases.rb:8:1:15:3 | case ... | CaseExpr |
| cases.rb:18:1:22:3 | case ... | CaseExpr |
| cases.rb:26:1:29:3 | case ... | CaseExpr |
| cases.rb:31:1:37:3 | case ... | CaseExpr |
| cases.rb:39:1:80:3 | case ... | CaseExpr |
| cases.rb:86:1:107:3 | case ... | CaseExpr |
| cases.rb:111:1:119:3 | case ... | CaseExpr |
| cases.rb:123:1:128:3 | case ... | CaseExpr |
| cases.rb:132:1:140:3 | case ... | CaseExpr |
| conditionals.rb:10:1:12:3 | if ... | IfExpr |
| conditionals.rb:15:1:19:3 | if ... | IfExpr |
| conditionals.rb:22:1:30:3 | if ... | IfExpr |

View File

@@ -19,4 +19,123 @@ case
when a > b then 10
when a == b then 20
when a < b then 30
end
end
# pattern matching
case expr
in 5 then true
else false
end
case expr
in x unless x < 0
then true
in x if x < 0
then true
else false
end
case expr
in 5
in 5,
in 1, 2
in 1, 2,
in 1, 2, 3
in 1, 2, 3,
in 1, 2, 3, *
in 1, *x, 3
in *
in *, 3, 4
in *, 3, *
in *a, 3, *b
in a:
in a: 5
in a: 5,
in a: 5, b:, **
in a: 5, b:, **map
in a: 5, b:, **nil
in **nil
in [5]
in [5,]
in [1, 2]
in [1, 2,]
in [1, 2, 3]
in [1, 2, 3,]
in [1, 2, 3, *]
in [1, *x, 3]
in [*]
in [*, 3, 4]
in [*, 3, *]
in [*a, 3, *b]
in {a:}
in {a: 5}
in {a: 5,}
in {a: 5, b:, **}
in {a: 5, b:, **map}
in {a: 5, b:, **nil}
in {**nil}
in {}
in []
end
# more pattern matching
foo = 42
case expr
in 5
in ^foo
in var
in "string"
in %w(foo bar)
in %i(foo bar)
in /.*abc[0-9]/
in 5 .. 10
in .. 10
in 5 ..
in 5 => x
in 5 | ^foo | var | "string"
in Foo
in Foo::Bar
in ::Foo::Bar
in nil | self | true | false | __LINE__ | __FILE__ | __ENCODING__
in -> x { x == 10 }
in :foo
in :"foo bar"
in -5 | +10
end
# array patterns
case expr
in [];
in [x];
in [x, ];
in Foo::Bar[];
in Foo();
in Bar(*);
in Bar(a, b, *c, d, e);
end
# find patterns
case expr
in [*, x, *];
in [*x, 1, 2, *y];
in Foo::Bar[*, 1, *];
in Foo(*, Bar, *);
end
# hash patterns
case expr
in {};
in {x:};
in Foo::Bar[ x:1 ];
in Foo::Bar[ x:1, a:, **rest ];
in Foo( y:);
in Bar( ** );
in Bar( a: 1, **nil);
end

View File

@@ -33,6 +33,8 @@ idParams
| params.rb:70:35:70:35 | a | a |
| params.rb:70:38:70:38 | b | b |
| params.rb:70:48:70:48 | c | c |
| params.rb:73:27:73:32 | wibble | wibble |
| params.rb:77:16:77:18 | val | val |
blockParams
| params.rb:46:28:46:33 | &block | block |
| params.rb:62:29:62:34 | &block | block |
@@ -83,6 +85,8 @@ paramsInMethods
| params.rb:58:1:59:3 | method_with_optional_params | 1 | params.rb:58:39:58:42 | val2 | OptionalParameter |
| params.rb:58:1:59:3 | method_with_optional_params | 2 | params.rb:58:49:58:52 | val3 | OptionalParameter |
| params.rb:62:1:64:3 | use_block_with_optional | 0 | params.rb:62:29:62:34 | &block | BlockParameter |
| params.rb:73:1:74:3 | method_with_nil_splat | 0 | params.rb:73:27:73:32 | wibble | SimpleParameter |
| params.rb:73:1:74:3 | method_with_nil_splat | 1 | params.rb:73:35:73:39 | **nil | HashSplatNilParameter |
paramsInBlocks
| params.rb:9:11:11:3 | do ... end | 0 | params.rb:9:15:9:17 | key | SimpleParameter |
| params.rb:9:11:11:3 | do ... end | 1 | params.rb:9:20:9:24 | value | SimpleParameter |
@@ -94,6 +98,8 @@ paramsInBlocks
| params.rb:49:24:51:3 | do ... end | 1 | params.rb:49:33:49:34 | yy | KeywordParameter |
| params.rb:65:25:67:3 | do ... end | 0 | params.rb:65:29:65:32 | name | SimpleParameter |
| params.rb:65:25:67:3 | do ... end | 1 | params.rb:65:35:65:37 | age | OptionalParameter |
| params.rb:77:12:78:3 | do ... end | 0 | params.rb:77:16:77:18 | val | SimpleParameter |
| params.rb:77:12:78:3 | do ... end | 1 | params.rb:77:21:77:25 | **nil | HashSplatNilParameter |
paramsInLambdas
| params.rb:14:7:14:33 | -> { ... } | 0 | params.rb:14:11:14:13 | foo | SimpleParameter |
| params.rb:14:7:14:33 | -> { ... } | 1 | params.rb:14:16:14:18 | bar | SimpleParameter |
@@ -147,3 +153,7 @@ params
| params.rb:70:35:70:35 | a | 0 | SimpleParameter |
| params.rb:70:38:70:38 | b | 1 | OptionalParameter |
| params.rb:70:48:70:48 | c | 2 | OptionalParameter |
| params.rb:73:27:73:32 | wibble | 0 | SimpleParameter |
| params.rb:73:35:73:39 | **nil | 1 | HashSplatNilParameter |
| params.rb:77:16:77:18 | val | 0 | SimpleParameter |
| params.rb:77:21:77:25 | **nil | 1 | HashSplatNilParameter |

View File

@@ -67,4 +67,13 @@ use_block_with_optional do |name, age = 99|
end
# Lambda containing optional parameters
lambda_with_optional_params = -> (a, b = 1000, c = 20) { a+b+c }
lambda_with_optional_params = -> (a, b = 1000, c = 20) { a+b+c }
# Method containing nil hash-splat params
def method_with_nil_splat(wibble, **nil)
end
# Block with nil hash-splat parameter
array.each do |val, **nil|
end

View File

@@ -1,2 +1,4 @@
| src/not_ruby.rb:5:25:5:26 | parse error | Extraction failed in src/not_ruby.rb with error parse error | 2 |
| src/unsupported_feature.rb:1:6:2:11 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |
| src/unsupported_feature.rb:2:1:2:4 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |
| src/unsupported_feature.rb:3:7:3:7 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |
| src/unsupported_feature.rb:3:14:3:14 | parse error | Extraction failed in src/unsupported_feature.rb with error parse error | 2 |

View File

@@ -1,3 +1,3 @@
case foo
in 3 then 5
end
# one line pattern matches
5 in 3
[1,2] => [x, *]