Ruby: expressions in pin operator ^

This commit is contained in:
Arthur Baars
2022-01-27 09:49:19 +01:00
parent 00fb4d3776
commit abf3ce6223
10 changed files with 91 additions and 33 deletions

View File

@@ -80,7 +80,7 @@ deprecated class TuplePattern extends Pattern, TTuplePattern {
private class TPatternNode =
TArrayPattern or TFindPattern or THashPattern or TAlternativePattern or TAsPattern or
TParenthesizedPattern or TVariableReferencePattern;
TParenthesizedPattern or TExpressionReferencePattern or TVariableReferencePattern;
private class TPattern =
TPatternNode or TLiteral or TLambda or TConstantAccess or TLocalVariableAccess or
@@ -404,6 +404,42 @@ class ParenthesizedPattern extends CasePattern, TParenthesizedPattern {
}
/**
* A variable or value reference in a pattern, i.e. `^x`, and `^(2 * x)` in the following example:
* ```rb
* x = 10
* case expr
* in ^x then puts "ok"
* in ^(2 * x) then puts "ok"
* end
* ```
*/
class ReferencePattern extends CasePattern, TReferencePattern {
private Ruby::AstNode value;
ReferencePattern() {
value = any(Ruby::VariableReferencePattern g | this = TVariableReferencePattern(g)).getName()
or
value =
any(Ruby::ExpressionReferencePattern g | this = TExpressionReferencePattern(g)).getValue()
}
/** Gets the value this reference pattern matches against. */
final Expr getValue() { toGenerated(result) = value }
final override string getAPrimaryQlClass() { result = "ReferencePattern" }
final override string toString() { result = "^..." }
override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getValue" and result = this.getValue()
}
}
/**
* DEPRECATED: Use `ReferencePattern` instead.
*
* A variable reference in a pattern, i.e. `^x` in the following example:
* ```rb
* x = 10
@@ -412,21 +448,7 @@ class ParenthesizedPattern extends CasePattern, TParenthesizedPattern {
* end
* ```
*/
class VariableReferencePattern extends CasePattern, TVariableReferencePattern {
private Ruby::VariableReferencePattern g;
VariableReferencePattern() { this = TVariableReferencePattern(g) }
deprecated class VariableReferencePattern extends ReferencePattern, TVariableReferencePattern {
/** Gets the variable access corresponding to this variable reference pattern. */
VariableReadAccess getVariableAccess() { toGenerated(result) = g.getName() }
final override string getAPrimaryQlClass() { result = "VariableReferencePattern" }
final override string toString() { result = "^..." }
final override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = "getVariableAccess" and result = this.getVariableAccess()
}
final VariableReadAccess getVariableAccess() { result = this.getValue() }
}

View File

@@ -320,11 +320,14 @@ private module Cached {
TUntilExpr(Ruby::Until g) or
TUntilModifierExpr(Ruby::UntilModifier g) or
TVariableReferencePattern(Ruby::VariableReferencePattern g) or
TExpressionReferencePattern(Ruby::ExpressionReferencePattern g) or
TWhenClause(Ruby::When g) or
TWhileExpr(Ruby::While g) or
TWhileModifierExpr(Ruby::WhileModifier g) or
TYieldCall(Ruby::Yield g)
class TReferencePattern = TVariableReferencePattern or TExpressionReferencePattern;
class TAstNodeReal =
TAddExprReal or TAliasStmt or TAlternativePattern or TArgumentList or TArrayPattern or
TAsPattern or TAssignAddExpr or TAssignBitwiseAndExpr or TAssignBitwiseOrExpr or
@@ -359,7 +362,7 @@ private module Cached {
TTernaryIfExpr or TThen or TTokenConstantAccess or TTokenMethodName or TTokenSuperCall or
TToplevel or TTrueLiteral or TUnaryMinusExpr or TUnaryPlusExpr or TUndefStmt or
TUnlessExpr or TUnlessModifierExpr or TUntilExpr or TUntilModifierExpr or
TVariableReferencePattern or TWhenClause or TWhileExpr or TWhileModifierExpr or TYieldCall;
TReferencePattern or TWhenClause or TWhileExpr or TWhileModifierExpr or TYieldCall;
class TAstNodeSynth =
TAddExprSynth or TAssignExprSynth or TBitwiseAndExprSynth or TBitwiseOrExprSynth or
@@ -529,6 +532,7 @@ private module Cached {
n = TUntilExpr(result) or
n = TUntilModifierExpr(result) or
n = TVariableReferencePattern(result) or
n = TExpressionReferencePattern(result) or
n = TWhenClause(result) or
n = TWhileExpr(result) or
n = TWhileModifierExpr(result) or

View File

@@ -312,6 +312,8 @@ private module Cached {
i = any(Ruby::WhileModifier x).getCondition()
or
i = any(Ruby::WhileModifier x).getBody()
or
i = any(Ruby::ExpressionReferencePattern x).getValue()
}
pragma[nomagic]

View File

@@ -235,7 +235,7 @@ private predicate inMatchingContext(AstNode n) {
or
n instanceof CasePattern
or
n = any(VariableReferencePattern p).getVariableAccess()
n = any(ReferencePattern p).getValue()
or
n.(Trees::DefaultValueParameterTree).hasDefaultValue()
}

View File

@@ -731,8 +731,8 @@ module Trees {
override ControlFlowTree getChildElement(int i) { result = this.getPattern() and i = 0 }
}
private class VariableReferencePatternTree extends StandardPreOrderTree, VariableReferencePattern {
override ControlFlowTree getChildElement(int i) { result = this.getVariableAccess() and i = 0 }
private class ReferencePatternTree extends StandardPreOrderTree, ReferencePattern {
override ControlFlowTree getChildElement(int i) { result = this.getValue() and i = 0 }
}
private class InClauseTree extends PreOrderTree, InClause {

View File

@@ -951,8 +951,8 @@ control/cases.rb:
# 87| getBranch: [InClause] in ... then ...
# 87| getPattern: [IntegerLiteral] 5
# 88| getBranch: [InClause] in ... then ...
# 88| getPattern: [VariableReferencePattern] ^...
# 88| getVariableAccess: [LocalVariableAccess] foo
# 88| getPattern: [ReferencePattern] ^...
# 88| getValue: [LocalVariableAccess] foo
# 89| getBranch: [InClause] in ... then ...
# 89| getPattern: [StringLiteral] "string"
# 89| getComponent: [StringTextComponent] string
@@ -1049,8 +1049,8 @@ control/cases.rb:
# 111| getBranch: [InClause] in ... then ...
# 111| getPattern: [AlternativePattern] ... | ...
# 111| getAlternative: [IntegerLiteral] 5
# 111| getAlternative: [VariableReferencePattern] ^...
# 111| getVariableAccess: [LocalVariableAccess] foo
# 111| getAlternative: [ReferencePattern] ^...
# 111| getValue: [LocalVariableAccess] foo
# 111| getAlternative: [StringLiteral] "string"
# 111| getComponent: [StringTextComponent] string
# 111| getAlternative: [LocalVariableAccess] var
@@ -1145,17 +1145,31 @@ control/cases.rb:
# 147| getValue: [MethodCall] call to expr
# 147| getReceiver: [Self, SelfVariableAccess] self
# 148| getBranch: [InClause] in ... then ...
# 148| getPattern: [VariableReferencePattern] ^...
# 148| getVariableAccess: [LocalVariableAccess] foo
# 148| getPattern: [ReferencePattern] ^...
# 148| getValue: [LocalVariableAccess] foo
# 149| getBranch: [InClause] in ... then ...
# 149| getPattern: [VariableReferencePattern] ^...
# 149| getVariableAccess: [GlobalVariableAccess] $foo
# 149| getPattern: [ReferencePattern] ^...
# 149| getValue: [GlobalVariableAccess] $foo
# 150| getBranch: [InClause] in ... then ...
# 150| getPattern: [VariableReferencePattern] ^...
# 150| getVariableAccess: [InstanceVariableAccess] @foo
# 150| getPattern: [ReferencePattern] ^...
# 150| getValue: [InstanceVariableAccess] @foo
# 151| getBranch: [InClause] in ... then ...
# 151| getPattern: [VariableReferencePattern] ^...
# 151| getVariableAccess: [ClassVariableAccess] @@foo
# 151| getPattern: [ReferencePattern] ^...
# 151| getValue: [ClassVariableAccess] @@foo
# 154| getStmt: [CaseExpr] case ...
# 154| getValue: [MethodCall] call to expr
# 154| getReceiver: [Self, SelfVariableAccess] self
# 155| getBranch: [InClause] in ... then ...
# 155| getPattern: [ReferencePattern] ^...
# 155| getValue: [LocalVariableAccess] foo
# 156| getBranch: [InClause] in ... then ...
# 156| getPattern: [ReferencePattern] ^...
# 156| getValue: [InstanceVariableAccess] @foo
# 157| getBranch: [InClause] in ... then ...
# 157| getPattern: [ReferencePattern] ^...
# 157| getValue: [AddExpr] ... + ...
# 157| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 157| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
modules/classes.rb:
# 2| [Toplevel] classes.rb
# 3| getStmt: [ClassDeclaration] Foo

View File

@@ -244,6 +244,10 @@
| control/cases.rb:144:11:144:11 | :a | :a |
| control/cases.rb:144:14:144:14 | 1 | 1 |
| control/cases.rb:148:7:148:9 | foo | 42 |
| control/cases.rb:155:8:155:10 | foo | 42 |
| control/cases.rb:157:8:157:8 | 1 | 1 |
| control/cases.rb:157:8:157:12 | ... + ... | 2 |
| control/cases.rb:157:12:157:12 | 1 | 1 |
| control/conditionals.rb:2:5:2:5 | 0 | 0 |
| control/conditionals.rb:3:5:3:5 | 0 | 0 |
| control/conditionals.rb:4:5:4:5 | 0 | 0 |

View File

@@ -9,6 +9,7 @@ caseValues
| cases.rb:128:1:133:3 | case ... | cases.rb:128:6:128:9 | call to expr |
| cases.rb:137:1:145:3 | case ... | cases.rb:137:6:137:9 | call to expr |
| cases.rb:147:1:152:3 | case ... | cases.rb:147:6:147:9 | call to expr |
| cases.rb:154:1:158:3 | case ... | cases.rb:154:6:154:9 | call to expr |
caseNoValues
| cases.rb:18:1:22:3 | case ... |
caseElseBranches
@@ -24,6 +25,7 @@ caseNoElseBranches
| cases.rb:128:1:133:3 | case ... |
| cases.rb:137:1:145:3 | case ... |
| cases.rb:147:1:152:3 | case ... |
| cases.rb:154:1:158:3 | case ... |
caseWhenBranches
| cases.rb:8:1:15:3 | case ... | cases.rb:9:1:10:7 | when ... | 0 | cases.rb:9:6:9:6 | b | cases.rb:9:7:10:7 | then ... |
| cases.rb:8:1:15:3 | case ... | cases.rb:11:1:12:7 | when ... | 0 | cases.rb:11:6:11:6 | c | cases.rb:11:10:12:7 | then ... |
@@ -127,3 +129,6 @@ caseAllBranches
| cases.rb:147:1:152:3 | case ... | 1 | cases.rb:149:3:149:11 | in ... then ... |
| cases.rb:147:1:152:3 | case ... | 2 | cases.rb:150:3:150:11 | in ... then ... |
| cases.rb:147:1:152:3 | case ... | 3 | cases.rb:151:3:151:12 | in ... then ... |
| cases.rb:154:1:158:3 | case ... | 0 | cases.rb:155:3:155:12 | in ... then ... |
| cases.rb:154:1:158:3 | case ... | 1 | cases.rb:156:3:156:13 | in ... then ... |
| cases.rb:154:1:158:3 | case ... | 2 | cases.rb:157:3:157:14 | in ... then ... |

View File

@@ -9,6 +9,7 @@
| cases.rb:128:1:133:3 | case ... | CaseExpr |
| cases.rb:137:1:145:3 | case ... | CaseExpr |
| cases.rb:147:1:152:3 | case ... | CaseExpr |
| cases.rb:154:1:158:3 | case ... | CaseExpr |
| conditionals.rb:10:1:12:3 | if ... | IfExpr |
| conditionals.rb:15:1:19:3 | if ... | IfExpr |
| conditionals.rb:22:1:30:3 | if ... | IfExpr |

View File

@@ -149,4 +149,10 @@ case expr
in ^$foo;
in ^@foo;
in ^@@foo;
end
case expr
in ^(foo);
in ^(@foo);
in ^(1 + 1);
end