diff --git a/ruby/ql/lib/codeql/ruby/ast/Control.qll b/ruby/ql/lib/codeql/ruby/ast/Control.qll index 48c17f6b97b2..b4862724763a 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Control.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Control.qll @@ -102,7 +102,7 @@ class IfExpr extends ConditionalExpr, TIfExpr { cond = false and result = this.getElse() } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getThen" and result = this.getThen() @@ -192,8 +192,8 @@ class UnlessExpr extends ConditionalExpr, TUnlessExpr { final override string toString() { result = "unless ..." } - override AstNode getAChild(string pred) { - result = ConditionalExpr.super.getAChild(pred) + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) or pred = "getThen" and result = this.getThen() or @@ -229,8 +229,8 @@ class IfModifierExpr extends ConditionalExpr, TIfModifierExpr { final override string toString() { result = "... if ..." } - override AstNode getAChild(string pred) { - result = ConditionalExpr.super.getAChild(pred) + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) or pred = "getBody" and result = this.getBody() } @@ -264,8 +264,8 @@ class UnlessModifierExpr extends ConditionalExpr, TUnlessModifierExpr { final override string toString() { result = "... unless ..." } - override AstNode getAChild(string pred) { - result = ConditionalExpr.super.getAChild(pred) + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) or pred = "getBody" and result = this.getBody() } @@ -300,8 +300,8 @@ class TernaryIfExpr extends ConditionalExpr, TTernaryIfExpr { final override string toString() { result = "... ? ... : ..." } - override AstNode getAChild(string pred) { - result = ConditionalExpr.super.getAChild(pred) + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) or pred = "getThen" and result = this.getThen() or @@ -390,7 +390,7 @@ class CaseExpr extends ControlExpr instanceof CaseExprImpl { final override string toString() { result = "case ..." } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = ControlExpr.super.getAChild(pred) or pred = "getValue" and result = this.getValue() @@ -444,7 +444,7 @@ class WhenExpr extends Expr, TWhenExpr { final override string toString() { result = "when ..." } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getBody" and result = this.getBody() @@ -517,7 +517,7 @@ class InClause extends Expr, TInClause { final override string toString() { result = "in ... then ..." } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getBody" and result = this.getBody() @@ -552,7 +552,7 @@ class ConditionalLoop extends Loop, TConditionalLoop { Expr getCondition() { none() } override AstNode getAChild(string pred) { - result = Loop.super.getAChild(pred) + result = super.getAChild(pred) or pred = "getCondition" and result = this.getCondition() } @@ -692,7 +692,7 @@ class ForExpr extends Loop, TForExpr { final override StmtSequence getBody() { toGenerated(result) = g.getBody() } /** Gets the pattern representing the iteration argument. */ - final Pattern getPattern() { toGenerated(result) = g.getPattern() } + final LhsExpr getPattern() { toGenerated(result) = g.getPattern() } /** * Gets the value being iterated over. In the following example, the result @@ -707,8 +707,8 @@ class ForExpr extends Loop, TForExpr { final override string toString() { result = "for ... in ..." } - override AstNode getAChild(string pred) { - result = Loop.super.getAChild(pred) + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) or pred = "getPattern" and result = this.getPattern() or diff --git a/ruby/ql/lib/codeql/ruby/ast/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/Expr.qll index d76fdb7cc628..a0609567e294 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Expr.qll @@ -66,6 +66,87 @@ class ArgumentList extends Expr, TArgumentList { } } +private class LhsExpr_ = + TVariableAccess or TTokenConstantAccess or TScopeResolutionConstantAccess or TMethodCall or + TDestructuredLhsExpr; + +/** + * A "left-hand-side" (LHS) expression. An `LhsExpr` can occur on the left-hand side of + * operator assignments (`AssignOperation`), on the left-hand side of assignments + * (`AssignExpr`), as patterns in for loops (`ForExpr`), and as exception variables + * in `rescue` clauses (`RescueClause`). + * + * An `LhsExpr` can be a simple variable, a constant, a call, or an element reference: + * + * ```rb + * var = 1 + * var += 1 + * E = 1 + * foo.bar = 1 + * foo[0] = 1 + * rescue E => var + * ``` + */ +class LhsExpr extends Expr, LhsExpr_ { + LhsExpr() { lhsExpr(this) } + + /** Gets a variable used in (or introduced by) this LHS. */ + Variable getAVariable() { result = this.(VariableAccess).getVariable() } +} + +/** + * A "left-hand-side" (LHS) expression of a destructured assignment. + * + * Examples: + * ```rb + * a, self.b = value + * (a, b), c[3] = value + * a, b, *rest, c, d = value + * ``` + */ +class DestructuredLhsExpr extends LhsExpr, TDestructuredLhsExpr { + override string getAPrimaryQlClass() { result = "DestructuredLhsExpr" } + + private DestructuredLhsExprImpl getImpl() { result = toGenerated(this) } + + private Ruby::AstNode getChild(int i) { result = this.getImpl().getChildNode(i) } + + /** Gets the `i`th element in this destructured LHS. */ + final Expr getElement(int i) { + exists(Ruby::AstNode c | c = this.getChild(i) | + toGenerated(result) = c.(Ruby::RestAssignment).getChild() + or + toGenerated(result) = c + ) + } + + /** Gets an element in this destructured LHS. */ + final Expr getAnElement() { result = this.getElement(_) } + + /** + * Gets the index of the element with the `*` marker on it, if it exists. + * In the example below the index is `2`. + * ```rb + * a, b, *rest, c, d = value + * ``` + */ + final int getRestIndex() { result = this.getImpl().getRestIndex() } + + override Variable getAVariable() { + result = this.getElement(_).(VariableWriteAccess).getVariable() + or + result = this.getElement(_).(DestructuredLhsExpr).getAVariable() + } + + override string toString() { result = "(..., ...)" } + + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) + or + pred = "getElement" and result = this.getElement(_) + } +} + /** A sequence of expressions. */ class StmtSequence extends Expr, TStmtSequence { override string getAPrimaryQlClass() { result = "StmtSequence" } @@ -136,7 +217,7 @@ class BodyStmt extends StmtSequence, TBodyStmt { final predicate hasEnsure() { exists(this.getEnsure()) } override AstNode getAChild(string pred) { - result = StmtSequence.super.getAChild(pred) + result = super.getAChild(pred) or pred = "getRescue" and result = this.getRescue(_) or @@ -214,7 +295,7 @@ class Pair extends Expr, TPair { final override string toString() { result = "Pair" } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getKey" and result = this.getKey() @@ -283,7 +364,7 @@ class RescueClause extends Expr, TRescueClause { final override string toString() { result = "rescue ..." } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getException" and result = this.getException(_) @@ -325,7 +406,7 @@ class RescueModifierExpr extends Expr, TRescueModifierExpr { final override string toString() { result = "... rescue ..." } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getBody" and result = this.getBody() @@ -386,7 +467,7 @@ class StringConcatenation extends Expr, TStringConcatenation { final override string toString() { result = "\"...\" \"...\"" } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = super.getAChild(pred) or pred = "getString" and result = this.getString(_) diff --git a/ruby/ql/lib/codeql/ruby/ast/Operation.qll b/ruby/ql/lib/codeql/ruby/ast/Operation.qll index 6c30224b3b1b..d8ab49d770f6 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Operation.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Operation.qll @@ -443,14 +443,14 @@ class NoRegExpMatchExpr extends BinaryOperation, TNoRegExpMatchExpr { */ class Assignment extends Operation instanceof AssignmentImpl { /** Gets the left hand side of this assignment. */ - final Pattern getLeftOperand() { result = super.getLeftOperandImpl() } + final LhsExpr getLeftOperand() { result = super.getLeftOperandImpl() } /** Gets the right hand side of this assignment. */ final Expr getRightOperand() { result = super.getRightOperandImpl() } final override string toString() { result = "... " + this.getOperator() + " ..." } - override AstNode getAChild(string pred) { + final override AstNode getAChild(string pred) { result = Operation.super.getAChild(pred) or pred = "getLeftOperand" and result = this.getLeftOperand() diff --git a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll index 0f154588ac75..efbd8a66ce82 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Parameter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Parameter.qll @@ -7,7 +7,14 @@ private import internal.TreeSitter /** A parameter. */ class Parameter extends AstNode, TParameter { /** Gets the callable that this parameter belongs to. */ - final Callable getCallable() { result.getAParameter() = this } + final Callable getCallable() { + result.getAParameter() = this + or + exists(DestructuredParameter parent | + this = parent.getAnElement() and + result = parent.getCallable() + ) + } /** Gets the zero-based position of this parameter. */ final int getPosition() { this = any(Callable c).getParameter(result) } @@ -23,21 +30,63 @@ class Parameter extends AstNode, TParameter { } /** + * A parameter defined using destructuring. For example + * + * ```rb + * def tuples((a,b)) + * puts "#{a} #{b}" + * end + * ``` + */ +class DestructuredParameter extends Parameter, TDestructuredParameter { + private DestructuredParameterImpl getImpl() { result = toGenerated(this) } + + private Ruby::AstNode getChild(int i) { result = this.getImpl().getChildNode(i) } + + /** Gets the `i`th element in this destructured parameter. */ + final AstNode getElement(int i) { + exists(Ruby::AstNode c | c = this.getChild(i) | toGenerated(result) = c) + } + + /** Gets an element in this destructured parameter. */ + final AstNode getAnElement() { result = this.getElement(_) } + + override LocalVariable getAVariable() { + result = this.getAnElement().(LocalVariableWriteAccess).getVariable() + or + result = this.getAnElement().(DestructuredParameter).getAVariable() + } + + override string toString() { result = "(..., ...)" } + + final override AstNode getAChild(string pred) { + result = super.getAChild(pred) + or + pred = "getElement" and result = this.getElement(_) + } + + final override string getAPrimaryQlClass() { result = "DestructuredParameter" } +} + +/** + * DEPRECATED + * * A parameter defined using a pattern. * * This includes both simple parameters and tuple parameters. */ -class PatternParameter extends Parameter, Pattern, TPatternParameter { +deprecated class PatternParameter extends Parameter, Pattern, TPatternParameter { override LocalVariable getAVariable() { result = Pattern.super.getAVariable() } } -/** A parameter defined using a tuple pattern. */ -class TuplePatternParameter extends PatternParameter, TuplePattern, TTuplePatternParameter { +/** + * DEPRECATED + * + * A parameter defined using a tuple pattern. + */ +deprecated class TuplePatternParameter extends PatternParameter, TuplePattern, + TDestructuredParameter { final override LocalVariable getAVariable() { result = TuplePattern.super.getAVariable() } - - final override string getAPrimaryQlClass() { result = "TuplePatternParameter" } - - override AstNode getAChild(string pred) { result = TuplePattern.super.getAChild(pred) } } /** A named parameter. */ @@ -72,7 +121,7 @@ class NamedParameter extends Parameter, TNamedParameter { } /** A simple (normal) parameter. */ -class SimpleParameter extends NamedParameter, PatternParameter, VariablePattern, TSimpleParameter instanceof SimpleParameterImpl { +class SimpleParameter extends NamedParameter, TSimpleParameter instanceof SimpleParameterImpl { final override string getName() { result = SimpleParameterImpl.super.getNameImpl() } final override LocalVariable getVariable() { diff --git a/ruby/ql/lib/codeql/ruby/ast/Pattern.qll b/ruby/ql/lib/codeql/ruby/ast/Pattern.qll index aee78fb05cff..7630732aecdf 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Pattern.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Pattern.qll @@ -6,8 +6,12 @@ private import internal.TreeSitter private import internal.Variable private import internal.Parameter -/** A pattern. */ -class Pattern extends AstNode { +/** + * DEPRECATED + * + * A pattern. + */ +deprecated class Pattern extends AstNode { Pattern() { explicitAssignmentNode(toGenerated(this), _) or @@ -24,36 +28,20 @@ class Pattern extends AstNode { Variable getAVariable() { none() } } -private class LhsExpr_ = - TVariableAccess or TTokenConstantAccess or TScopeResolutionConstantAccess or TMethodCall or - TSimpleParameter; +deprecated private class TVariablePattern = TVariableAccess or TSimpleParameter; /** - * A "left-hand-side" expression. An `LhsExpr` can occur on the left-hand side of - * operator assignments (`AssignOperation`), in patterns (`Pattern`) on the left-hand side of - * an assignment (`AssignExpr`) or for loop (`ForExpr`), and as the exception - * variable of a `rescue` clause (`RescueClause`). + * DEPRECATED * - * An `LhsExpr` can be a simple variable, a constant, a call, or an element reference: - * ```rb - * var = 1 - * var += 1 - * E = 1 - * foo.bar = 1 - * foo[0] = 1 - * rescue E => var - * ``` + * A simple variable pattern. */ -class LhsExpr extends Pattern, LhsExpr_, Expr { +deprecated class VariablePattern extends Pattern, LhsExpr, TVariablePattern { override Variable getAVariable() { result = this.(VariableAccess).getVariable() } } -private class TVariablePattern = TVariableAccess or TSimpleParameter; - -/** A simple variable pattern. */ -class VariablePattern extends Pattern, LhsExpr, TVariablePattern { } - /** + * DEPRECATED + * * A tuple pattern. * * This includes both tuple patterns in parameters and assignments. Example patterns: @@ -63,9 +51,7 @@ class VariablePattern extends Pattern, LhsExpr, TVariablePattern { } * a, b, *rest, c, d = value * ``` */ -class TuplePattern extends Pattern, TTuplePattern { - override string getAPrimaryQlClass() { result = "TuplePattern" } - +deprecated class TuplePattern extends Pattern, TTuplePattern { private TuplePatternImpl getImpl() { result = toGenerated(this) } private Ruby::AstNode getChild(int i) { result = this.getImpl().getChildNode(i) } @@ -92,10 +78,6 @@ class TuplePattern extends Pattern, TTuplePattern { final int getRestIndex() { result = this.getImpl().getRestIndex() } override Variable getAVariable() { result = this.getElement(_).getAVariable() } - - override string toString() { result = "(..., ...)" } - - override AstNode getAChild(string pred) { pred = "getElement" and result = this.getElement(_) } } private class TPatternNode = diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll index 27e4621ddf94..b78eded2edaf 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll @@ -296,7 +296,7 @@ private module Cached { TTokenSuperCall(Ruby::Super g) { vcall(g) } or TToplevel(Ruby::Program g) or TTrueLiteral(Ruby::True g) or - TTuplePatternParameter(Ruby::DestructuredParameter g) or + TDestructuredParameter(Ruby::DestructuredParameter g) or TUnaryMinusExpr(Ruby::Unary g) { g instanceof @ruby_unary_minus } or TUnaryPlusExpr(Ruby::Unary g) { g instanceof @ruby_unary_plus } or TUndefStmt(Ruby::Undef g) or @@ -321,9 +321,9 @@ private module Cached { 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 - TEncoding or TEndBlock or TEnsure or TEqExpr or TExponentExprReal or TFalseLiteral or - TFile or TFindPattern or TFloatLiteral or TForExpr or TForwardParameter or + TDestructuredParameter or TDivExprReal or TDo or TDoBlock or TElementReference or TElse or + TElsif or TEmptyStmt 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 @@ -342,8 +342,8 @@ private module Cached { TStringConcatenation or TStringEscapeSequenceComponent or TStringInterpolationComponent or TStringTextComponent or TSubExprReal or TSubshellLiteral or TSymbolArrayLiteral or 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 + TToplevel or TTrueLiteral or TUnaryMinusExpr or TUnaryPlusExpr or TUndefStmt or + TUnlessExpr or TUnlessModifierExpr or TUntilExpr or TUntilModifierExpr or TVariableReferencePattern or TWhenExpr or TWhileExpr or TWhileModifierExpr or TYieldCall; class TAstNodeSynth = @@ -502,7 +502,7 @@ private module Cached { n = TTokenSuperCall(result) or n = TToplevel(result) or n = TTrueLiteral(result) or - n = TTuplePatternParameter(result) or + n = TDestructuredParameter(result) or n = TUnaryMinusExpr(result) or n = TUnaryPlusExpr(result) or n = TUndefStmt(result) or @@ -613,6 +613,15 @@ private module Cached { or result = toGenerated(n).getLocation() } + + cached + predicate lhsExpr(AST::Expr e) { + explicitAssignmentNode(toGenerated(e), _) + or + implicitAssignmentNode(toGenerated(e)) + or + e = getSynthChild(any(AST::AssignExpr ae), 0) + } } import Cached @@ -645,11 +654,13 @@ class TLoop = TConditionalLoop or TForExpr; class TSelf = TSelfReal or TSelfSynth; +class TDestructuredLhsExpr = TDestructuredLeftAssignment or TLeftAssignmentList; + class TExpr = 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; + TSimpleParameter or TForwardArgument or TDestructuredLhsExpr; class TSplatExpr = TSplatExprReal or TSplatExprSynth; @@ -778,18 +789,20 @@ class TStmt = class TReturningStmt = TReturnStmt or TBreakStmt or TNextStmt; class TParameter = - TPatternParameter or TBlockParameter or THashSplatParameter or THashSplatNilParameter or - TKeywordParameter or TOptionalParameter or TSplatParameter or TForwardParameter; + TSimpleParameter or TDestructuredParameter or TBlockParameter or THashSplatParameter or + THashSplatNilParameter or TKeywordParameter or TOptionalParameter or TSplatParameter or + TForwardParameter; class TSimpleParameter = TSimpleParameterReal or TSimpleParameterSynth; -class TPatternParameter = TSimpleParameter or TTuplePatternParameter; +deprecated class TPatternParameter = TSimpleParameter or TDestructuredParameter; class TNamedParameter = TSimpleParameter or TBlockParameter or THashSplatParameter or TKeywordParameter or TOptionalParameter or TSplatParameter; -class TTuplePattern = TTuplePatternParameter or TDestructuredLeftAssignment or TLeftAssignmentList; +deprecated class TTuplePattern = + TDestructuredParameter or TDestructuredLeftAssignment or TLeftAssignmentList; class TVariableAccess = TLocalVariableAccess or TGlobalVariableAccess or TInstanceVariableAccess or diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll index 4aa4dd4b79cf..167f5f90d1e6 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Expr.qll @@ -73,3 +73,29 @@ Ruby::AstNode getBodyStmtChild(TBodyStmt b, int i) { or result = any(Ruby::Begin g | b = TBeginExpr(g)).getChild(i) } + +abstract class DestructuredLhsExprImpl extends Ruby::AstNode { + abstract Ruby::AstNode getChildNode(int i); + + final int getRestIndex() { + result = unique(int i | this.getChildNode(i) instanceof Ruby::RestAssignment) + } +} + +class DestructuredLeftAssignmentImpl extends DestructuredLhsExprImpl, + Ruby::DestructuredLeftAssignment { + override Ruby::AstNode getChildNode(int i) { result = this.getChild(i) } +} + +class LeftAssignmentListImpl extends DestructuredLhsExprImpl, Ruby::LeftAssignmentList { + override Ruby::AstNode getChildNode(int i) { + this = + any(Ruby::LeftAssignmentList lal | + if + strictcount(int j | exists(lal.getChild(j))) = 1 and + lal.getChild(0) instanceof Ruby::DestructuredLeftAssignment + then result = lal.getChild(0).(Ruby::DestructuredLeftAssignment).getChild(i) + else result = lal.getChild(i) + ) + } +} diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll index 3571c97e9dc7..a63da1768cfa 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Operation.qll @@ -154,7 +154,7 @@ class BitwiseXorSynthExpr extends BinaryOperationSynth, TBitwiseXorExprSynth { } abstract class AssignmentImpl extends OperationImpl, TAssignment { - abstract Pattern getLeftOperandImpl(); + abstract Expr getLeftOperandImpl(); abstract Expr getRightOperandImpl(); @@ -172,7 +172,7 @@ class AssignExprReal extends AssignmentImpl, TAssignExprReal { final override string getOperatorImpl() { result = "=" } - final override Pattern getLeftOperandImpl() { toGenerated(result) = g.getLeft() } + final override Expr getLeftOperandImpl() { toGenerated(result) = g.getLeft() } final override Expr getRightOperandImpl() { toGenerated(result) = g.getRight() } } @@ -180,7 +180,7 @@ class AssignExprReal extends AssignmentImpl, TAssignExprReal { class AssignExprSynth extends AssignmentImpl, TAssignExprSynth { final override string getOperatorImpl() { result = "=" } - final override Pattern getLeftOperandImpl() { synthChild(this, 0, result) } + final override Expr getLeftOperandImpl() { synthChild(this, 0, result) } final override Expr getRightOperandImpl() { synthChild(this, 1, result) } } @@ -192,7 +192,7 @@ class AssignOperationImpl extends AssignmentImpl, TAssignOperation { final override string getOperatorImpl() { result = g.getOperator() } - final override Pattern getLeftOperandImpl() { toGenerated(result) = g.getLeft() } + final override Expr getLeftOperandImpl() { toGenerated(result) = g.getLeft() } final override Expr getRightOperandImpl() { toGenerated(result) = g.getRight() } } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll index b1312b4d1dfb..0a0a7ddb7086 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Parameter.qll @@ -44,3 +44,7 @@ class SimpleParameterSynthImpl extends SimpleParameterImpl, TSimpleParameterSynt override string getNameImpl() { result = this.getVariableImpl().getName() } } + +class DestructuredParameterImpl extends Ruby::DestructuredParameter { + Ruby::AstNode getChildNode(int i) { result = this.getChild(i) } +} diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll index 277aec6622fa..ab577a24eade 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Pattern.qll @@ -1,33 +1,25 @@ private import codeql.ruby.AST +private import codeql.ruby.ast.internal.Expr +private import codeql.ruby.ast.internal.Parameter private import AST private import TreeSitter -abstract class TuplePatternImpl extends Ruby::AstNode { - abstract Ruby::AstNode getChildNode(int i); - - final int getRestIndex() { - result = unique(int i | this.getChildNode(i) instanceof Ruby::RestAssignment) +deprecated class TuplePatternImpl extends Ruby::AstNode { + TuplePatternImpl() { + this instanceof DestructuredParameterImpl or + this instanceof DestructuredLhsExprImpl } -} - -class TuplePatternParameterImpl extends TuplePatternImpl, Ruby::DestructuredParameter { - override Ruby::AstNode getChildNode(int i) { result = this.getChild(i) } -} -class DestructuredLeftAssignmentImpl extends TuplePatternImpl, Ruby::DestructuredLeftAssignment { - override Ruby::AstNode getChildNode(int i) { result = this.getChild(i) } -} + Ruby::AstNode getChildNode(int i) { + result = + [ + this.(DestructuredParameterImpl).getChildNode(i), + this.(DestructuredLhsExprImpl).getChildNode(i) + ] + } -class LeftAssignmentListImpl extends TuplePatternImpl, Ruby::LeftAssignmentList { - override Ruby::AstNode getChildNode(int i) { - this = - any(Ruby::LeftAssignmentList lal | - if - strictcount(int j | exists(lal.getChild(j))) = 1 and - lal.getChild(0) instanceof Ruby::DestructuredLeftAssignment - then result = lal.getChild(0).(Ruby::DestructuredLeftAssignment).getChild(i) - else result = lal.getChild(i) - ) + final int getRestIndex() { + result = unique(int i | this.getChildNode(i) instanceof Ruby::RestAssignment) } } diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll index 83c0f9972157..060ff3bb5bc4 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Synthesis.qll @@ -636,36 +636,36 @@ private module AssignOperationDesugar { } } -private module CompoundAssignDesugar { - /** An assignment where the left-hand side is a tuple pattern. */ - private class TupleAssignExpr extends AssignExpr { - private TuplePattern tp; +private module DestructuredAssignDesugar { + /** A destructured assignment. */ + private class DestructuredAssignExpr extends AssignExpr { + private DestructuredLhsExpr lhs; pragma[nomagic] - TupleAssignExpr() { tp = this.getLeftOperand() } + DestructuredAssignExpr() { lhs = this.getLeftOperand() } - TuplePattern getTuplePattern() { result = tp } + DestructuredLhsExpr getLhs() { result = lhs } pragma[nomagic] - Pattern getElement(int i) { result = tp.getElement(i) } + Expr getElement(int i) { result = lhs.getElement(i) } pragma[nomagic] int getNumberOfElements() { - toGenerated(tp) = any(TuplePatternImpl impl | result = count(impl.getChildNode(_))) + toGenerated(lhs) = any(DestructuredLhsExprImpl impl | result = count(impl.getChildNode(_))) } pragma[nomagic] int getRestIndexOrNumberOfElements() { - result = tp.getRestIndex() + result = lhs.getRestIndex() or - toGenerated(tp) = any(TuplePatternImpl impl | not exists(impl.getRestIndex())) and + toGenerated(lhs) = any(DestructuredLhsExprImpl impl | not exists(impl.getRestIndex())) and result = this.getNumberOfElements() } } pragma[nomagic] - private predicate compoundAssignSynthesis(AstNode parent, int i, Child child) { - exists(TupleAssignExpr tae | + private predicate destructuredAssignSynthesis(AstNode parent, int i, Child child) { + exists(DestructuredAssignExpr tae | parent = tae and i = -1 and child = SynthChild(StmtSequenceKind()) @@ -689,8 +689,8 @@ private module CompoundAssignDesugar { child = childRef(tae.getRightOperand()) ) or - exists(Pattern p, int j, int restIndex | - p = tae.getElement(j) and + exists(AstNode elem, int j, int restIndex | + elem = tae.getElement(j) and restIndex = tae.getRestIndexOrNumberOfElements() | parent = seq and @@ -700,7 +700,7 @@ private module CompoundAssignDesugar { exists(AstNode assign | assign = TAssignExprSynth(seq, j + 1) | parent = assign and i = 0 and - child = childRef(p) + child = childRef(elem) or parent = assign and i = 1 and @@ -756,26 +756,26 @@ private module CompoundAssignDesugar { * z = __synth__0[-1]; * ``` */ - private class CompoundAssignSynthesis extends Synthesis { + private class DestructuredAssignSynthesis extends Synthesis { final override predicate child(AstNode parent, int i, Child child) { - compoundAssignSynthesis(parent, i, child) + destructuredAssignSynthesis(parent, i, child) } final override predicate location(AstNode n, Location l) { - exists(TupleAssignExpr tae, StmtSequence seq | seq = tae.getDesugared() | + exists(DestructuredAssignExpr tae, StmtSequence seq | seq = tae.getDesugared() | n = seq.getStmt(0) and hasLocation(tae.getRightOperand(), l) or - exists(Pattern p, int j | - p = tae.getElement(j) and + exists(AstNode elem, int j | + elem = tae.getElement(j) and n = seq.getStmt(j + 1) and - hasLocation(p, l) + hasLocation(elem, l) ) ) } final override predicate localVariable(AstNode n, int i) { - n instanceof TupleAssignExpr and + n instanceof DestructuredAssignExpr and i = 0 } @@ -784,10 +784,6 @@ private module CompoundAssignDesugar { setter = false and arity = 1 } - - final override predicate excludeFromControlFlowTree(AstNode n) { - n = any(TupleAssignExpr tae).getTuplePattern() - } } } @@ -820,7 +816,7 @@ private module ArrayLiteralDesugar { * ::Array.[](1, 2, 3) * ``` */ - private class CompoundAssignSynthesis extends Synthesis { + private class ArrayLiteralSynthesis extends Synthesis { final override predicate child(AstNode parent, int i, Child child) { arrayLiteralSynthesis(parent, i, child) } diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll index 1bc6c2676aba..43d1eee4bb01 100644 --- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll +++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll @@ -935,6 +935,10 @@ module Trees { } } + private class DestructuredParameterTree extends StandardPostOrderTree, DestructuredParameter { + final override ControlFlowTree getChildElement(int i) { result = this.getElement(i) } + } + private class DesugaredTree extends ControlFlowTree { ControlFlowTree desugared; @@ -1381,10 +1385,6 @@ module Trees { } } - private class TuplePatternTree extends StandardPostOrderTree, TuplePattern { - final override ControlFlowTree getChildElement(int i) { result = this.getElement(i) } - } - private class UndefStmtTree extends StandardPreOrderTree, UndefStmt { final override ControlFlowTree getChildElement(int i) { result = this.getMethodName(i) } } diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected index c98183b5f79e..3c40c864e469 100644 --- a/ruby/ql/test/library-tests/ast/Ast.expected +++ b/ruby/ql/test/library-tests/ast/Ast.expected @@ -559,7 +559,7 @@ calls/calls.rb: # 315| getArgument: [IntegerLiteral] 0 # 315| getAnOperand/getRightOperand: [IntegerLiteral] 10 # 316| getStmt: [AssignExpr] ... = ... -# 316| getLeftOperand: [TuplePattern] (..., ...) +# 316| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 316| getElement: [MethodCall] call to foo # 316| getReceiver: [Self, SelfVariableAccess] self # 316| getElement: [MethodCall] call to bar @@ -574,7 +574,7 @@ calls/calls.rb: # 316| getElement: [IntegerLiteral] 3 # 316| getElement: [IntegerLiteral] 4 # 317| getStmt: [AssignExpr] ... = ... -# 317| getLeftOperand: [TuplePattern] (..., ...) +# 317| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 317| getElement: [LocalVariableAccess] a # 317| getElement: [ElementReference] ...[...] # 317| getReceiver: [MethodCall] call to foo @@ -654,7 +654,7 @@ calls/calls.rb: # 336| getArgument: [LocalVariableAccess] b # 336| getArgument: [ForwardedArguments] ... # 340| getStmt: [ForExpr] for ... in ... -# 340| getPattern: [TuplePattern] (..., ...) +# 340| getPattern: [DestructuredLhsExpr] (..., ...) # 340| getElement: [LocalVariableAccess] x # 340| getElement: [LocalVariableAccess] y # 340| getElement: [LocalVariableAccess] z @@ -1845,7 +1845,7 @@ control/loops.rb: # 18| getAnOperand/getLeftOperand: [LocalVariableAccess] foo # 18| getAnOperand/getRightOperand: [LocalVariableAccess] n # 22| getStmt: [ForExpr] for ... in ... -# 22| getPattern: [TuplePattern] (..., ...) +# 22| getPattern: [DestructuredLhsExpr] (..., ...) # 22| getElement: [LocalVariableAccess] key # 22| getElement: [LocalVariableAccess] value # 22| getValue: [HashLiteral] {...} @@ -1863,7 +1863,7 @@ control/loops.rb: # 24| getAnOperand/getLeftOperand: [LocalVariableAccess] foo # 24| getAnOperand/getRightOperand: [LocalVariableAccess] value # 28| getStmt: [ForExpr] for ... in ... -# 28| getPattern: [TuplePattern] (..., ...) +# 28| getPattern: [DestructuredLhsExpr] (..., ...) # 28| getElement: [LocalVariableAccess] key # 28| getElement: [LocalVariableAccess] value # 28| getValue: [HashLiteral] {...} @@ -2367,7 +2367,7 @@ params/params.rb: # 14| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] foo # 14| getAnOperand/getArgument/getRightOperand: [LocalVariableAccess] bar # 17| getStmt: [Method] destructured_method_param -# 17| getParameter: [TuplePatternParameter] (..., ...) +# 17| getParameter: [DestructuredParameter] (..., ...) # 17| getElement: [LocalVariableAccess] a # 17| getElement: [LocalVariableAccess] b # 17| getElement: [LocalVariableAccess] c @@ -2377,7 +2377,7 @@ params/params.rb: # 22| getStmt: [MethodCall] call to each # 22| getReceiver: [LocalVariableAccess] array # 22| getBlock: [BraceBlock] { ... } -# 22| getParameter: [TuplePatternParameter] (..., ...) +# 22| getParameter: [DestructuredParameter] (..., ...) # 22| getElement: [LocalVariableAccess] a # 22| getElement: [LocalVariableAccess] b # 22| getStmt: [MethodCall] call to puts @@ -2388,10 +2388,10 @@ params/params.rb: # 25| getStmt: [AssignExpr] ... = ... # 25| getAnOperand/getLeftOperand: [LocalVariableAccess] sum_four_values # 25| getAnOperand/getRightOperand: [Lambda] -> { ... } -# 25| getParameter: [TuplePatternParameter] (..., ...) +# 25| getParameter: [DestructuredParameter] (..., ...) # 25| getElement: [LocalVariableAccess] first # 25| getElement: [LocalVariableAccess] second -# 25| getParameter: [TuplePatternParameter] (..., ...) +# 25| getParameter: [DestructuredParameter] (..., ...) # 25| getElement: [LocalVariableAccess] third # 25| getElement: [LocalVariableAccess] fourth # 26| getStmt: [AddExpr] ... + ... diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected index 71b66f9739b7..bfe8d69971ab 100644 --- a/ruby/ql/test/library-tests/ast/AstDesugar.expected +++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected @@ -245,7 +245,7 @@ calls/calls.rb: # 340| getAnOperand/getRightOperand: [MethodCall] call to [] # 340| getArgument: [IntegerLiteral] 2 # 340| getReceiver: [LocalVariableAccess] __synth__0__1 -# 340| getLeftOperand: [TuplePattern] (..., ...) +# 340| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 341| getStmt: [MethodCall] call to foo # 341| getReceiver: [Self, SelfVariableAccess] self # 341| getArgument: [LocalVariableAccess] x @@ -477,7 +477,7 @@ control/loops.rb: # 22| getAnOperand/getRightOperand: [MethodCall] call to [] # 22| getArgument: [IntegerLiteral] 1 # 22| getReceiver: [LocalVariableAccess] __synth__0__1 -# 22| getLeftOperand: [TuplePattern] (..., ...) +# 22| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 23| getStmt: [AssignAddExpr] ... += ... # 23| getDesugared: [AssignExpr] ... = ... # 23| getAnOperand/getLeftOperand: [LocalVariableAccess] sum @@ -518,7 +518,7 @@ control/loops.rb: # 28| getAnOperand/getRightOperand: [MethodCall] call to [] # 28| getArgument: [IntegerLiteral] 1 # 28| getReceiver: [LocalVariableAccess] __synth__0__1 -# 28| getLeftOperand: [TuplePattern] (..., ...) +# 28| getAnOperand/getLeftOperand: [DestructuredLhsExpr] (..., ...) # 29| getStmt: [AssignAddExpr] ... += ... # 29| getDesugared: [AssignExpr] ... = ... # 29| getAnOperand/getLeftOperand: [LocalVariableAccess] sum diff --git a/ruby/ql/test/library-tests/ast/control/Loop.ql b/ruby/ql/test/library-tests/ast/control/Loop.ql index d5275b46e333..ff3d846c4bda 100644 --- a/ruby/ql/test/library-tests/ast/control/Loop.ql +++ b/ruby/ql/test/library-tests/ast/control/Loop.ql @@ -13,13 +13,13 @@ query predicate conditionalLoops( cond = l.getCondition() } -query predicate forExprs(ForExpr f, Pattern p, StmtSequence body, int i, Stmt bodyChild) { +query predicate forExprs(ForExpr f, LhsExpr p, StmtSequence body, int i, Stmt bodyChild) { p = f.getPattern() and body = f.getBody() and bodyChild = body.getStmt(i) } -query predicate forExprsTuplePatterns(ForExpr f, TuplePattern tp, int i, Pattern cp) { +query predicate forExprsTuplePatterns(ForExpr f, DestructuredLhsExpr tp, int i, Expr cp) { tp = f.getPattern() and cp = tp.getElement(i) } diff --git a/ruby/ql/test/library-tests/ast/params/params.expected b/ruby/ql/test/library-tests/ast/params/params.expected index 6c7ee9d2e1ab..910675a27e36 100644 --- a/ruby/ql/test/library-tests/ast/params/params.expected +++ b/ruby/ql/test/library-tests/ast/params/params.expected @@ -73,7 +73,7 @@ paramsInMethods | 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:17:1:18:3 | destructured_method_param | 0 | params.rb:17:31:17:39 | (..., ...) | DestructuredParameter | | 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 | @@ -90,7 +90,7 @@ paramsInMethods 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 | -| params.rb:22:12:22:32 | { ... } | 0 | params.rb:22:15:22:20 | (..., ...) | TuplePatternParameter | +| params.rb:22:12:22:32 | { ... } | 0 | params.rb:22:15:22:20 | (..., ...) | DestructuredParameter | | params.rb:34:12:35:3 | do ... end | 0 | params.rb:34:16:34:18 | val | SimpleParameter | | params.rb:34:12:35:3 | do ... end | 1 | params.rb:34:21:34:26 | *splat | SplatParameter | | params.rb:34:12:35:3 | do ... end | 2 | params.rb:34:29:34:42 | **double_splat | HashSplatParameter | @@ -103,8 +103,8 @@ paramsInBlocks 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 | -| 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:25:19:27:1 | -> { ... } | 0 | params.rb:25:23:25:37 | (..., ...) | DestructuredParameter | +| params.rb:25:19:27:1 | -> { ... } | 1 | params.rb:25:40:25:54 | (..., ...) | DestructuredParameter | | 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 | @@ -122,10 +122,10 @@ params | 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:17:31:17:39 | (..., ...) | 0 | DestructuredParameter | +| params.rb:22:15:22:20 | (..., ...) | 0 | DestructuredParameter | +| params.rb:25:23:25:37 | (..., ...) | 0 | DestructuredParameter | +| params.rb:25:40:25:54 | (..., ...) | 1 | DestructuredParameter | | 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 | diff --git a/ruby/ql/test/library-tests/ast/params/params.ql b/ruby/ql/test/library-tests/ast/params/params.ql index eb77ac0e4182..68c22636a2ca 100644 --- a/ruby/ql/test/library-tests/ast/params/params.ql +++ b/ruby/ql/test/library-tests/ast/params/params.ql @@ -6,7 +6,7 @@ query predicate idParams(NamedParameter np, string name) { name = np.getName() } query predicate blockParams(BlockParameter bp, string name) { name = bp.getName() } -query predicate patternParams(TuplePatternParameter tpp, Pattern child, int childIndex) { +query predicate patternParams(DestructuredParameter tpp, AstNode child, int childIndex) { tpp.getElement(childIndex) = child } diff --git a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected index fe84897c026e..801501f8e65f 100644 --- a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected +++ b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected @@ -1941,12 +1941,12 @@ cfg.rb: # 62| call to [] #-----| -> * ... -# 62| ... -#-----| -> ... - # 62| 1 #-----| -> call to [] +# 62| ... +#-----| -> ... + # 62| __synth__0 #-----| -> 1 @@ -3626,12 +3626,12 @@ desugar.rb: # 22| call to [] #-----| -> ... = ... -# 22| ... -#-----| -> ... - # 22| -1 #-----| -> call to [] +# 22| ... +#-----| -> ... + # 22| __synth__0 #-----| -> -1 @@ -3706,12 +3706,12 @@ desugar.rb: # 26| call to [] #-----| -> * ... -# 26| ... -#-----| -> ... - # 26| 1 #-----| -> call to [] +# 26| ... +#-----| -> ... + # 26| __synth__0 #-----| -> 1 diff --git a/ruby/ql/test/library-tests/variables/parameter.expected b/ruby/ql/test/library-tests/variables/parameter.expected index eaee1d26da3b..cd3a257a8210 100644 --- a/ruby/ql/test/library-tests/variables/parameter.expected +++ b/ruby/ql/test/library-tests/variables/parameter.expected @@ -23,6 +23,11 @@ parameterVariable | parameters.rb:49:12:49:16 | (..., ...) | parameters.rb:49:13:49:13 | a | | parameters.rb:49:12:49:16 | (..., ...) | parameters.rb:49:15:49:15 | b | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | +| parameters.rb:59:19:59:27 | (..., ...) | parameters.rb:59:20:59:20 | a | +| parameters.rb:59:19:59:27 | (..., ...) | parameters.rb:59:23:59:23 | b | +| parameters.rb:59:19:59:27 | (..., ...) | parameters.rb:59:25:59:25 | c | +| parameters.rb:59:22:59:26 | (..., ...) | parameters.rb:59:23:59:23 | b | +| parameters.rb:59:22:59:26 | (..., ...) | parameters.rb:59:25:59:25 | c | | 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 | | ssa.rb:1:7:1:7 | b | ssa.rb:1:7:1:7 | b | diff --git a/ruby/ql/test/library-tests/variables/parameters.rb b/ruby/ql/test/library-tests/variables/parameters.rb index 99aff4df5aee..47b9946beab4 100644 --- a/ruby/ql/test/library-tests/variables/parameters.rb +++ b/ruby/ql/test/library-tests/variables/parameters.rb @@ -56,3 +56,7 @@ def tuples((a,b)) puts y end +def tuples_nested((a,(b,c))) + puts "#{a} #{b} #{c}" +end + diff --git a/ruby/ql/test/library-tests/variables/ssa.expected b/ruby/ql/test/library-tests/variables/ssa.expected index 05701ea74660..fc170598d964 100644 --- a/ruby/ql/test/library-tests/variables/ssa.expected +++ b/ruby/ql/test/library-tests/variables/ssa.expected @@ -29,7 +29,7 @@ definition | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | | nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | | nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | -| parameters.rb:1:9:5:3 | | parameters.rb:1:1:58:1 | self | +| parameters.rb:1:9:5:3 | | parameters.rb:1:1:62:1 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | | parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | @@ -63,11 +63,15 @@ definition | parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | | parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | | parameters.rb:53:1:53:6 | ... = ... | parameters.rb:53:1:53:1 | x | -| parameters.rb:54:9:57:3 | | parameters.rb:1:1:58:1 | self | +| parameters.rb:54:9:57:3 | | parameters.rb:1:1:62:1 | self | | parameters.rb:54:9:57:3 | | parameters.rb:53:1:53:1 | x | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | | parameters.rb:54:19:54:23 | ... = ... | parameters.rb:53:1:53:1 | x | | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | +| parameters.rb:59:1:61:3 | self (tuples_nested) | parameters.rb:59:1:61:3 | self | +| parameters.rb:59:20:59:20 | a | parameters.rb:59:20:59:20 | a | +| parameters.rb:59:23:59:23 | b | parameters.rb:59:23:59:23 | b | +| parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | | scopes.rb:1:1:1:15 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | @@ -180,8 +184,8 @@ read | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:32:11:32:16 | self | | nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | | nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | -| parameters.rb:1:9:5:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:3:4:3:9 | self | -| parameters.rb:1:9:5:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:4:4:4:9 | self | +| parameters.rb:1:9:5:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:3:4:3:9 | self | +| parameters.rb:1:9:5:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:4:4:4:9 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:3:9:3:9 | x | | parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:9:5:9:33 | self | @@ -215,10 +219,14 @@ read | parameters.rb:49:1:51:3 | self (tuples) | parameters.rb:49:1:51:3 | self | parameters.rb:50:3:50:18 | self | | parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:50:11:50:11 | a | | parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:50:16:50:16 | b | -| parameters.rb:54:9:57:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:55:4:55:9 | self | -| parameters.rb:54:9:57:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:56:4:56:9 | self | +| parameters.rb:54:9:57:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:55:4:55:9 | self | +| parameters.rb:54:9:57:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:56:4:56:9 | self | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:56:9:56:9 | y | | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:55:9:55:9 | x | +| parameters.rb:59:1:61:3 | self (tuples_nested) | parameters.rb:59:1:61:3 | self | parameters.rb:60:3:60:23 | self | +| parameters.rb:59:20:59:20 | a | parameters.rb:59:20:59:20 | a | parameters.rb:60:11:60:11 | a | +| parameters.rb:59:23:59:23 | b | parameters.rb:59:23:59:23 | b | parameters.rb:60:16:60:16 | b | +| parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | parameters.rb:60:21:60:21 | c | | scopes.rb:1:1:1:15 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | scopes.rb:8:1:8:6 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:3:4:3:9 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:3:9:3:9 | self | @@ -339,7 +347,7 @@ firstRead | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:32:11:32:16 | self | | nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | | nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | -| parameters.rb:1:9:5:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:3:4:3:9 | self | +| parameters.rb:1:9:5:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:3:4:3:9 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:3:9:3:9 | x | | parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:9:5:9:33 | self | @@ -371,9 +379,13 @@ firstRead | parameters.rb:49:1:51:3 | self (tuples) | parameters.rb:49:1:51:3 | self | parameters.rb:50:3:50:18 | self | | parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:50:11:50:11 | a | | parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:50:16:50:16 | b | -| parameters.rb:54:9:57:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:55:4:55:9 | self | +| parameters.rb:54:9:57:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:55:4:55:9 | self | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:56:9:56:9 | y | | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:55:9:55:9 | x | +| parameters.rb:59:1:61:3 | self (tuples_nested) | parameters.rb:59:1:61:3 | self | parameters.rb:60:3:60:23 | self | +| parameters.rb:59:20:59:20 | a | parameters.rb:59:20:59:20 | a | parameters.rb:60:11:60:11 | a | +| parameters.rb:59:23:59:23 | b | parameters.rb:59:23:59:23 | b | parameters.rb:60:16:60:16 | b | +| parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | parameters.rb:60:21:60:21 | c | | scopes.rb:1:1:1:15 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | scopes.rb:8:1:8:6 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:3:4:3:9 | self | | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | @@ -464,7 +476,7 @@ lastRead | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:32:11:32:16 | self | | nested_scopes.rb:31:11:31:16 | ... = ... | nested_scopes.rb:31:11:31:11 | a | nested_scopes.rb:32:16:32:16 | a | | nested_scopes.rb:40:1:40:18 | ... = ... | nested_scopes.rb:40:1:40:1 | d | nested_scopes.rb:41:1:41:1 | d | -| parameters.rb:1:9:5:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:4:4:4:9 | self | +| parameters.rb:1:9:5:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:4:4:4:9 | self | | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:3:9:3:9 | x | | parameters.rb:2:4:2:8 | ... = ... | parameters.rb:1:18:1:18 | y | parameters.rb:4:9:4:9 | y | | parameters.rb:7:1:13:3 | self (order_pizza) | parameters.rb:7:1:13:3 | self | parameters.rb:9:5:9:33 | self | @@ -496,9 +508,13 @@ lastRead | parameters.rb:49:1:51:3 | self (tuples) | parameters.rb:49:1:51:3 | self | parameters.rb:50:3:50:18 | self | | parameters.rb:49:13:49:13 | a | parameters.rb:49:13:49:13 | a | parameters.rb:50:11:50:11 | a | | parameters.rb:49:15:49:15 | b | parameters.rb:49:15:49:15 | b | parameters.rb:50:16:50:16 | b | -| parameters.rb:54:9:57:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:56:4:56:9 | self | +| parameters.rb:54:9:57:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:56:4:56:9 | self | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:56:9:56:9 | y | | parameters.rb:55:4:55:9 | phi | parameters.rb:53:1:53:1 | x | parameters.rb:55:9:55:9 | x | +| parameters.rb:59:1:61:3 | self (tuples_nested) | parameters.rb:59:1:61:3 | self | parameters.rb:60:3:60:23 | self | +| parameters.rb:59:20:59:20 | a | parameters.rb:59:20:59:20 | a | parameters.rb:60:11:60:11 | a | +| parameters.rb:59:23:59:23 | b | parameters.rb:59:23:59:23 | b | parameters.rb:60:16:60:16 | b | +| parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | parameters.rb:60:21:60:21 | c | | scopes.rb:1:1:1:15 | self (scopes.rb) | scopes.rb:1:1:49:4 | self | scopes.rb:8:1:8:6 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:5:4:5:9 | self | | scopes.rb:4:4:4:8 | ... = ... | scopes.rb:4:4:4:4 | a | scopes.rb:5:9:5:9 | a | @@ -568,11 +584,11 @@ adjacentReads | nested_scopes.rb:13:11:13:15 | ... = ... | nested_scopes.rb:13:11:13:11 | a | nested_scopes.rb:14:16:14:16 | a | nested_scopes.rb:15:11:15:11 | a | | nested_scopes.rb:27:7:29:9 | self (show) | nested_scopes.rb:27:7:29:9 | self | nested_scopes.rb:28:11:28:16 | self | nested_scopes.rb:28:16:28:16 | self | | nested_scopes.rb:30:16:30:19 | self (class << ...) | nested_scopes.rb:30:7:33:9 | self | nested_scopes.rb:30:16:30:19 | self | nested_scopes.rb:32:11:32:16 | self | -| parameters.rb:1:9:5:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:3:4:3:9 | self | parameters.rb:4:4:4:9 | self | +| parameters.rb:1:9:5:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:3:4:3:9 | self | parameters.rb:4:4:4:9 | self | | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:8:6:8:11 | pizzas | parameters.rb:11:14:11:19 | pizzas | | parameters.rb:25:1:28:3 | self (opt_param) | parameters.rb:25:1:28:3 | self | parameters.rb:26:3:26:11 | self | parameters.rb:27:3:27:11 | self | | parameters.rb:25:15:25:18 | name | parameters.rb:25:15:25:18 | name | parameters.rb:25:40:25:43 | name | parameters.rb:26:8:26:11 | name | -| parameters.rb:54:9:57:3 | | parameters.rb:1:1:58:1 | self | parameters.rb:55:4:55:9 | self | parameters.rb:56:4:56:9 | self | +| parameters.rb:54:9:57:3 | | parameters.rb:1:1:62:1 | self | parameters.rb:55:4:55:9 | self | parameters.rb:56:4:56:9 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:3:4:3:9 | self | scopes.rb:3:9:3:9 | self | | scopes.rb:2:9:6:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:3:9:3:9 | self | scopes.rb:5:4:5:9 | self | | scopes.rb:9:9:18:3 | | scopes.rb:1:1:49:4 | self | scopes.rb:10:4:10:9 | self | scopes.rb:12:4:12:9 | self | diff --git a/ruby/ql/test/library-tests/variables/varaccess.expected b/ruby/ql/test/library-tests/variables/varaccess.expected index ff2e1af49bc4..2b3294bc0a7c 100644 --- a/ruby/ql/test/library-tests/variables/varaccess.expected +++ b/ruby/ql/test/library-tests/variables/varaccess.expected @@ -73,9 +73,9 @@ variableAccess | parameters.rb:1:14:1:14 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | do ... end | | parameters.rb:1:18:1:18 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | do ... end | | parameters.rb:2:4:2:4 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | do ... end | -| parameters.rb:3:4:3:9 | self | parameters.rb:1:1:58:1 | self | parameters.rb:1:1:58:1 | parameters.rb | +| parameters.rb:3:4:3:9 | self | parameters.rb:1:1:62:1 | self | parameters.rb:1:1:62:1 | parameters.rb | | parameters.rb:3:9:3:9 | x | parameters.rb:1:14:1:14 | x | parameters.rb:1:9:5:3 | do ... end | -| parameters.rb:4:4:4:9 | self | parameters.rb:1:1:58:1 | self | parameters.rb:1:1:58:1 | parameters.rb | +| parameters.rb:4:4:4:9 | self | parameters.rb:1:1:62:1 | self | parameters.rb:1:1:62:1 | parameters.rb | | parameters.rb:4:9:4:9 | y | parameters.rb:1:18:1:18 | y | parameters.rb:1:9:5:3 | do ... end | | parameters.rb:7:17:7:22 | client | parameters.rb:7:17:7:22 | client | parameters.rb:7:1:13:3 | order_pizza | | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:26:7:31 | pizzas | parameters.rb:7:1:13:3 | order_pizza | @@ -108,7 +108,7 @@ variableAccess | parameters.rb:31:11:31:15 | first | parameters.rb:30:15:30:19 | first | parameters.rb:30:1:32:3 | key_param | | parameters.rb:31:20:31:25 | middle | parameters.rb:30:24:30:29 | middle | parameters.rb:30:1:32:3 | key_param | | parameters.rb:31:30:31:33 | last | parameters.rb:30:36:30:39 | last | parameters.rb:30:1:32:3 | key_param | -| parameters.rb:34:1:34:1 | b | parameters.rb:34:1:34:1 | b | parameters.rb:1:1:58:1 | parameters.rb | +| parameters.rb:34:1:34:1 | b | parameters.rb:34:1:34:1 | b | parameters.rb:1:1:62:1 | parameters.rb | | parameters.rb:35:11:35:11 | a | parameters.rb:35:11:35:11 | a | parameters.rb:35:1:38:3 | multi | | parameters.rb:35:16:35:16 | b | parameters.rb:35:16:35:16 | b | parameters.rb:35:1:38:3 | multi | | parameters.rb:37:3:37:18 | self | parameters.rb:35:1:38:3 | self | parameters.rb:35:1:38:3 | multi | @@ -127,13 +127,20 @@ variableAccess | parameters.rb:50:3:50:18 | self | parameters.rb:49:1:51:3 | self | parameters.rb:49:1:51:3 | tuples | | parameters.rb:50:11:50:11 | a | parameters.rb:49:13:49:13 | a | parameters.rb:49:1:51:3 | tuples | | parameters.rb:50:16:50:16 | b | parameters.rb:49:15:49:15 | b | parameters.rb:49:1:51:3 | tuples | -| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | parameters.rb | +| parameters.rb:53:1:53:1 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:62:1 | parameters.rb | | parameters.rb:54:14:54:14 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | do ... end | -| parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | parameters.rb | -| parameters.rb:55:4:55:9 | self | parameters.rb:1:1:58:1 | self | parameters.rb:1:1:58:1 | parameters.rb | -| parameters.rb:55:9:55:9 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:58:1 | parameters.rb | -| parameters.rb:56:4:56:9 | self | parameters.rb:1:1:58:1 | self | parameters.rb:1:1:58:1 | parameters.rb | +| parameters.rb:54:19:54:19 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:62:1 | parameters.rb | +| parameters.rb:55:4:55:9 | self | parameters.rb:1:1:62:1 | self | parameters.rb:1:1:62:1 | parameters.rb | +| parameters.rb:55:9:55:9 | x | parameters.rb:53:1:53:1 | x | parameters.rb:1:1:62:1 | parameters.rb | +| parameters.rb:56:4:56:9 | self | parameters.rb:1:1:62:1 | self | parameters.rb:1:1:62:1 | parameters.rb | | parameters.rb:56:9:56:9 | y | parameters.rb:54:14:54:14 | y | parameters.rb:54:9:57:3 | do ... end | +| parameters.rb:59:20:59:20 | a | parameters.rb:59:20:59:20 | a | parameters.rb:59:1:61:3 | tuples_nested | +| parameters.rb:59:23:59:23 | b | parameters.rb:59:23:59:23 | b | parameters.rb:59:1:61:3 | tuples_nested | +| parameters.rb:59:25:59:25 | c | parameters.rb:59:25:59:25 | c | parameters.rb:59:1:61:3 | tuples_nested | +| parameters.rb:60:3:60:23 | self | parameters.rb:59:1:61:3 | self | parameters.rb:59:1:61:3 | tuples_nested | +| parameters.rb:60:11:60:11 | a | parameters.rb:59:20:59:20 | a | parameters.rb:59:1:61:3 | tuples_nested | +| parameters.rb:60:16:60:16 | b | parameters.rb:59:23:59:23 | b | parameters.rb:59:1:61:3 | tuples_nested | +| parameters.rb:60:21:60:21 | c | parameters.rb:59:25:59:25 | c | parameters.rb:59:1:61:3 | tuples_nested | | scopes.rb:2:14:2:14 | x | scopes.rb:2:14:2:14 | x | scopes.rb:2:9:6:3 | do ... end | | scopes.rb:3:4:3:9 | self | scopes.rb:1:1:49:4 | self | scopes.rb:1:1:49:4 | scopes.rb | | scopes.rb:3:9:3:9 | self | scopes.rb:1:1:49:4 | self | scopes.rb:1:1:49:4 | scopes.rb | @@ -354,6 +361,9 @@ implicitWrite | parameters.rb:49:13:49:13 | a | | parameters.rb:49:15:49:15 | b | | parameters.rb:54:14:54:14 | y | +| parameters.rb:59:20:59:20 | a | +| parameters.rb:59:23:59:23 | b | +| parameters.rb:59:25:59:25 | c | | scopes.rb:2:14:2:14 | x | | scopes.rb:9:14:9:14 | x | | ssa.rb:1:7:1:7 | b | @@ -452,6 +462,10 @@ readAccess | parameters.rb:55:9:55:9 | x | | parameters.rb:56:4:56:9 | self | | parameters.rb:56:9:56:9 | y | +| parameters.rb:60:3:60:23 | self | +| parameters.rb:60:11:60:11 | a | +| parameters.rb:60:16:60:16 | b | +| parameters.rb:60:21:60:21 | c | | scopes.rb:3:4:3:9 | self | | scopes.rb:3:9:3:9 | self | | scopes.rb:5:4:5:9 | self | diff --git a/ruby/ql/test/library-tests/variables/variable.expected b/ruby/ql/test/library-tests/variables/variable.expected index 0da853550735..541ed3946530 100644 --- a/ruby/ql/test/library-tests/variables/variable.expected +++ b/ruby/ql/test/library-tests/variables/variable.expected @@ -56,7 +56,7 @@ | nested_scopes.rb:30:7:33:9 | self | | nested_scopes.rb:31:11:31:11 | a | | nested_scopes.rb:40:1:40:1 | d | -| parameters.rb:1:1:58:1 | self | +| parameters.rb:1:1:62:1 | self | | parameters.rb:1:14:1:14 | x | | parameters.rb:1:18:1:18 | y | | parameters.rb:7:1:13:3 | self | @@ -89,6 +89,10 @@ | parameters.rb:49:15:49:15 | b | | parameters.rb:53:1:53:1 | x | | parameters.rb:54:14:54:14 | y | +| parameters.rb:59:1:61:3 | self | +| parameters.rb:59:20:59:20 | a | +| parameters.rb:59:23:59:23 | b | +| parameters.rb:59:25:59:25 | c | | scopes.rb:1:1:1:15 | self | | scopes.rb:1:1:49:4 | self | | scopes.rb:2:14:2:14 | x | diff --git a/ruby/ql/test/library-tests/variables/varscopes.expected b/ruby/ql/test/library-tests/variables/varscopes.expected index 70db175cfe0f..1859ab015503 100644 --- a/ruby/ql/test/library-tests/variables/varscopes.expected +++ b/ruby/ql/test/library-tests/variables/varscopes.expected @@ -32,7 +32,7 @@ | nested_scopes.rb:22:9:24:11 | show_a2 | | nested_scopes.rb:27:7:29:9 | show | | nested_scopes.rb:30:7:33:9 | class << ... | -| parameters.rb:1:1:58:1 | parameters.rb | +| parameters.rb:1:1:62:1 | parameters.rb | | parameters.rb:1:9:5:3 | do ... end | | parameters.rb:7:1:13:3 | order_pizza | | parameters.rb:15:1:19:3 | print_map | @@ -45,6 +45,7 @@ | parameters.rb:45:1:47:3 | dup_underscore | | parameters.rb:49:1:51:3 | tuples | | parameters.rb:54:9:57:3 | do ... end | +| parameters.rb:59:1:61:3 | tuples_nested | | scopes.rb:1:1:1:15 | a | | scopes.rb:1:1:49:4 | scopes.rb | | scopes.rb:2:9:6:3 | do ... end |