Skip to content

Commit 8860b8a

Browse files
authored
Merge pull request #198 from github/hvitved/desugar-compound-assignment
2 parents f74dff5 + 962768e commit 8860b8a

18 files changed

Lines changed: 1115 additions & 346 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/Call.qll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ predicate isScopeResolutionMethodCall(Generated::ScopeResolution g, Generated::I
1313
}
1414

1515
abstract class CallImpl extends Call {
16-
abstract Expr getArgumentImpl(int n);
16+
abstract AstNode getArgumentImpl(int n);
1717

1818
/**
1919
* It is not possible to define this predicate as
@@ -28,7 +28,7 @@ abstract class CallImpl extends Call {
2828
}
2929

3030
abstract class MethodCallImpl extends CallImpl, MethodCall {
31-
abstract Expr getReceiverImpl();
31+
abstract AstNode getReceiverImpl();
3232

3333
abstract string getMethodNameImpl();
3434
}
@@ -42,9 +42,9 @@ class MethodCallSynth extends MethodCallImpl, TMethodCallSynth {
4242
)
4343
}
4444

45-
final override Expr getReceiverImpl() { synthChild(this, 0, result) }
45+
final override AstNode getReceiverImpl() { synthChild(this, 0, result) }
4646

47-
final override Expr getArgumentImpl(int n) { synthChild(this, n + 1, result) and n >= 0 }
47+
final override AstNode getArgumentImpl(int n) { synthChild(this, n + 1, result) and n >= 0 }
4848

4949
final override int getNumberOfArgumentsImpl() { this = TMethodCallSynth(_, _, _, _, result) }
5050
}
@@ -56,7 +56,7 @@ class IdentifierMethodCall extends MethodCallImpl, TIdentifierMethodCall {
5656

5757
final override string getMethodNameImpl() { result = g.getValue() }
5858

59-
final override Self getReceiverImpl() { result = TSelfSynth(this, 0) }
59+
final override AstNode getReceiverImpl() { result = TSelfSynth(this, 0) }
6060

6161
final override Expr getArgumentImpl(int n) { none() }
6262

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

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,45 @@ private import AST
33
private import TreeSitter
44

55
class AssignmentImpl extends Operation, TAssignment {
6-
abstract Pattern getLeftOperandImpl();
6+
abstract AstNode getLeftOperandImpl();
77

8-
abstract Expr getRightOperandImpl();
8+
abstract AstNode getRightOperandImpl();
99
}
1010

1111
class AssignExprReal extends AssignmentImpl, AssignExpr, TAssignExprReal {
1212
private Generated::Assignment g;
1313

1414
AssignExprReal() { this = TAssignExprReal(g) }
1515

16-
final override Pattern getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
16+
final override AstNode getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
1717

18-
final override Expr getRightOperandImpl() { toGenerated(result) = g.getRight() }
18+
final override AstNode getRightOperandImpl() { toGenerated(result) = g.getRight() }
1919
}
2020

2121
class AssignExprSynth extends AssignmentImpl, AssignExpr, TAssignExprSynth {
22-
final override Pattern getLeftOperandImpl() { synthChild(this, 0, result) }
22+
final override AstNode getLeftOperandImpl() { synthChild(this, 0, result) }
2323

24-
final override Expr getRightOperandImpl() { synthChild(this, 1, result) }
24+
final override AstNode getRightOperandImpl() { synthChild(this, 1, result) }
2525
}
2626

2727
class AssignOperationImpl extends AssignmentImpl, AssignOperation {
28-
final override LhsExpr getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
28+
final override AstNode getLeftOperandImpl() { toGenerated(result) = g.getLeft() }
2929

30-
final override Expr getRightOperandImpl() { toGenerated(result) = g.getRight() }
30+
final override AstNode getRightOperandImpl() { toGenerated(result) = g.getRight() }
31+
}
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) }
3147
}

0 commit comments

Comments
 (0)