Skip to content

Commit 6678ac0

Browse files
committed
Desugar compound assignments
1 parent da9adfb commit 6678ac0

15 files changed

Lines changed: 687 additions & 103 deletions

File tree

ql/src/codeql_ruby/ast/Literal.qll

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -752,31 +752,25 @@ class HashLiteral extends Literal, THashLiteral {
752752
* ```
753753
*/
754754
class RangeLiteral extends Literal, TRangeLiteral {
755-
private Generated::Range g;
756-
757-
RangeLiteral() { this = TRangeLiteral(g) }
758-
759755
final override string getAPrimaryQlClass() { result = "RangeLiteral" }
760756

761757
/** Gets the begin expression of this range, if any. */
762-
final Expr getBegin() { toGenerated(result) = g.getBegin() }
758+
Expr getBegin() { none() }
763759

764760
/** Gets the end expression of this range, if any. */
765-
final Expr getEnd() { toGenerated(result) = g.getEnd() }
761+
Expr getEnd() { none() }
766762

767763
/**
768764
* Holds if the range is inclusive of the end value, i.e. uses the `..`
769765
* operator.
770766
*/
771-
final predicate isInclusive() { g instanceof @range_dotdot }
767+
predicate isInclusive() { none() }
772768

773769
/**
774770
* Holds if the range is exclusive of the end value, i.e. uses the `...`
775771
* operator.
776772
*/
777-
final predicate isExclusive() { g instanceof @range_dotdotdot }
778-
779-
final override string toString() { result = "_ " + g.getOperator() + " _" }
773+
predicate isExclusive() { none() }
780774

781775
final override AstNode getAChild(string pred) {
782776
result = super.getAChild(pred)
@@ -785,6 +779,44 @@ class RangeLiteral extends Literal, TRangeLiteral {
785779
or
786780
pred = "getEnd" and result = this.getEnd()
787781
}
782+
783+
final override string toString() {
784+
exists(string op |
785+
this.isInclusive() and op = ".."
786+
or
787+
this.isExclusive() and op = "..."
788+
|
789+
result = "_ " + op + " _"
790+
)
791+
}
792+
}
793+
794+
private class RangeLiteralReal extends RangeLiteral, TRangeLiteralReal {
795+
private Generated::Range g;
796+
797+
RangeLiteralReal() { this = TRangeLiteralReal(g) }
798+
799+
final override Expr getBegin() { toGenerated(result) = g.getBegin() }
800+
801+
final override Expr getEnd() { toGenerated(result) = g.getEnd() }
802+
803+
final override predicate isInclusive() { g instanceof @range_dotdot }
804+
805+
final override predicate isExclusive() { g instanceof @range_dotdotdot }
806+
}
807+
808+
private class RangeLiteralSynth extends RangeLiteral, TRangeLiteralSynth {
809+
private boolean inclusive;
810+
811+
RangeLiteralSynth() { this = TRangeLiteralSynth(_, _, inclusive) }
812+
813+
final override Expr getBegin() { result = TIntegerLiteralSynth(this, 0, _) }
814+
815+
final override Expr getEnd() { result = TIntegerLiteralSynth(this, 1, _) }
816+
817+
final override predicate isInclusive() { inclusive = true }
818+
819+
final override predicate isExclusive() { inclusive = false }
788820
}
789821

790822
/**

ql/src/codeql_ruby/ast/Operation.qll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,8 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, TUnaryMinusExpr {
9191
* foo(*args)
9292
* ```
9393
*/
94-
class SplatExpr extends UnaryOperation, TSplatArgument {
95-
private Generated::SplatArgument g;
96-
97-
SplatExpr() { this = TSplatArgument(g) }
98-
99-
final override Expr getOperand() { toGenerated(result) = g.getChild() }
94+
class SplatExpr extends UnaryOperation, TSplatExpr {
95+
final override Expr getOperand() { result = this.(SplatExprImpl).getOperandImpl() }
10096

10197
final override string getOperator() { result = "*" }
10298

@@ -109,10 +105,10 @@ class SplatExpr extends UnaryOperation, TSplatArgument {
109105
* foo(**options)
110106
* ```
111107
*/
112-
class HashSplatExpr extends UnaryOperation, THashSplatArgument {
108+
class HashSplatExpr extends UnaryOperation, THashSplatExpr {
113109
private Generated::HashSplatArgument g;
114110

115-
HashSplatExpr() { this = THashSplatArgument(g) }
111+
HashSplatExpr() { this = THashSplatExpr(g) }
116112

117113
final override Expr getOperand() { toGenerated(result) = g.getChild() }
118114

ql/src/codeql_ruby/ast/Pattern.qll

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
private import codeql_ruby.AST
22
private import codeql.Locations
33
private import internal.AST
4+
private import internal.Pattern
45
private import internal.TreeSitter
56
private import internal.Variable
67

@@ -62,20 +63,9 @@ class VariablePattern extends Pattern, LhsExpr, TVariablePattern { }
6263
class TuplePattern extends Pattern, TTuplePattern {
6364
override string getAPrimaryQlClass() { result = "TuplePattern" }
6465

65-
private Generated::AstNode getChild(int i) {
66-
result = toGenerated(this).(Generated::DestructuredParameter).getChild(i)
67-
or
68-
result = toGenerated(this).(Generated::DestructuredLeftAssignment).getChild(i)
69-
or
70-
toGenerated(this) =
71-
any(Generated::LeftAssignmentList lal |
72-
if
73-
strictcount(int j | exists(lal.getChild(j))) = 1 and
74-
lal.getChild(0) instanceof Generated::DestructuredLeftAssignment
75-
then result = lal.getChild(0).(Generated::DestructuredLeftAssignment).getChild(i)
76-
else result = lal.getChild(i)
77-
)
78-
}
66+
private TuplePatternImpl getImpl() { result = toGenerated(this) }
67+
68+
private Generated::AstNode getChild(int i) { result = this.getImpl().getChildNode(i) }
7969

8070
/** Gets the `i`th pattern in this tuple pattern. */
8171
final Pattern getElement(int i) {
@@ -96,9 +86,7 @@ class TuplePattern extends Pattern, TTuplePattern {
9686
* a, b, *rest, c, d = value
9787
* ```
9888
*/
99-
final int getRestIndex() {
100-
result = unique(int i | getChild(i) instanceof Generated::RestAssignment)
101-
}
89+
final int getRestIndex() { result = this.getImpl().getRestIndex() }
10290

10391
override Variable getAVariable() { result = this.getElement(_).getAVariable() }
10492

ql/src/codeql_ruby/ast/internal/AST.qll

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ private module Cached {
138138
} or
139139
THashKeySymbolLiteral(Generated::HashKeySymbol g) or
140140
THashLiteral(Generated::Hash g) or
141-
THashSplatArgument(Generated::HashSplatArgument g) or
141+
THashSplatExpr(Generated::HashSplatArgument g) or
142142
THashSplatParameter(Generated::HashSplatParameter g) or
143143
THereDoc(Generated::HeredocBeginning g) or
144144
TIdentifierMethodCall(Generated::Identifier g) { isIdentifierMethodCall(g) } or
@@ -198,7 +198,10 @@ private module Cached {
198198
TParenthesizedExpr(Generated::ParenthesizedStatements g) or
199199
TRShiftExprReal(Generated::Binary g) { g instanceof @binary_ranglerangle } or
200200
TRShiftExprSynth(AST::AstNode parent, int i) { mkSynthChild(RShiftExprKind(), parent, i) } or
201-
TRangeLiteral(Generated::Range g) or
201+
TRangeLiteralReal(Generated::Range g) or
202+
TRangeLiteralSynth(AST::AstNode parent, int i, boolean inclusive) {
203+
mkSynthChild(RangeLiteralKind(inclusive), parent, i)
204+
} or
202205
TRationalLiteral(Generated::Rational g) or
203206
TRedoStmt(Generated::Redo g) or
204207
TRegexLiteral(Generated::Regex g) or
@@ -232,7 +235,8 @@ private module Cached {
232235
TSingletonClass(Generated::SingletonClass g) or
233236
TSingletonMethod(Generated::SingletonMethod g) or
234237
TSpaceshipExpr(Generated::Binary g) { g instanceof @binary_langleequalrangle } or
235-
TSplatArgument(Generated::SplatArgument g) or
238+
TSplatExprReal(Generated::SplatArgument g) or
239+
TSplatExprSynth(AST::AstNode parent, int i) { mkSynthChild(SplatExprKind(), parent, i) } or
236240
TSplatParameter(Generated::SplatParameter g) or
237241
TStmtSequenceSynth(AST::AstNode parent, int i) { mkSynthChild(StmtSequenceKind(), parent, i) } or
238242
TStringArrayLiteral(Generated::StringArray g) or
@@ -337,7 +341,7 @@ private module Cached {
337341
n = TGlobalVariableAccessReal(result, _) or
338342
n = THashKeySymbolLiteral(result) or
339343
n = THashLiteral(result) or
340-
n = THashSplatArgument(result) or
344+
n = THashSplatExpr(result) or
341345
n = THashSplatParameter(result) or
342346
n = THereDoc(result) or
343347
n = TIdentifierMethodCall(result) or
@@ -367,7 +371,7 @@ private module Cached {
367371
n = TPair(result) or
368372
n = TParenthesizedExpr(result) or
369373
n = TRShiftExprReal(result) or
370-
n = TRangeLiteral(result) or
374+
n = TRangeLiteralReal(result) or
371375
n = TRationalLiteral(result) or
372376
n = TRedoStmt(result) or
373377
n = TRegexLiteral(result) or
@@ -388,7 +392,7 @@ private module Cached {
388392
n = TSingletonClass(result) or
389393
n = TSingletonMethod(result) or
390394
n = TSpaceshipExpr(result) or
391-
n = TSplatArgument(result) or
395+
n = TSplatExprReal(result) or
392396
n = TSplatParameter(result) or
393397
n = TStringArrayLiteral(result) or
394398
n = TStringConcatenation(result) or
@@ -458,10 +462,14 @@ private module Cached {
458462
or
459463
result = TMulExprSynth(parent, i)
460464
or
465+
result = TRangeLiteralSynth(parent, i, _)
466+
or
461467
result = TRShiftExprSynth(parent, i)
462468
or
463469
result = TSelfSynth(parent, i)
464470
or
471+
result = TSplatExprSynth(parent, i)
472+
or
465473
result = TStmtSequenceSynth(parent, i)
466474
or
467475
result = TSubExprSynth(parent, i)
@@ -493,18 +501,11 @@ private module Cached {
493501
)
494502
}
495503

496-
private Location synthLocation(AST::AstNode n) {
497-
exists(Synthesis s, AST::AstNode parent, int i |
498-
s.child(parent, i, _, SomeLocation(result)) and
499-
n = getSynthChild(parent, i)
500-
)
501-
}
502-
503504
cached
504505
Location getLocation(AST::AstNode n) {
505-
result = synthLocation(n)
506+
synthLocation(n, result)
506507
or
507-
not exists(synthLocation(n)) and
508+
not synthLocation(n, _) and
508509
result = toGeneratedInclSynth(n).getLocation()
509510
}
510511
}
@@ -538,9 +539,10 @@ class TSelf = TSelfReal or TSelfSynth;
538539

539540
class TExpr =
540541
TSelf or TArgumentList or TRescueClause or TRescueModifierExpr or TPair or TStringConcatenation or
541-
TCall or TBlockArgument or TSplatArgument or THashSplatArgument or TConstantAccess or
542-
TControlExpr or TWhenExpr or TLiteral or TCallable or TVariableAccess or TStmtSequence or
543-
TOperation or TSimpleParameter;
542+
TCall or TBlockArgument or TConstantAccess or TControlExpr or TWhenExpr or TLiteral or
543+
TCallable or TVariableAccess or TStmtSequence or TOperation or TSimpleParameter;
544+
545+
class TSplatExpr = TSplatExprReal or TSplatExprSynth;
544546

545547
class TStmtSequence =
546548
TBeginBlock or TEndBlock or TThen or TElse or TDo or TEnsure or TStringInterpolationComponent or
@@ -586,7 +588,7 @@ class TOperation = TUnaryOperation or TBinaryOperation or TAssignment;
586588

587589
class TUnaryOperation =
588590
TUnaryLogicalOperation or TUnaryArithmeticOperation or TUnaryBitwiseOperation or TDefinedExpr or
589-
TSplatArgument or THashSplatArgument;
591+
TSplatExpr or THashSplatExpr;
590592

591593
class TUnaryLogicalOperation = TNotExpr;
592594

@@ -624,6 +626,8 @@ class TBinaryBitwiseOperation =
624626

625627
class TLShiftExpr = TLShiftExprReal or TLShiftExprSynth;
626628

629+
class TRangeLiteral = TRangeLiteralReal or TRangeLiteralSynth;
630+
627631
class TRShiftExpr = TRShiftExprReal or TRShiftExprSynth;
628632

629633
class TBitwiseAndExpr = TBitwiseAndExprReal or TBitwiseAndExprSynth;

ql/src/codeql_ruby/ast/internal/Operation.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,19 @@ class AssignOperationImpl extends AssignmentImpl, AssignOperation {
2929

3030
final override AstNode getRightOperandImpl() { toGenerated(result) = g.getRight() }
3131
}
32+
33+
abstract class SplatExprImpl extends SplatExpr {
34+
abstract Expr getOperandImpl();
35+
}
36+
37+
class SplatExprReal extends SplatExprImpl, TSplatExprReal {
38+
private Generated::SplatArgument g;
39+
40+
SplatExprReal() { this = TSplatExprReal(g) }
41+
42+
final override Expr getOperandImpl() { toGenerated(result) = g.getChild() }
43+
}
44+
45+
class SplatExprSynth extends SplatExprImpl, TSplatExprSynth {
46+
final override Expr getOperandImpl() { synthChild(this, 0, result) }
47+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
private import codeql_ruby.AST
2+
private import AST
3+
private import TreeSitter
4+
5+
abstract class TuplePatternImpl extends Generated::AstNode {
6+
abstract Generated::AstNode getChildNode(int i);
7+
8+
final int getRestIndex() {
9+
result = unique(int i | this.getChildNode(i) instanceof Generated::RestAssignment)
10+
}
11+
}
12+
13+
class TuplePatternParameterImpl extends TuplePatternImpl, Generated::DestructuredParameter {
14+
override Generated::AstNode getChildNode(int i) { result = this.getChild(i) }
15+
}
16+
17+
class DestructuredLeftAssignmentImpl extends TuplePatternImpl, Generated::DestructuredLeftAssignment {
18+
override Generated::AstNode getChildNode(int i) { result = this.getChild(i) }
19+
}
20+
21+
class LeftAssignmentListImpl extends TuplePatternImpl, Generated::LeftAssignmentList {
22+
override Generated::AstNode getChildNode(int i) {
23+
this =
24+
any(Generated::LeftAssignmentList lal |
25+
if
26+
strictcount(int j | exists(lal.getChild(j))) = 1 and
27+
lal.getChild(0) instanceof Generated::DestructuredLeftAssignment
28+
then result = lal.getChild(0).(Generated::DestructuredLeftAssignment).getChild(i)
29+
else result = lal.getChild(i)
30+
)
31+
}
32+
}

0 commit comments

Comments
 (0)