mirror of
https://github.com/github/codeql.git
synced 2026-02-19 16:33:40 +01:00
Various changes to user-facing library
- Remove `abstract` classes from public API. - Align `Variable.qll` with rest of library. - Introduce `Callable` class. - Make `Pattern` class cover everything that can be on the LHS of an assignment and in a pattern (except special parameters such as `**param`).
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import codeql.Locations
|
||||
import codeql_ruby.ast.Method
|
||||
import codeql_ruby.ast.Parameter
|
||||
import codeql_ruby.ast.Pattern
|
||||
import codeql_ruby.ast.Variable
|
||||
private import codeql_ruby.Generated
|
||||
|
||||
/**
|
||||
@@ -26,29 +28,4 @@ class AstNode extends @ast_node {
|
||||
|
||||
/** Gets the location if this node. */
|
||||
Location getLocation() { result = generated.getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the parent of this node in the abstract syntax tree, if it has one.
|
||||
*/
|
||||
AstNode getParent() { result = generated.getParent() }
|
||||
|
||||
/**
|
||||
* Gets the index (position) of this node in the parent node's list of
|
||||
* children.
|
||||
*/
|
||||
int getParentIndex() { result = generated.getParentIndex() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Models program elements for destructured patterns.
|
||||
*/
|
||||
abstract class Pattern extends AstNode {
|
||||
/** Gets the number of elements in this pattern. */
|
||||
abstract int getNumberOfElements();
|
||||
|
||||
/** Gets the nth element in this pattern. */
|
||||
abstract AstNode getElement(int n);
|
||||
|
||||
/** Gets an element in this pattern. */
|
||||
AstNode getAnElement() { result = this.getElement(_) }
|
||||
}
|
||||
|
||||
@@ -1,17 +1,30 @@
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
private import internal.Method
|
||||
|
||||
/** A Ruby method. */
|
||||
class Method extends @method, AstNode {
|
||||
Generated::Method generated;
|
||||
/** A callable. */
|
||||
class Callable extends AstNode {
|
||||
Callable() { this instanceof CallableRange }
|
||||
|
||||
Method() { generated = this }
|
||||
/** Gets the number of parameters of this callable. */
|
||||
final int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
/** Gets a parameter of this callable. */
|
||||
final Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the nth parameter of this callable. */
|
||||
final Parameter getParameter(int n) { result = this.(CallableRange).getParameter(n) }
|
||||
}
|
||||
|
||||
/** A method. */
|
||||
class Method extends Callable, @method {
|
||||
final override Generated::Method generated;
|
||||
|
||||
override string describeQlClass() { result = "Method" }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of the method. */
|
||||
/** Gets the name of this method. */
|
||||
string getName() {
|
||||
result = generated.getName().(Generated::Token).getValue() or
|
||||
// TODO: use hand-written Symbol class
|
||||
@@ -21,7 +34,7 @@ class Method extends @method, AstNode {
|
||||
|
||||
/**
|
||||
* Holds if this is a setter method, as in the following example:
|
||||
* ```
|
||||
* ```rb
|
||||
* class Person
|
||||
* def name=(n)
|
||||
* @name = n
|
||||
@@ -30,90 +43,63 @@ class Method extends @method, AstNode {
|
||||
* ```
|
||||
*/
|
||||
predicate isSetter() { generated.getName() instanceof Generated::Setter }
|
||||
}
|
||||
|
||||
/** Gets the number of parameters of this method. */
|
||||
int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
/** A singleton method. */
|
||||
class SingletonMethod extends Callable, @singleton_method {
|
||||
final override Generated::SingletonMethod generated;
|
||||
|
||||
/** Gets a parameter of this method. */
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
override string describeQlClass() { result = "SingletonMethod" }
|
||||
|
||||
/** Gets the nth parameter of this method. */
|
||||
Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of this method. */
|
||||
string getName() {
|
||||
result = generated.getName().(Generated::Token).getValue() or
|
||||
// TODO: use hand-written Symbol class
|
||||
result = generated.getName().(Generated::Symbol).toString() or
|
||||
result = generated.getName().(Generated::Setter).getName().getValue() + "="
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Ruby lambda (anonymous method). For example:
|
||||
* ```
|
||||
* A lambda (anonymous method). For example:
|
||||
* ```rb
|
||||
* -> (x) { x + 1 }
|
||||
* ```
|
||||
*/
|
||||
class Lambda extends @lambda, AstNode {
|
||||
Generated::Lambda generated;
|
||||
|
||||
Lambda() { generated = this }
|
||||
class Lambda extends Callable, @lambda {
|
||||
final override Generated::Lambda generated;
|
||||
|
||||
override string describeQlClass() { result = "Lambda" }
|
||||
|
||||
override string toString() { result = "-> { ... }" }
|
||||
|
||||
/** Gets the number of parameters of this lambda. */
|
||||
int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
/** Gets a parameter of this lambda. */
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the nth parameter of this lambda. */
|
||||
Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
}
|
||||
|
||||
/** A Ruby block. */
|
||||
abstract class Block extends AstNode {
|
||||
/** Gets the number of parameters of this block. */
|
||||
abstract int getNumberOfParameters();
|
||||
|
||||
/** Gets the nth parameter of this block. */
|
||||
abstract Parameter getParameter(int n);
|
||||
|
||||
/** Gets a parameter of this block. */
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
// TODO: body/statements
|
||||
/** A block. */
|
||||
class Block extends AstNode, Callable {
|
||||
Block() { this instanceof BlockRange }
|
||||
}
|
||||
|
||||
/** A Ruby block enclosed within `do` and `end`. */
|
||||
class DoBlock extends @do_block, Block {
|
||||
Generated::DoBlock generated;
|
||||
|
||||
DoBlock() { generated = this }
|
||||
/** A block enclosed within `do` and `end`. */
|
||||
class DoBlock extends Block, @do_block {
|
||||
final override Generated::DoBlock generated;
|
||||
|
||||
override string describeQlClass() { result = "DoBlock" }
|
||||
|
||||
override string toString() { result = "| ... |" }
|
||||
|
||||
/** Gets the number of parameters of this block. */
|
||||
override int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
/** Gets the nth parameter of this block. */
|
||||
override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Ruby block defined using curly braces, e.g. in the following code:
|
||||
* ```
|
||||
* A block defined using curly braces, e.g. in the following code:
|
||||
* ```rb
|
||||
* names.each { |name| puts name }
|
||||
* ```
|
||||
*/
|
||||
class BraceBlock extends @block, Block {
|
||||
Generated::Block generated;
|
||||
|
||||
BraceBlock() { generated = this }
|
||||
class BraceBlock extends Block, @block {
|
||||
final override Generated::Block generated;
|
||||
|
||||
override string describeQlClass() { result = "BraceBlock" }
|
||||
|
||||
override string toString() { result = "{ ... }" }
|
||||
|
||||
/** Gets the number of parameters of this block. */
|
||||
override int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
/** Gets the nth parameter of this block. */
|
||||
override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
}
|
||||
|
||||
@@ -1,105 +1,123 @@
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
private import Variable
|
||||
private import Pattern
|
||||
private import internal.Variable
|
||||
|
||||
/** A parameter. */
|
||||
class Parameter extends AstNode {
|
||||
private int pos;
|
||||
|
||||
Parameter() {
|
||||
this = any(Generated::BlockParameters bp).getChild(pos)
|
||||
or
|
||||
this = any(Generated::MethodParameters mp).getChild(pos)
|
||||
or
|
||||
this = any(Generated::LambdaParameters lp).getChild(pos)
|
||||
}
|
||||
|
||||
/** Gets the callable that this parameter belongs to. */
|
||||
Callable getCallable() { result.getAParameter() = this }
|
||||
|
||||
/** Gets the zero-based position of this parameter. */
|
||||
int getPosition() { result = pos }
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter to a block, lambda, or method.
|
||||
* A parameter defined using a pattern.
|
||||
*
|
||||
* This includes both simple parameters and tuple parameters.
|
||||
*/
|
||||
abstract class Parameter extends AstNode {
|
||||
/**
|
||||
* Gets the position of this parameter in the parent block, lambda, or
|
||||
* method's parameter list.
|
||||
*/
|
||||
int getPosition() {
|
||||
exists(Method m | m.getParameter(result) = this) or
|
||||
exists(Block b | b.getParameter(result) = this) or
|
||||
exists(Lambda l | l.getParameter(result) = this)
|
||||
}
|
||||
class PatternParameter extends Parameter, Pattern {
|
||||
override string toString() { result = Pattern.super.toString() }
|
||||
|
||||
override Location getLocation() { result = Pattern.super.getLocation() }
|
||||
}
|
||||
|
||||
/** A parameter defined using a tuple pattern. */
|
||||
class TuplePatternParameter extends PatternParameter, TuplePattern {
|
||||
override string toString() { result = TuplePattern.super.toString() }
|
||||
|
||||
override string describeQlClass() { result = "TuplePatternParameter" }
|
||||
}
|
||||
|
||||
/** A named parameter. */
|
||||
class NamedParameter extends Parameter {
|
||||
NamedParameter() { not this instanceof TuplePattern }
|
||||
|
||||
/** Gets the name of this parameter. */
|
||||
string getName() { none() }
|
||||
|
||||
/** Gets the variable introduced by this parameter. */
|
||||
Variable getVariable() { none() }
|
||||
|
||||
/** Gets an access to this parameter. */
|
||||
final VariableAccess getAnAccess() { result = this.getVariable().getAnAccess() }
|
||||
}
|
||||
|
||||
/** A simple (normal) parameter. */
|
||||
class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern {
|
||||
override string getName() { result = VariablePattern.super.getName() }
|
||||
|
||||
final override Variable getVariable() { result = TLocalVariable(_, _, this) }
|
||||
|
||||
override string describeQlClass() { result = "SimpleParameter" }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter that is a block. For example, `&bar` in the following code:
|
||||
* ```
|
||||
* ```rb
|
||||
* def foo(&bar)
|
||||
* bar.call if block_given?
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class BlockParameter extends @block_parameter, Parameter {
|
||||
Generated::BlockParameter generated;
|
||||
class BlockParameter extends @block_parameter, NamedParameter {
|
||||
override Generated::BlockParameter generated;
|
||||
|
||||
BlockParameter() { generated = this }
|
||||
final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) }
|
||||
|
||||
override string describeQlClass() { result = "BlockParameter" }
|
||||
|
||||
override string toString() { result = "&" + this.getName() }
|
||||
|
||||
/** Gets the name of the parameter. */
|
||||
string getName() { result = generated.getName().getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A parameter that is destructured. For example, the parameter `(a, b)` in the
|
||||
* following code:
|
||||
* ```
|
||||
* pairs.each do |(a, b)|
|
||||
* puts a + b
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class PatternParameter extends @destructured_parameter, Parameter, Pattern {
|
||||
Generated::DestructuredParameter generated;
|
||||
|
||||
PatternParameter() { generated = this }
|
||||
|
||||
override string describeQlClass() { result = "PatternParameter" }
|
||||
|
||||
override string toString() { result = "(..., ...)" }
|
||||
|
||||
/**
|
||||
* Gets the number of parameters of this destructuring.
|
||||
*/
|
||||
override int getNumberOfElements() { result = count(this.getElement(_)) }
|
||||
|
||||
/**
|
||||
* Gets the nth parameter of this pattern.
|
||||
*/
|
||||
override AstNode getElement(int n) { result = generated.getChild(n) }
|
||||
override string getName() { result = generated.getName().getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A hash-splat (or double-splat) parameter. For example, `**options` in the
|
||||
* following code:
|
||||
* ```
|
||||
* ```rb
|
||||
* def foo(bar, **options)
|
||||
* ...
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class HashSplatParameter extends @hash_splat_parameter, Parameter {
|
||||
Generated::HashSplatParameter generated;
|
||||
class HashSplatParameter extends @hash_splat_parameter, NamedParameter {
|
||||
override Generated::HashSplatParameter generated;
|
||||
|
||||
HashSplatParameter() { generated = this }
|
||||
final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) }
|
||||
|
||||
override string describeQlClass() { result = "HashSplatParameter" }
|
||||
|
||||
override string toString() { result = "**" + this.getName() }
|
||||
|
||||
/** Gets the name of the parameter. */
|
||||
string getName() { result = generated.getName().getValue() }
|
||||
override string getName() { result = generated.getName().getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
class KeywordParameter extends @keyword_parameter, Parameter {
|
||||
Generated::KeywordParameter generated;
|
||||
class KeywordParameter extends @keyword_parameter, NamedParameter {
|
||||
override Generated::KeywordParameter generated;
|
||||
|
||||
KeywordParameter() { generated = this }
|
||||
final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) }
|
||||
|
||||
override string describeQlClass() { result = "KeywordParameter" }
|
||||
|
||||
/** Gets the name of the parameter. */
|
||||
string getName() { result = generated.getName().getValue() }
|
||||
override string getName() { result = generated.getName().getValue() }
|
||||
|
||||
/**
|
||||
* Gets the default value, i.e. the value assigned to the parameter when one
|
||||
@@ -115,23 +133,22 @@ class KeywordParameter extends @keyword_parameter, Parameter {
|
||||
/**
|
||||
* An optional parameter. For example, the parameter `name` in the following
|
||||
* code:
|
||||
* ```
|
||||
* ```rb
|
||||
* def say_hello(name = 'Anon')
|
||||
* puts "hello #{name}"
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class OptionalParameter extends @optional_parameter, Parameter {
|
||||
Generated::OptionalParameter generated;
|
||||
class OptionalParameter extends @optional_parameter, NamedParameter {
|
||||
override Generated::OptionalParameter generated;
|
||||
|
||||
OptionalParameter() { generated = this }
|
||||
final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) }
|
||||
|
||||
override string describeQlClass() { result = "OptionalParameter" }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of the parameter. */
|
||||
string getName() { result = generated.getName().getValue() }
|
||||
override string getName() { result = generated.getName().getValue() }
|
||||
|
||||
/**
|
||||
* Gets the default value, i.e. the value assigned to the parameter when one
|
||||
@@ -143,40 +160,20 @@ class OptionalParameter extends @optional_parameter, Parameter {
|
||||
|
||||
/**
|
||||
* A splat parameter. For example, `*values` in the following code:
|
||||
* ```
|
||||
* ```rb
|
||||
* def foo(bar, *values)
|
||||
* ...
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
class SplatParameter extends @splat_parameter, Parameter {
|
||||
Generated::SplatParameter generated;
|
||||
class SplatParameter extends @splat_parameter, NamedParameter {
|
||||
override Generated::SplatParameter generated;
|
||||
|
||||
SplatParameter() { generated = this }
|
||||
final override Variable getVariable() { result = TLocalVariable(_, _, generated.getName()) }
|
||||
|
||||
override string describeQlClass() { result = "SplatParameter" }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of the parameter. */
|
||||
string getName() { result = generated.getName().getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An identifier that is a parameter in a block, lambda, or method.
|
||||
*/
|
||||
class IdentifierParameter extends @token_identifier, Parameter {
|
||||
IdentifierParameter() {
|
||||
block_parameters_child(_, _, this) or
|
||||
destructured_parameter_child(_, _, this) or
|
||||
lambda_parameters_child(_, _, this) or
|
||||
method_parameters_child(_, _, this)
|
||||
}
|
||||
|
||||
override string describeQlClass() { result = "IdentifierParameter" }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of the parameter. */
|
||||
string getName() { result = this.(Generated::Identifier).getValue() }
|
||||
override string getName() { result = generated.getName().getValue() }
|
||||
}
|
||||
|
||||
40
ql/src/codeql_ruby/ast/Pattern.qll
Normal file
40
ql/src/codeql_ruby/ast/Pattern.qll
Normal file
@@ -0,0 +1,40 @@
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
private import codeql.Locations
|
||||
private import internal.Pattern
|
||||
private import Variable
|
||||
|
||||
/** A pattern. */
|
||||
class Pattern extends AstNode {
|
||||
Pattern() { this instanceof PatternRange }
|
||||
}
|
||||
|
||||
/** A simple variable pattern. */
|
||||
class VariablePattern extends Pattern {
|
||||
override Generated::Identifier generated;
|
||||
|
||||
/** Gets the name of the variable used in this pattern. */
|
||||
string getName() { result = generated.getValue() }
|
||||
|
||||
/** Gets the variable used in this pattern. */
|
||||
Variable getVariable() { this = result.getAnAccess() }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A tuple pattern.
|
||||
*
|
||||
* This includes both tuple patterns in parameters and assignments.
|
||||
*/
|
||||
class TuplePattern extends Pattern {
|
||||
TuplePattern() { this instanceof TuplePatternRange }
|
||||
|
||||
/** Gets the `i`th pattern in this tuple pattern. */
|
||||
final Pattern getElement(int i) { result = this.(TuplePatternRange).getElement(i) }
|
||||
|
||||
/** Gets a sub pattern in this tuple pattern. */
|
||||
final Pattern getAnElement() { result = this.getElement(_) }
|
||||
|
||||
override string toString() { result = "(..., ...)" }
|
||||
}
|
||||
@@ -1,140 +1,9 @@
|
||||
/** Provides classes for modeling program variables. */
|
||||
|
||||
private import codeql_ruby.Generated::Generated
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
private import codeql.Locations
|
||||
|
||||
private AstNode parent(AstNode n) {
|
||||
result = n.getParent() and
|
||||
not n = any(VariableScope s).getScopeElement()
|
||||
}
|
||||
|
||||
/** Gets the enclosing scope for `node`. */
|
||||
private VariableScope enclosingScope(AstNode node) {
|
||||
result.getScopeElement() = parent*(node.getParent())
|
||||
}
|
||||
|
||||
/** A parameter. */
|
||||
class Parameter extends AstNode {
|
||||
private int position;
|
||||
private VariableScope scope;
|
||||
|
||||
Parameter() {
|
||||
this =
|
||||
scope.(BlockScope).getScopeElement().getAFieldOrChild().(BlockParameters).getChild(position)
|
||||
or
|
||||
this =
|
||||
scope.(MethodScope).getScopeElement().getAFieldOrChild().(MethodParameters).getChild(position)
|
||||
}
|
||||
|
||||
/** Gets the (zero-based) position of this parameter. */
|
||||
final int getPosition() { result = position }
|
||||
|
||||
/** Gets the scope this parameter is declared in. */
|
||||
final VariableScope getDeclaringScope() { result = scope }
|
||||
|
||||
/** Gets an access to this parameter. */
|
||||
final ParameterAccess getAnAccess() { result.getParameter() = this }
|
||||
}
|
||||
|
||||
private Identifier parameterIdentifier(Parameter p) {
|
||||
result = p or
|
||||
result = p.(SplatParameter).getName() or
|
||||
result = p.(HashSplatParameter).getName() or
|
||||
result = p.(BlockParameter).getName() or
|
||||
result = p.(OptionalParameter).getName() or
|
||||
result = p.(KeywordParameter).getName() or
|
||||
result = destructuredIdentifier(p.(DestructuredParameter))
|
||||
}
|
||||
|
||||
private Identifier destructuredIdentifier(AstNode node) {
|
||||
result = node or
|
||||
result = destructuredIdentifier(node.(DestructuredParameter).getAFieldOrChild())
|
||||
}
|
||||
|
||||
/** Holds if `scope` defines `name` in its parameter declaration. */
|
||||
private predicate scopeDefinesParameter(VariableScope scope, string name, Location location) {
|
||||
location =
|
||||
min(Parameter p, Identifier i |
|
||||
scope = p.getDeclaringScope() and
|
||||
i = parameterIdentifier(p) and
|
||||
name = i.getValue()
|
||||
|
|
||||
i.getLocation() as loc order by loc.getStartLine(), loc.getStartColumn()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `var` is assigned in `scope`. */
|
||||
private predicate scopeAssigns(VariableScope scope, Identifier var) {
|
||||
var in [any(Assignment assign).getLeft(), any(OperatorAssignment assign).getLeft()] and
|
||||
scope = enclosingScope(var)
|
||||
}
|
||||
|
||||
/** Holds if location `one` starts strictly before location `two` */
|
||||
pragma[inline]
|
||||
predicate strictlyBefore(Location one, Location two) {
|
||||
one.getStartLine() < two.getStartLine()
|
||||
or
|
||||
one.getStartLine() = two.getStartLine() and one.getStartColumn() < two.getStartColumn()
|
||||
}
|
||||
|
||||
/** Holds if block scope `scope` inherits `var` from an outer scope `outer`. */
|
||||
private predicate blockScopeInherits(BlockScope scope, string var, VariableScope outer) {
|
||||
not scopeDefinesParameter(scope, var, _) and
|
||||
(
|
||||
outer = scope.getOuterScope() and
|
||||
(
|
||||
scopeDefinesParameter(outer, var, _)
|
||||
or
|
||||
exists(Identifier i | i.getValue() = var |
|
||||
scopeAssigns(outer, i) and
|
||||
strictlyBefore(i.getLocation(), scope.getLocation())
|
||||
)
|
||||
)
|
||||
or
|
||||
blockScopeInherits(scope.getOuterScope(), var, outer)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
newtype TScope =
|
||||
TTopLevelScope(Program node) or
|
||||
TModuleScope(Module node) or
|
||||
TClassScope(AstNode cls) { cls instanceof Class or cls instanceof SingletonClass } or
|
||||
TMethodScope(AstNode method) { method instanceof Method or method instanceof SingletonMethod } or
|
||||
TBlockScope(AstNode block) { block instanceof Block or block instanceof DoBlock }
|
||||
|
||||
cached
|
||||
newtype TVariable =
|
||||
TLocalVariable(VariableScope scope, string name, Location location) {
|
||||
scopeDefinesParameter(scope, name, location)
|
||||
or
|
||||
not scopeDefinesParameter(scope, name, _) and
|
||||
not blockScopeInherits(scope, name, _) and
|
||||
location =
|
||||
min(Location loc, Identifier other |
|
||||
loc = other.getLocation() and name = other.getValue() and scopeAssigns(scope, other)
|
||||
|
|
||||
loc order by loc.getStartLine(), loc.getStartColumn()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate access(Identifier access, Variable variable) {
|
||||
exists(string name | name = access.getValue() |
|
||||
variable = enclosingScope(access).getVariable(name) and
|
||||
not strictlyBefore(access.getLocation(), variable.getLocation())
|
||||
or
|
||||
exists(VariableScope declScope |
|
||||
variable = declScope.getVariable(name) and
|
||||
blockScopeInherits(enclosingScope(access), name, declScope)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private import Cached
|
||||
private import internal.Variable
|
||||
|
||||
/** A scope in which variables can be declared. */
|
||||
class VariableScope extends TScope {
|
||||
@@ -157,6 +26,47 @@ class VariableScope extends TScope {
|
||||
}
|
||||
}
|
||||
|
||||
/** A top-level scope. */
|
||||
class TopLevelScope extends VariableScope, TTopLevelScope {
|
||||
final override string toString() { result = "top-level scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TTopLevelScope(result) = this }
|
||||
}
|
||||
|
||||
/** A module scope. */
|
||||
class ModuleScope extends VariableScope, TModuleScope {
|
||||
final override string toString() { result = "module scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TModuleScope(result) = this }
|
||||
}
|
||||
|
||||
/** A class scope. */
|
||||
class ClassScope extends VariableScope, TClassScope {
|
||||
final override string toString() { result = "class scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TClassScope(result) = this }
|
||||
}
|
||||
|
||||
/** A callable scope. */
|
||||
class CallableScope extends VariableScope, TCallableScope {
|
||||
private Callable c;
|
||||
|
||||
CallableScope() { this = TCallableScope(c) }
|
||||
|
||||
final override string toString() {
|
||||
(c instanceof Method or c instanceof SingletonMethod) and
|
||||
result = "method scope"
|
||||
or
|
||||
c instanceof Lambda and
|
||||
result = "lambda scope"
|
||||
or
|
||||
c instanceof Block and
|
||||
result = "block scope"
|
||||
}
|
||||
|
||||
final override Callable getScopeElement() { TCallableScope(result) = this }
|
||||
}
|
||||
|
||||
/** A variable declared in a scope. */
|
||||
class Variable extends TVariable {
|
||||
/** Gets the name of this variable. */
|
||||
@@ -179,78 +89,37 @@ class Variable extends TVariable {
|
||||
class LocalVariable extends Variable {
|
||||
private VariableScope scope;
|
||||
private string name;
|
||||
private Location location;
|
||||
private Generated::Identifier i;
|
||||
|
||||
LocalVariable() { this = TLocalVariable(scope, name, location) }
|
||||
LocalVariable() { this = TLocalVariable(scope, name, i) }
|
||||
|
||||
final override string getName() { result = name }
|
||||
|
||||
final override Location getLocation() { result = location }
|
||||
final override Location getLocation() { result = i.getLocation() }
|
||||
|
||||
final override VariableScope getDeclaringScope() { result = scope }
|
||||
|
||||
final override LocalVariableAccess getAnAccess() { result.getVariable() = this }
|
||||
}
|
||||
|
||||
/** An identifier that refers to a variable. */
|
||||
class VariableAccess extends Identifier {
|
||||
/** An access to a variable. */
|
||||
class VariableAccess extends AstNode, @token_identifier {
|
||||
override Generated::Identifier generated;
|
||||
Variable variable;
|
||||
|
||||
VariableAccess() { access(this, variable) }
|
||||
|
||||
/**
|
||||
* Gets the variable this identifier refers to.
|
||||
*/
|
||||
/** Gets the variable this identifier refers to. */
|
||||
Variable getVariable() { result = variable }
|
||||
|
||||
override string toString() { result = variable.getName() }
|
||||
}
|
||||
|
||||
/** An identifier that refers to a parameter. */
|
||||
class ParameterAccess extends VariableAccess {
|
||||
Parameter parameter;
|
||||
/** An access to a local variable. */
|
||||
class LocalVariableAccess extends VariableAccess {
|
||||
override LocalVariable variable;
|
||||
|
||||
ParameterAccess() {
|
||||
exists(Identifier i |
|
||||
i = parameterIdentifier(parameter) and
|
||||
variable.getDeclaringScope() = parameter.getDeclaringScope() and
|
||||
variable.getLocation() = i.getLocation()
|
||||
)
|
||||
}
|
||||
override LocalVariable getVariable() { result = variable }
|
||||
|
||||
final Parameter getParameter() { result = parameter }
|
||||
}
|
||||
|
||||
/** A top-level scope. */
|
||||
class TopLevelScope extends VariableScope, TTopLevelScope {
|
||||
final override string toString() { result = "top-level scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TTopLevelScope(result) = this }
|
||||
}
|
||||
|
||||
/** A module scope. */
|
||||
class ModuleScope extends VariableScope, TModuleScope {
|
||||
final override string toString() { result = "module scope" }
|
||||
|
||||
final override Module getScopeElement() { TModuleScope(result) = this }
|
||||
}
|
||||
|
||||
/** A class scope. */
|
||||
class ClassScope extends VariableScope, TClassScope {
|
||||
final override string toString() { result = "class scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TClassScope(result) = this }
|
||||
}
|
||||
|
||||
/** A method scope. */
|
||||
class MethodScope extends VariableScope, TMethodScope {
|
||||
final override string toString() { result = "method scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TMethodScope(result) = this }
|
||||
}
|
||||
|
||||
/** A block scope. */
|
||||
class BlockScope extends VariableScope, TBlockScope {
|
||||
final override string toString() { result = "block scope" }
|
||||
|
||||
final override AstNode getScopeElement() { TBlockScope(result) = this }
|
||||
|
||||
/** Gets the scope in which this scope is nested, if any. */
|
||||
final VariableScope getOuterScope() { result = enclosingScope(this.getScopeElement()) }
|
||||
override string toString() { result = variable.getName() }
|
||||
}
|
||||
|
||||
42
ql/src/codeql_ruby/ast/internal/Method.qll
Normal file
42
ql/src/codeql_ruby/ast/internal/Method.qll
Normal file
@@ -0,0 +1,42 @@
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
|
||||
abstract class CallableRange extends AstNode {
|
||||
abstract Parameter getParameter(int n);
|
||||
}
|
||||
|
||||
private class MethodRange extends CallableRange, @method {
|
||||
final override Generated::Method generated;
|
||||
|
||||
override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
}
|
||||
|
||||
private class SingletonMethodRange extends CallableRange, @singleton_method {
|
||||
final override Generated::SingletonMethod generated;
|
||||
|
||||
override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
}
|
||||
|
||||
private class LambdaRange extends CallableRange, @lambda {
|
||||
final override Generated::Lambda generated;
|
||||
|
||||
final override Parameter getParameter(int n) { result = generated.getParameters().getChild(n) }
|
||||
}
|
||||
|
||||
abstract class BlockRange extends CallableRange {
|
||||
Generated::BlockParameters params;
|
||||
|
||||
final override Parameter getParameter(int n) { result = params.getChild(n) }
|
||||
}
|
||||
|
||||
private class DoBlockRange extends BlockRange, @do_block {
|
||||
final override Generated::DoBlock generated;
|
||||
|
||||
DoBlockRange() { params = generated.getParameters() }
|
||||
}
|
||||
|
||||
private class BraceBlockRange extends BlockRange, @block {
|
||||
final override Generated::Block generated;
|
||||
|
||||
BraceBlockRange() { params = generated.getParameters() }
|
||||
}
|
||||
65
ql/src/codeql_ruby/ast/internal/Pattern.qll
Normal file
65
ql/src/codeql_ruby/ast/internal/Pattern.qll
Normal file
@@ -0,0 +1,65 @@
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
private import codeql.Locations
|
||||
|
||||
private predicate tuplePatternNode(Generated::AstNode n, boolean parameter) {
|
||||
n instanceof Generated::DestructuredParameter and
|
||||
parameter = true
|
||||
or
|
||||
n instanceof Generated::DestructuredLeftAssignment and
|
||||
parameter = false
|
||||
or
|
||||
n instanceof Generated::LeftAssignmentList and
|
||||
parameter = false
|
||||
or
|
||||
tuplePatternNode(n.getParent(), parameter)
|
||||
}
|
||||
|
||||
private predicate patternNode(Generated::AstNode n, boolean parameter) {
|
||||
tuplePatternNode(n, parameter)
|
||||
or
|
||||
parameter = true and
|
||||
n = any(Callable c).getAParameter()
|
||||
or
|
||||
parameter = false and
|
||||
n in [
|
||||
any(Generated::Assignment assign).getLeft(),
|
||||
any(Generated::OperatorAssignment assign).getLeft()
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a variable is assigned at `i`. `parameter` indicates whether it is
|
||||
* an implicit parameter assignment.
|
||||
*/
|
||||
predicate assignment(Generated::Identifier i, boolean parameter) { patternNode(i, parameter) }
|
||||
|
||||
abstract class PatternRange extends AstNode {
|
||||
PatternRange() { patternNode(this, _) }
|
||||
}
|
||||
|
||||
private class VariablePatternRange extends PatternRange {
|
||||
override Generated::Identifier generated;
|
||||
}
|
||||
|
||||
abstract class TuplePatternRange extends PatternRange {
|
||||
abstract Pattern getElement(int i);
|
||||
}
|
||||
|
||||
private class ParameterTuplePatternRange extends TuplePatternRange {
|
||||
override Generated::DestructuredParameter generated;
|
||||
|
||||
override Pattern getElement(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
|
||||
private class AssignmentTuplePatternRange extends TuplePatternRange {
|
||||
override Generated::DestructuredLeftAssignment generated;
|
||||
|
||||
override Pattern getElement(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
|
||||
private class AssignmentListPatternRange extends TuplePatternRange {
|
||||
override Generated::LeftAssignmentList generated;
|
||||
|
||||
override Pattern getElement(int i) { result = generated.getChild(i) }
|
||||
}
|
||||
130
ql/src/codeql_ruby/ast/internal/Variable.qll
Normal file
130
ql/src/codeql_ruby/ast/internal/Variable.qll
Normal file
@@ -0,0 +1,130 @@
|
||||
import codeql_ruby.AST
|
||||
private import codeql_ruby.Generated
|
||||
private import codeql.Locations
|
||||
private import Pattern
|
||||
|
||||
private Generated::AstNode parent(Generated::AstNode n) {
|
||||
result = n.getParent() and
|
||||
not n = any(VariableScope s).getScopeElement()
|
||||
}
|
||||
|
||||
/** Gets the enclosing scope for `node`. */
|
||||
private VariableScope enclosingScope(Generated::AstNode node) {
|
||||
result.getScopeElement() = parent*(node.getParent())
|
||||
}
|
||||
|
||||
/** Holds if `scope` defines `name` in its parameter declaration at `i`. */
|
||||
private predicate scopeDefinesParameterVariable(
|
||||
CallableScope scope, string name, Generated::Identifier i
|
||||
) {
|
||||
assignment(i, true) and
|
||||
scope = enclosingScope(i) and
|
||||
name = i.getValue()
|
||||
or
|
||||
exists(Parameter p |
|
||||
p = scope.getScopeElement().getAParameter() and
|
||||
name = p.(NamedParameter).getName()
|
||||
|
|
||||
i = p.(Generated::BlockParameter).getName() or
|
||||
i = p.(Generated::HashSplatParameter).getName() or
|
||||
i = p.(Generated::KeywordParameter).getName() or
|
||||
i = p.(Generated::OptionalParameter).getName() or
|
||||
i = p.(Generated::SplatParameter).getName()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `name` is assigned in `scope` at `i`. */
|
||||
private predicate scopeAssigns(VariableScope scope, string name, Generated::Identifier i) {
|
||||
assignment(i, false) and
|
||||
name = i.getValue() and
|
||||
scope = enclosingScope(i)
|
||||
}
|
||||
|
||||
/** Holds if location `one` starts strictly before location `two` */
|
||||
pragma[inline]
|
||||
private predicate strictlyBefore(Location one, Location two) {
|
||||
one.getStartLine() < two.getStartLine()
|
||||
or
|
||||
one.getStartLine() = two.getStartLine() and one.getStartColumn() < two.getStartColumn()
|
||||
}
|
||||
|
||||
/** A scope that may capture outer local variables. */
|
||||
private class CapturingScope extends CallableScope {
|
||||
CapturingScope() {
|
||||
exists(Callable c | c = this.getScopeElement() |
|
||||
c instanceof Block
|
||||
or
|
||||
c instanceof DoBlock
|
||||
or
|
||||
c instanceof Lambda // TODO: Check if this is actually the case
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the scope in which this scope is nested, if any. */
|
||||
private VariableScope getOuterScope() { result = enclosingScope(this.getScopeElement()) }
|
||||
|
||||
/** Holds if this scope inherits `name` from an outer scope `outer`. */
|
||||
predicate inherits(string name, VariableScope outer) {
|
||||
not scopeDefinesParameterVariable(this, name, _) and
|
||||
(
|
||||
outer = this.getOuterScope() and
|
||||
(
|
||||
scopeDefinesParameterVariable(outer, name, _)
|
||||
or
|
||||
exists(Generated::Identifier i |
|
||||
scopeAssigns(outer, name, i) and
|
||||
strictlyBefore(i.getLocation(), this.getLocation())
|
||||
)
|
||||
)
|
||||
or
|
||||
this.getOuterScope().(CapturingScope).inherits(name, outer)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
newtype TScope =
|
||||
TTopLevelScope(Generated::Program node) or
|
||||
TModuleScope(Generated::Module node) or
|
||||
TClassScope(AstNode cls) {
|
||||
cls instanceof Generated::Class or cls instanceof Generated::SingletonClass
|
||||
} or
|
||||
TCallableScope(Callable c)
|
||||
|
||||
cached
|
||||
newtype TVariable =
|
||||
TLocalVariable(VariableScope scope, string name, Generated::Identifier i) {
|
||||
scopeDefinesParameterVariable(scope, name, i)
|
||||
or
|
||||
scopeAssigns(scope, name, i) and
|
||||
i =
|
||||
min(Generated::Identifier other |
|
||||
scopeAssigns(scope, name, other)
|
||||
|
|
||||
other order by other.getLocation().getStartLine(), other.getLocation().getStartColumn()
|
||||
) and
|
||||
not scopeDefinesParameterVariable(scope, name, _) and
|
||||
not scope.(CapturingScope).inherits(name, _)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate access(Generated::Identifier access, Variable variable) {
|
||||
exists(string name |
|
||||
name = access.getValue() and
|
||||
// Do not generate an access at the defining location
|
||||
not variable = TLocalVariable(_, name, access)
|
||||
|
|
||||
variable = enclosingScope(access).getVariable(name) and
|
||||
not strictlyBefore(access.getLocation(), variable.getLocation())
|
||||
or
|
||||
exists(VariableScope declScope |
|
||||
variable = declScope.getVariable(name) and
|
||||
enclosingScope(access).(CapturingScope).inherits(name, declScope)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
@@ -6,23 +6,33 @@ idParams
|
||||
| params.rb:9:20:9:24 | value | value |
|
||||
| params.rb:14:11:14:13 | foo | foo |
|
||||
| params.rb:14:16:14:18 | bar | bar |
|
||||
| params.rb:17:32:17:32 | a | a |
|
||||
| params.rb:17:35:17:35 | b | b |
|
||||
| params.rb:17:38:17:38 | c | c |
|
||||
| params.rb:22:16:22:16 | a | a |
|
||||
| params.rb:22:19:22:19 | b | b |
|
||||
| params.rb:25:24:25:28 | first | first |
|
||||
| params.rb:25:31:25:36 | second | second |
|
||||
| params.rb:25:41:25:45 | third | third |
|
||||
| params.rb:25:48:25:53 | fourth | fourth |
|
||||
| params.rb:30:23:30:28 | wibble | wibble |
|
||||
| params.rb:30:31:30:36 | splat | splat |
|
||||
| params.rb:30:39:30:52 | **double_splat | double_splat |
|
||||
| params.rb:34:16:34:18 | val | val |
|
||||
| params.rb:34:21:34:26 | splat | splat |
|
||||
| params.rb:34:29:34:42 | **double_splat | double_splat |
|
||||
| params.rb:38:26:38:26 | x | x |
|
||||
| params.rb:38:29:38:33 | blah | blah |
|
||||
| params.rb:38:36:38:43 | **wibble | wibble |
|
||||
| params.rb:41:32:41:32 | x | x |
|
||||
| params.rb:41:35:41:38 | foo | foo |
|
||||
| params.rb:41:41:41:46 | bar | bar |
|
||||
| params.rb:46:28:46:33 | &block | block |
|
||||
| params.rb:49:28:49:30 | xx | xx |
|
||||
| params.rb:49:33:49:39 | yy | yy |
|
||||
| params.rb:53:34:53:34 | x | x |
|
||||
| params.rb:53:37:53:38 | y | y |
|
||||
| params.rb:53:41:53:44 | z | z |
|
||||
| params.rb:58:33:58:36 | val1 | val1 |
|
||||
| params.rb:58:39:58:46 | val2 | val2 |
|
||||
| params.rb:58:49:58:58 | val3 | val3 |
|
||||
| params.rb:62:29:62:34 | &block | block |
|
||||
| params.rb:65:29:65:32 | name | name |
|
||||
| params.rb:65:35:65:42 | age | age |
|
||||
| params.rb:70:35:70:35 | a | a |
|
||||
| params.rb:70:38:70:45 | b | b |
|
||||
| params.rb:70:48:70:53 | c | c |
|
||||
blockParams
|
||||
| params.rb:46:28:46:33 | &block | block |
|
||||
| params.rb:62:29:62:34 | &block | block |
|
||||
@@ -58,82 +68,82 @@ optionalParams
|
||||
| params.rb:70:38:70:45 | b | b | params.rb:70:42:70:45 | AstNode |
|
||||
| params.rb:70:48:70:53 | c | c | params.rb:70:52:70:53 | AstNode |
|
||||
paramsInMethods
|
||||
| params.rb:4:1:5:3 | identifier_method_params | 0 | params.rb:4:30:4:32 | foo | IdentifierParameter |
|
||||
| params.rb:4:1:5:3 | identifier_method_params | 1 | params.rb:4:35:4:37 | bar | IdentifierParameter |
|
||||
| params.rb:4:1:5:3 | identifier_method_params | 2 | params.rb:4:40:4:42 | baz | IdentifierParameter |
|
||||
| params.rb:17:1:18:3 | destructured_method_param | 0 | params.rb:17:31:17:39 | (..., ...) | PatternParameter |
|
||||
| params.rb:30:1:31:3 | method_with_splat | 0 | params.rb:30:23:30:28 | wibble | IdentifierParameter |
|
||||
| params.rb:4:1:5:3 | identifier_method_params | 0 | params.rb:4:30:4:32 | foo | SimpleParameter |
|
||||
| params.rb:4:1:5:3 | identifier_method_params | 1 | params.rb:4:35:4:37 | bar | SimpleParameter |
|
||||
| params.rb:4:1:5:3 | identifier_method_params | 2 | params.rb:4:40:4:42 | baz | SimpleParameter |
|
||||
| params.rb:17:1:18:3 | destructured_method_param | 0 | params.rb:17:31:17:39 | (..., ...) | TuplePatternParameter |
|
||||
| params.rb:30:1:31:3 | method_with_splat | 0 | params.rb:30:23:30:28 | wibble | SimpleParameter |
|
||||
| params.rb:30:1:31:3 | method_with_splat | 1 | params.rb:30:31:30:36 | splat | SplatParameter |
|
||||
| params.rb:30:1:31:3 | method_with_splat | 2 | params.rb:30:39:30:52 | **double_splat | HashSplatParameter |
|
||||
| params.rb:41:1:43:3 | method_with_keyword_params | 0 | params.rb:41:32:41:32 | x | IdentifierParameter |
|
||||
| params.rb:41:1:43:3 | method_with_keyword_params | 0 | params.rb:41:32:41:32 | x | SimpleParameter |
|
||||
| params.rb:41:1:43:3 | method_with_keyword_params | 1 | params.rb:41:35:41:38 | foo | KeywordParameter |
|
||||
| params.rb:41:1:43:3 | method_with_keyword_params | 2 | params.rb:41:41:41:46 | bar | KeywordParameter |
|
||||
| params.rb:46:1:48:3 | use_block_with_keyword | 0 | params.rb:46:28:46:33 | &block | BlockParameter |
|
||||
| params.rb:58:1:59:3 | method_with_optional_params | 0 | params.rb:58:33:58:36 | val1 | IdentifierParameter |
|
||||
| params.rb:58:1:59:3 | method_with_optional_params | 0 | params.rb:58:33:58:36 | val1 | SimpleParameter |
|
||||
| params.rb:58:1:59:3 | method_with_optional_params | 1 | params.rb:58:39:58:46 | val2 | OptionalParameter |
|
||||
| params.rb:58:1:59:3 | method_with_optional_params | 2 | params.rb:58:49:58:58 | val3 | OptionalParameter |
|
||||
| params.rb:62:1:64:3 | use_block_with_optional | 0 | params.rb:62:29:62:34 | &block | BlockParameter |
|
||||
paramsInBlocks
|
||||
| params.rb:9:11:11:3 | \| ... \| | 0 | params.rb:9:15:9:17 | key | IdentifierParameter |
|
||||
| params.rb:9:11:11:3 | \| ... \| | 1 | params.rb:9:20:9:24 | value | IdentifierParameter |
|
||||
| params.rb:22:12:22:32 | { ... } | 0 | params.rb:22:15:22:20 | (..., ...) | PatternParameter |
|
||||
| params.rb:34:12:35:3 | \| ... \| | 0 | params.rb:34:16:34:18 | val | IdentifierParameter |
|
||||
| params.rb:9:11:11:3 | \| ... \| | 0 | params.rb:9:15:9:17 | key | SimpleParameter |
|
||||
| params.rb:9:11:11:3 | \| ... \| | 1 | params.rb:9:20:9:24 | value | SimpleParameter |
|
||||
| params.rb:22:12:22:32 | { ... } | 0 | params.rb:22:15:22:20 | (..., ...) | TuplePatternParameter |
|
||||
| params.rb:34:12:35:3 | \| ... \| | 0 | params.rb:34:16:34:18 | val | SimpleParameter |
|
||||
| params.rb:34:12:35:3 | \| ... \| | 1 | params.rb:34:21:34:26 | splat | SplatParameter |
|
||||
| params.rb:34:12:35:3 | \| ... \| | 2 | params.rb:34:29:34:42 | **double_splat | HashSplatParameter |
|
||||
| params.rb:49:24:51:3 | \| ... \| | 0 | params.rb:49:28:49:30 | xx | KeywordParameter |
|
||||
| params.rb:49:24:51:3 | \| ... \| | 1 | params.rb:49:33:49:39 | yy | KeywordParameter |
|
||||
| params.rb:65:25:67:3 | \| ... \| | 0 | params.rb:65:29:65:32 | name | IdentifierParameter |
|
||||
| params.rb:65:25:67:3 | \| ... \| | 0 | params.rb:65:29:65:32 | name | SimpleParameter |
|
||||
| params.rb:65:25:67:3 | \| ... \| | 1 | params.rb:65:35:65:42 | age | OptionalParameter |
|
||||
paramsInLambdas
|
||||
| params.rb:14:7:14:33 | -> { ... } | 0 | params.rb:14:11:14:13 | foo | IdentifierParameter |
|
||||
| params.rb:14:7:14:33 | -> { ... } | 1 | params.rb:14:16:14:18 | bar | IdentifierParameter |
|
||||
| params.rb:25:19:27:1 | -> { ... } | 0 | params.rb:25:23:25:37 | (..., ...) | PatternParameter |
|
||||
| params.rb:25:19:27:1 | -> { ... } | 1 | params.rb:25:40:25:54 | (..., ...) | PatternParameter |
|
||||
| params.rb:38:22:38:47 | -> { ... } | 0 | params.rb:38:26:38:26 | x | IdentifierParameter |
|
||||
| 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 |
|
||||
| params.rb:25:19:27:1 | -> { ... } | 0 | params.rb:25:23:25:37 | (..., ...) | TuplePatternParameter |
|
||||
| params.rb:25:19:27:1 | -> { ... } | 1 | params.rb:25:40:25:54 | (..., ...) | TuplePatternParameter |
|
||||
| params.rb:38:22:38:47 | -> { ... } | 0 | params.rb:38:26:38:26 | x | SimpleParameter |
|
||||
| params.rb:38:22:38:47 | -> { ... } | 1 | params.rb:38:29:38:33 | blah | SplatParameter |
|
||||
| params.rb:38:22:38:47 | -> { ... } | 2 | params.rb:38:36:38:43 | **wibble | HashSplatParameter |
|
||||
| params.rb:53:30:55:1 | -> { ... } | 0 | params.rb:53:34:53:34 | x | IdentifierParameter |
|
||||
| params.rb:53:30:55:1 | -> { ... } | 0 | params.rb:53:34:53:34 | x | SimpleParameter |
|
||||
| params.rb:53:30:55:1 | -> { ... } | 1 | params.rb:53:37:53:38 | y | KeywordParameter |
|
||||
| params.rb:53:30:55:1 | -> { ... } | 2 | params.rb:53:41:53:44 | z | KeywordParameter |
|
||||
| params.rb:70:31:70:64 | -> { ... } | 0 | params.rb:70:35:70:35 | a | IdentifierParameter |
|
||||
| params.rb:70:31:70:64 | -> { ... } | 0 | params.rb:70:35:70:35 | a | SimpleParameter |
|
||||
| params.rb:70:31:70:64 | -> { ... } | 1 | params.rb:70:38:70:45 | b | OptionalParameter |
|
||||
| params.rb:70:31:70:64 | -> { ... } | 2 | params.rb:70:48:70:53 | c | OptionalParameter |
|
||||
#select
|
||||
| params.rb:4:30:4:32 | foo | 0 | IdentifierParameter |
|
||||
| params.rb:4:35:4:37 | bar | 1 | IdentifierParameter |
|
||||
| params.rb:4:40:4:42 | baz | 2 | IdentifierParameter |
|
||||
| params.rb:9:15:9:17 | key | 0 | IdentifierParameter |
|
||||
| params.rb:9:20:9:24 | value | 1 | IdentifierParameter |
|
||||
| params.rb:14:11:14:13 | foo | 0 | IdentifierParameter |
|
||||
| params.rb:14:16:14:18 | bar | 1 | IdentifierParameter |
|
||||
| params.rb:17:31:17:39 | (..., ...) | 0 | PatternParameter |
|
||||
| params.rb:22:15:22:20 | (..., ...) | 0 | PatternParameter |
|
||||
| params.rb:25:23:25:37 | (..., ...) | 0 | PatternParameter |
|
||||
| params.rb:25:40:25:54 | (..., ...) | 1 | PatternParameter |
|
||||
| params.rb:30:23:30:28 | wibble | 0 | IdentifierParameter |
|
||||
| params.rb:4:30:4:32 | foo | 0 | SimpleParameter |
|
||||
| params.rb:4:35:4:37 | bar | 1 | SimpleParameter |
|
||||
| params.rb:4:40:4:42 | baz | 2 | SimpleParameter |
|
||||
| params.rb:9:15:9:17 | key | 0 | SimpleParameter |
|
||||
| params.rb:9:20:9:24 | value | 1 | SimpleParameter |
|
||||
| params.rb:14:11:14:13 | foo | 0 | SimpleParameter |
|
||||
| params.rb:14:16:14:18 | bar | 1 | SimpleParameter |
|
||||
| params.rb:17:31:17:39 | (..., ...) | 0 | TuplePatternParameter |
|
||||
| params.rb:22:15:22:20 | (..., ...) | 0 | TuplePatternParameter |
|
||||
| params.rb:25:23:25:37 | (..., ...) | 0 | TuplePatternParameter |
|
||||
| params.rb:25:40:25:54 | (..., ...) | 1 | TuplePatternParameter |
|
||||
| params.rb:30:23:30:28 | wibble | 0 | SimpleParameter |
|
||||
| params.rb:30:31:30:36 | splat | 1 | SplatParameter |
|
||||
| params.rb:30:39:30:52 | **double_splat | 2 | HashSplatParameter |
|
||||
| params.rb:34:16:34:18 | val | 0 | IdentifierParameter |
|
||||
| params.rb:34:16:34:18 | val | 0 | SimpleParameter |
|
||||
| params.rb:34:21:34:26 | splat | 1 | SplatParameter |
|
||||
| params.rb:34:29:34:42 | **double_splat | 2 | HashSplatParameter |
|
||||
| params.rb:38:26:38:26 | x | 0 | IdentifierParameter |
|
||||
| params.rb:38:26:38:26 | x | 0 | SimpleParameter |
|
||||
| params.rb:38:29:38:33 | blah | 1 | SplatParameter |
|
||||
| params.rb:38:36:38:43 | **wibble | 2 | HashSplatParameter |
|
||||
| params.rb:41:32:41:32 | x | 0 | IdentifierParameter |
|
||||
| params.rb:41:32:41:32 | x | 0 | SimpleParameter |
|
||||
| params.rb:41:35:41:38 | foo | 1 | KeywordParameter |
|
||||
| params.rb:41:41:41:46 | bar | 2 | KeywordParameter |
|
||||
| params.rb:46:28:46:33 | &block | 0 | BlockParameter |
|
||||
| params.rb:49:28:49:30 | xx | 0 | KeywordParameter |
|
||||
| params.rb:49:33:49:39 | yy | 1 | KeywordParameter |
|
||||
| params.rb:53:34:53:34 | x | 0 | IdentifierParameter |
|
||||
| params.rb:53:34:53:34 | x | 0 | SimpleParameter |
|
||||
| params.rb:53:37:53:38 | y | 1 | KeywordParameter |
|
||||
| params.rb:53:41:53:44 | z | 2 | KeywordParameter |
|
||||
| params.rb:58:33:58:36 | val1 | 0 | IdentifierParameter |
|
||||
| params.rb:58:33:58:36 | val1 | 0 | SimpleParameter |
|
||||
| params.rb:58:39:58:46 | val2 | 1 | OptionalParameter |
|
||||
| params.rb:58:49:58:58 | val3 | 2 | OptionalParameter |
|
||||
| params.rb:62:29:62:34 | &block | 0 | BlockParameter |
|
||||
| params.rb:65:29:65:32 | name | 0 | IdentifierParameter |
|
||||
| params.rb:65:29:65:32 | name | 0 | SimpleParameter |
|
||||
| params.rb:65:35:65:42 | age | 1 | OptionalParameter |
|
||||
| params.rb:70:35:70:35 | a | 0 | IdentifierParameter |
|
||||
| params.rb:70:35:70:35 | a | 0 | SimpleParameter |
|
||||
| params.rb:70:38:70:45 | b | 1 | OptionalParameter |
|
||||
| params.rb:70:48:70:53 | c | 2 | OptionalParameter |
|
||||
|
||||
@@ -2,12 +2,12 @@ import ruby
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Query predicates for various types of parameter
|
||||
query predicate idParams(IdentifierParameter ip, string name) { name = ip.getName() }
|
||||
query predicate idParams(NamedParameter np, string name) { name = np.getName() }
|
||||
|
||||
query predicate blockParams(BlockParameter bp, string name) { name = bp.getName() }
|
||||
|
||||
query predicate patternParams(PatternParameter pp, Parameter child, int childIndex) {
|
||||
pp.getElement(childIndex) = child
|
||||
query predicate patternParams(TuplePatternParameter tpp, Pattern child, int childIndex) {
|
||||
tpp.getElement(childIndex) = child
|
||||
}
|
||||
|
||||
query predicate splatParams(SplatParameter sp, string name) { name = sp.getName() }
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
parameter
|
||||
| nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a |
|
||||
| nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:26:16:26 | x |
|
||||
| nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:29:16:29 | a |
|
||||
| nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:26:18:26 | x |
|
||||
| nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a |
|
||||
| parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x |
|
||||
| parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client |
|
||||
| parameters.rb:7:25:7:31 | SplatParameter | parameters.rb:7:26:7:31 | pizzas |
|
||||
| parameters.rb:15:15:15:19 | HashSplatParameter | parameters.rb:15:17:15:19 | map |
|
||||
| parameters.rb:7:25:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas |
|
||||
| parameters.rb:15:15:15:19 | **map | parameters.rb:15:17:15:19 | map |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value |
|
||||
| parameters.rb:21:16:21:21 | BlockParameter | parameters.rb:21:17:21:21 | block |
|
||||
| parameters.rb:25:15:25:30 | OptionalParameter | parameters.rb:25:15:25:18 | name |
|
||||
| parameters.rb:25:33:25:50 | OptionalParameter | parameters.rb:25:33:25:36 | size |
|
||||
| parameters.rb:30:15:30:20 | KeywordParameter | parameters.rb:30:15:30:19 | first |
|
||||
| parameters.rb:30:24:30:33 | KeywordParameter | parameters.rb:30:24:30:29 | middle |
|
||||
| parameters.rb:30:36:30:40 | KeywordParameter | parameters.rb:30:36:30:39 | last |
|
||||
| parameters.rb:35:11:35:21 | OptionalParameter | parameters.rb:35:11:35:11 | a |
|
||||
| parameters.rb:40:12:40:19 | KeywordParameter | parameters.rb:40:12:40:12 | d |
|
||||
| parameters.rb:21:16:21:21 | &block | parameters.rb:21:17:21:21 | block |
|
||||
| parameters.rb:25:15:25:30 | name | parameters.rb:25:15:25:18 | name |
|
||||
| parameters.rb:25:33:25:50 | size | parameters.rb:25:33:25:36 | size |
|
||||
| parameters.rb:30:15:30:20 | first | parameters.rb:30:15:30:19 | first |
|
||||
| parameters.rb:30:24:30:33 | middle | parameters.rb:30:24:30:29 | middle |
|
||||
| parameters.rb:30:36:30:40 | last | parameters.rb:30:36:30:39 | last |
|
||||
| parameters.rb:35:11:35:21 | a | parameters.rb:35:11:35:11 | a |
|
||||
| parameters.rb:40:12:40:19 | d | parameters.rb:40:12:40:12 | d |
|
||||
| parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ |
|
||||
| parameters.rb:49:12:49:16 | DestructuredParameter | parameters.rb:49:13:49:13 | a |
|
||||
| parameters.rb:49:12:49:16 | DestructuredParameter | parameters.rb:49:15:49:15 | b |
|
||||
| parameters.rb:54:14:54:24 | OptionalParameter | parameters.rb:54:14:54:14 | y |
|
||||
| scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x |
|
||||
| scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x |
|
||||
| parameters.rb:45:20:45:20 | _ | parameters.rb:45:22:45:22 | _ |
|
||||
| parameters.rb:45:22:45:22 | _ | parameters.rb:45:20:45:20 | _ |
|
||||
| parameters.rb:45:22:45:22 | _ | parameters.rb:45:22:45:22 | _ |
|
||||
| parameters.rb:54:14:54:24 | y | parameters.rb:54:14:54:14 | y |
|
||||
parameterNoAcess
|
||||
| parameters.rb:45:22:45:22 | _ |
|
||||
| nested_scopes.rb:16:26:16:26 | x |
|
||||
| nested_scopes.rb:18:26:18:26 | x |
|
||||
| scopes.rb:2:14:2:14 | x |
|
||||
| scopes.rb:9:14:9:14 | x |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import codeql_ruby.ast.Variable
|
||||
|
||||
query predicate parameter(Parameter p, Variable v) { p.getAnAccess().getVariable() = v }
|
||||
query predicate parameter(NamedParameter p, Variable v) { p.getAnAccess().getVariable() = v }
|
||||
|
||||
query predicate parameterNoAcess(Parameter p) { not exists(p.getAnAccess()) }
|
||||
query predicate parameterNoAcess(NamedParameter p) { not exists(p.getAnAccess()) }
|
||||
|
||||
@@ -10,4 +10,9 @@ puts a
|
||||
puts a # local variable from top-level
|
||||
a = 3
|
||||
puts a # local variable from top-level
|
||||
a, b, (c, d) = [4, 5, [6, 7]]
|
||||
puts a # local variable from top-level
|
||||
puts b # new local variable
|
||||
puts c # new local variable
|
||||
puts d # new local variable
|
||||
end
|
||||
@@ -1,173 +1,52 @@
|
||||
variableAccess
|
||||
| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope |
|
||||
| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope |
|
||||
| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope |
|
||||
| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope |
|
||||
| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope |
|
||||
| nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope |
|
||||
| nested_scopes.rb:15:11:15:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope |
|
||||
| nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope |
|
||||
| nested_scopes.rb:16:13:16:13 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope |
|
||||
| nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:18:15:18:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:23:18:36 | block scope |
|
||||
| nested_scopes.rb:18:34:18:34 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope |
|
||||
| nested_scopes.rb:23:16:23:16 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope |
|
||||
| nested_scopes.rb:25:14:25:14 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope |
|
||||
| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope |
|
||||
| nested_scopes.rb:32:16:32:16 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope |
|
||||
| nested_scopes.rb:34:12:34:12 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope |
|
||||
| nested_scopes.rb:36:10:36:10 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope |
|
||||
| nested_scopes.rb:38:8:38:8 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope |
|
||||
| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope |
|
||||
| nested_scopes.rb:41:1:41:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope |
|
||||
| parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:3:9:3:9 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:4:9:4:9 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:8:6:8:11 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:9:25:9:30 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:11:14:11:19 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:11:41:11:46 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope |
|
||||
| parameters.rb:16:3:16:5 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:17:13:17:15 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:17:22:17:26 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope |
|
||||
| parameters.rb:22:3:22:7 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:25:40:25:43 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:26:8:26:11 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:27:8:27:11 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:30:15:30:19 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:30:24:30:29 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:30:36:30:39 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:31:11:31:15 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:31:20:31:25 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:31:30:31:33 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:34:1:34:1 | b | parameters.rb:34:1:34:1 | b | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:35:11:35:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:37:11:37:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:37:16:37:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:40:12:40:12 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:42:11:42:11 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:42:16:42:16 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:45:22:45:22 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:46:8:46:8 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:46:8:46:8 | _ | parameters.rb:45:22:45:22 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:50:11:50:11 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:50:16:50:16 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope |
|
||||
| parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:55:9:55:9 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:56:9:56:9 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope |
|
||||
| scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x | scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:5:9:5:9 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:8:6:8:6 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x | scopes.rb:9:9:13:3 | block scope |
|
||||
| scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
parameterAccess
|
||||
| nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope |
|
||||
| nested_scopes.rb:16:13:16:13 | a | nested_scopes.rb:15:23:15:23 | a | nested_scopes.rb:15:19:20:13 | block scope |
|
||||
| nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:26:16:26 | x | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:17:15:17:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:18:15:18:15 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:26:18:26 | x | nested_scopes.rb:18:23:18:36 | block scope |
|
||||
| nested_scopes.rb:18:34:18:34 | a | nested_scopes.rb:16:29:16:29 | a | nested_scopes.rb:16:21:19:15 | block scope |
|
||||
| nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope |
|
||||
| nested_scopes.rb:23:16:23:16 | a | nested_scopes.rb:22:21:22:21 | a | nested_scopes.rb:22:9:24:11 | method scope |
|
||||
| parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:3:9:3:9 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:4:9:4:9 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | block scope |
|
||||
| parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:8:6:8:11 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:9:25:9:30 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:11:14:11:19 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:11:41:11:46 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | method scope |
|
||||
| parameters.rb:15:17:15:19 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope |
|
||||
| parameters.rb:16:3:16:5 | map | parameters.rb:15:17:15:19 | map | parameters.rb:15:1:19:3 | method scope |
|
||||
| parameters.rb:16:16:16:18 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:16:21:16:25 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:17:13:17:15 | key | parameters.rb:16:16:16:18 | key | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:17:22:17:26 | value | parameters.rb:16:21:16:25 | value | parameters.rb:16:12:18:5 | block scope |
|
||||
| parameters.rb:21:17:21:21 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope |
|
||||
| parameters.rb:22:3:22:7 | block | parameters.rb:21:17:21:21 | block | parameters.rb:21:1:23:3 | method scope |
|
||||
| parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:25:33:25:36 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:25:40:25:43 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:26:8:26:11 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:27:8:27:11 | size | parameters.rb:25:33:25:36 | size | parameters.rb:25:1:28:3 | method scope |
|
||||
| parameters.rb:30:15:30:19 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:30:24:30:29 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:30:36:30:39 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:31:11:31:15 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:31:20:31:25 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:31:30:31:33 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | method scope |
|
||||
| parameters.rb:35:11:35:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:37:11:37:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:40:12:40:12 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:42:11:42:11 | d | parameters.rb:40:12:40:12 | d | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:45:20:45:20 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:45:22:45:22 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:46:8:46:8 | _ | parameters.rb:45:20:45:20 | _ | parameters.rb:45:1:47:3 | method scope |
|
||||
| parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:50:11:50:11 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:50:16:50:16 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope |
|
||||
| parameters.rb:56:9:56:9 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | block scope |
|
||||
| scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x | scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:9:14:9:14 | x | scopes.rb:9:14:9:14 | x | scopes.rb:9:9:13:3 | block scope |
|
||||
localVariableAccess
|
||||
| nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope |
|
||||
| nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope |
|
||||
| nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope |
|
||||
| nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope |
|
||||
| nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope |
|
||||
| nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope |
|
||||
| nested_scopes.rb:15:11:15:11 | a | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:12:9:21:11 | method scope |
|
||||
| nested_scopes.rb:25:14:25:14 | a | nested_scopes.rb:11:9:11:9 | a | nested_scopes.rb:10:7:26:9 | class scope |
|
||||
| nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope |
|
||||
| nested_scopes.rb:32:16:32:16 | a | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:30:7:33:9 | class scope |
|
||||
| nested_scopes.rb:34:12:34:12 | a | nested_scopes.rb:9:7:9:7 | a | nested_scopes.rb:8:5:35:7 | module scope |
|
||||
| nested_scopes.rb:36:10:36:10 | a | nested_scopes.rb:7:5:7:5 | a | nested_scopes.rb:6:3:37:5 | module scope |
|
||||
| nested_scopes.rb:38:8:38:8 | a | nested_scopes.rb:5:3:5:3 | a | nested_scopes.rb:4:1:39:3 | class scope |
|
||||
| nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope |
|
||||
| nested_scopes.rb:41:1:41:1 | d | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:1:1:42:1 | top-level scope |
|
||||
| parameters.rb:34:1:34:1 | b | parameters.rb:34:1:34:1 | b | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:37:16:37:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | method scope |
|
||||
| parameters.rb:40:15:40:15 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:42:16:42:16 | e | parameters.rb:40:15:40:15 | e | parameters.rb:40:1:43:3 | method scope |
|
||||
| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| parameters.rb:55:9:55:9 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | top-level scope |
|
||||
| scopes.rb:4:4:4:4 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:5:9:5:9 | a | scopes.rb:4:4:4:4 | a | scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:7:1:7:1 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:8:6:8:6 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:8:6:8:6 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:10:9:10:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:11:4:11:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:12:9:12:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:13:4:13:4 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:14:9:14:9 | a | scopes.rb:7:1:7:1 | a | scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:15:9:15:9 | b | scopes.rb:13:7:13:7 | b | scopes.rb:9:9:18:3 | block scope |
|
||||
| scopes.rb:16:9:16:9 | c | scopes.rb:13:11:13:11 | c | scopes.rb:9:9:18:3 | block scope |
|
||||
| scopes.rb:17:9:17:9 | d | scopes.rb:13:14:13:14 | d | scopes.rb:9:9:18:3 | block scope |
|
||||
|
||||
@@ -4,16 +4,3 @@ query predicate variableAccess(VariableAccess access, Variable variable, Variabl
|
||||
variable = access.getVariable() and
|
||||
scope = variable.getDeclaringScope()
|
||||
}
|
||||
|
||||
query predicate parameterAccess(ParameterAccess access, LocalVariable variable, VariableScope scope) {
|
||||
variable = access.getVariable() and
|
||||
scope = variable.getDeclaringScope()
|
||||
}
|
||||
|
||||
query predicate localVariableAccess(
|
||||
VariableAccess access, LocalVariable variable, VariableScope scope
|
||||
) {
|
||||
not access instanceof ParameterAccess and
|
||||
variable = access.getVariable() and
|
||||
scope = variable.getDeclaringScope()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
variable
|
||||
| nested_scopes.rb:5:3:5:3 | a |
|
||||
| nested_scopes.rb:7:5:7:5 | a |
|
||||
| nested_scopes.rb:9:7:9:7 | a |
|
||||
@@ -30,6 +29,7 @@ variable
|
||||
| parameters.rb:40:12:40:12 | d |
|
||||
| parameters.rb:40:15:40:15 | e |
|
||||
| parameters.rb:45:20:45:20 | _ |
|
||||
| parameters.rb:45:22:45:22 | _ |
|
||||
| parameters.rb:49:13:49:13 | a |
|
||||
| parameters.rb:49:15:49:15 | b |
|
||||
| parameters.rb:53:1:53:1 | x |
|
||||
@@ -38,44 +38,6 @@ variable
|
||||
| scopes.rb:4:4:4:4 | a |
|
||||
| scopes.rb:7:1:7:1 | a |
|
||||
| scopes.rb:9:14:9:14 | x |
|
||||
parameter
|
||||
| nested_scopes.rb:15:23:15:23 | a |
|
||||
| nested_scopes.rb:16:26:16:26 | x |
|
||||
| nested_scopes.rb:16:29:16:29 | a |
|
||||
| nested_scopes.rb:18:26:18:26 | x |
|
||||
| nested_scopes.rb:22:21:22:21 | a |
|
||||
| parameters.rb:1:14:1:14 | x |
|
||||
| parameters.rb:1:18:1:18 | y |
|
||||
| parameters.rb:7:17:7:22 | client |
|
||||
| parameters.rb:7:26:7:31 | pizzas |
|
||||
| parameters.rb:15:17:15:19 | map |
|
||||
| parameters.rb:16:16:16:18 | key |
|
||||
| parameters.rb:16:21:16:25 | value |
|
||||
| parameters.rb:21:17:21:21 | block |
|
||||
| parameters.rb:25:15:25:18 | name |
|
||||
| parameters.rb:25:33:25:36 | size |
|
||||
| parameters.rb:30:15:30:19 | first |
|
||||
| parameters.rb:30:24:30:29 | middle |
|
||||
| parameters.rb:30:36:30:39 | last |
|
||||
| parameters.rb:35:11:35:11 | a |
|
||||
| parameters.rb:40:12:40:12 | d |
|
||||
| parameters.rb:45:20:45:20 | _ |
|
||||
| parameters.rb:49:13:49:13 | a |
|
||||
| parameters.rb:49:15:49:15 | b |
|
||||
| parameters.rb:54:14:54:14 | y |
|
||||
| scopes.rb:2:14:2:14 | x |
|
||||
| scopes.rb:9:14:9:14 | x |
|
||||
localVariable
|
||||
| nested_scopes.rb:5:3:5:3 | a |
|
||||
| nested_scopes.rb:7:5:7:5 | a |
|
||||
| nested_scopes.rb:9:7:9:7 | a |
|
||||
| nested_scopes.rb:11:9:11:9 | a |
|
||||
| nested_scopes.rb:13:11:13:11 | a |
|
||||
| nested_scopes.rb:31:11:31:11 | a |
|
||||
| nested_scopes.rb:40:1:40:1 | d |
|
||||
| parameters.rb:34:1:34:1 | b |
|
||||
| parameters.rb:35:16:35:16 | b |
|
||||
| parameters.rb:40:15:40:15 | e |
|
||||
| parameters.rb:53:1:53:1 | x |
|
||||
| scopes.rb:4:4:4:4 | a |
|
||||
| scopes.rb:7:1:7:1 | a |
|
||||
| scopes.rb:13:7:13:7 | b |
|
||||
| scopes.rb:13:11:13:11 | c |
|
||||
| scopes.rb:13:14:13:14 | d |
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import codeql_ruby.ast.Variable
|
||||
|
||||
query predicate variable(Variable v) { any() }
|
||||
|
||||
query predicate parameter(LocalVariable v) { v.getAnAccess() instanceof ParameterAccess }
|
||||
|
||||
query predicate localVariable(LocalVariable v) { not v.getAnAccess() instanceof ParameterAccess }
|
||||
|
||||
@@ -25,6 +25,6 @@
|
||||
| parameters.rb:49:1:51:3 | method scope |
|
||||
| parameters.rb:54:9:57:3 | block scope |
|
||||
| scopes.rb:1:1:1:15 | method scope |
|
||||
| scopes.rb:1:1:13:3 | top-level scope |
|
||||
| scopes.rb:1:1:18:3 | top-level scope |
|
||||
| scopes.rb:2:9:6:3 | block scope |
|
||||
| scopes.rb:9:9:13:3 | block scope |
|
||||
| scopes.rb:9:9:18:3 | block scope |
|
||||
|
||||
Reference in New Issue
Block a user