Skip to content

Commit 3a098d7

Browse files
committed
Ruby: Adopt shared ConditionalCompletionSplitting implementation
1 parent 5d925d3 commit 3a098d7

File tree

2 files changed

+49
-45
lines changed

2 files changed

+49
-45
lines changed

ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ class AstNode extends Ast::AstNode {
2222
private module CfgInput implements CfgShared::InputSig<Location> {
2323
private import ControlFlowGraphImpl as Impl
2424
private import Completion as Comp
25-
private import Splitting as Splitting
2625
private import codeql.ruby.CFG as Cfg
2726

2827
class AstNode = Impl::AstNode;
@@ -45,10 +44,6 @@ private module CfgInput implements CfgShared::InputSig<Location> {
4544
scope.(Impl::CfgScopeImpl).exit(last, c)
4645
}
4746

48-
class SplitKindBase = Splitting::TSplitKind;
49-
50-
class Split = Splitting::Split;
51-
5247
class SuccessorType = Cfg::SuccessorType;
5348

5449
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
@@ -67,7 +62,21 @@ private module CfgInput implements CfgShared::InputSig<Location> {
6762
}
6863
}
6964

70-
import CfgShared::Make<Location, CfgInput>
65+
private module CfgSplittingInput implements CfgShared::SplittingInputSig<Location, CfgInput> {
66+
private import Splitting as S
67+
68+
class SplitKindBase = S::TSplitKind;
69+
70+
class Split = S::Split;
71+
}
72+
73+
private module ConditionalCompletionSplittingInput implements
74+
CfgShared::ConditionalCompletionSplittingInputSig<Location, CfgInput, CfgSplittingInput>
75+
{
76+
import Splitting::ConditionalCompletionSplitting::ConditionalCompletionSplittingInput
77+
}
78+
79+
import CfgShared::MakeWithSplitting<Location, CfgInput, CfgSplittingInput, ConditionalCompletionSplittingInput>
7180

7281
abstract class CfgScopeImpl extends AstNode {
7382
abstract predicate entry(AstNode first);

ruby/ql/lib/codeql/ruby/controlflow/internal/Splitting.qll

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
*/
44

55
private import codeql.ruby.AST as Ast
6-
private import Completion
6+
private import Completion as Comp
7+
private import Comp
78
private import ControlFlowGraphImpl
89
private import SuccessorTypes
910
private import codeql.ruby.controlflow.ControlFlowGraph
@@ -31,7 +32,7 @@ class Split extends TSplit {
3132
string toString() { none() }
3233
}
3334

34-
private module ConditionalCompletionSplitting {
35+
module ConditionalCompletionSplitting {
3536
/**
3637
* A split for conditional completions. For example, in
3738
*
@@ -51,67 +52,61 @@ private module ConditionalCompletionSplitting {
5152

5253
ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }
5354

55+
ConditionalCompletion getCompletion() { result = completion }
56+
5457
override string toString() { result = completion.toString() }
5558
}
5659

57-
private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
60+
private class ConditionalCompletionSplitKind_ extends SplitKind, TConditionalCompletionSplitKind {
5861
override int getListOrder() { result = 0 }
5962

6063
override predicate isEnabled(AstNode n) { this.appliesTo(n) }
6164

6265
override string toString() { result = "ConditionalCompletion" }
6366
}
6467

65-
int getNextListOrder() { result = 1 }
68+
module ConditionalCompletionSplittingInput {
69+
private import Completion as Comp
6670

67-
private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
68-
{
69-
ConditionalCompletion completion;
71+
class ConditionalCompletion = Comp::ConditionalCompletion;
7072

71-
ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
73+
class ConditionalCompletionSplitKind extends ConditionalCompletionSplitKind_, TSplitKind { }
7274

73-
override ConditionalCompletionSplitKind getKind() { any() }
75+
class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;
7476

75-
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
76-
succ(pred, succ, c) and
77-
last(succ, _, completion) and
77+
bindingset[parent, parentCompletion]
78+
predicate condPropagateExpr(
79+
AstNode parent, ConditionalCompletion parentCompletion, AstNode child,
80+
ConditionalCompletion childCompletion
81+
) {
82+
child = parent.(Ast::NotExpr).getOperand() and
83+
childCompletion.(BooleanCompletion).getDual() = parentCompletion
84+
or
85+
childCompletion = parentCompletion and
7886
(
79-
last(succ.(Ast::NotExpr).getOperand(), pred, c) and
80-
completion.(BooleanCompletion).getDual() = c
81-
or
82-
last(succ.(Ast::LogicalAndExpr).getAnOperand(), pred, c) and
83-
completion = c
87+
child = parent.(Ast::LogicalAndExpr).getAnOperand()
8488
or
85-
last(succ.(Ast::LogicalOrExpr).getAnOperand(), pred, c) and
86-
completion = c
89+
child = parent.(Ast::LogicalOrExpr).getAnOperand()
8790
or
88-
last(succ.(Ast::StmtSequence).getLastStmt(), pred, c) and
89-
completion = c
91+
child = parent.(Ast::StmtSequence).getLastStmt()
9092
or
91-
last(succ.(Ast::ConditionalExpr).getBranch(_), pred, c) and
92-
completion = c
93+
child = parent.(Ast::ConditionalExpr).getBranch(_)
9394
)
94-
or
95-
succ(pred, succ, c) and
96-
succ instanceof Ast::WhenClause and
97-
completion = c
9895
}
96+
}
9997

100-
override predicate hasEntryScope(CfgScope scope, AstNode succ) { none() }
98+
int getNextListOrder() { result = 1 }
10199

102-
override predicate hasExit(AstNode pred, AstNode succ, Completion c) {
103-
this.appliesTo(pred) and
100+
private class ConditionalCompletionSplitImpl extends SplitImplementations::ConditionalCompletionSplitting::ConditionalCompletionSplitImpl
101+
{
102+
override predicate hasEntry(AstNode pred, AstNode succ, Completion c) {
103+
super.hasEntry(pred, succ, c)
104+
or
105+
// a non-standard case is needed for `when` clauses
104106
succ(pred, succ, c) and
105-
if c instanceof ConditionalCompletion then completion = c else any()
106-
}
107-
108-
override predicate hasExitScope(CfgScope scope, AstNode last, Completion c) {
109-
this.appliesTo(last) and
110-
succExit(scope, last, c) and
111-
if c instanceof ConditionalCompletion then completion = c else any()
107+
succ instanceof Ast::WhenClause and
108+
c = this.getCompletion()
112109
}
113-
114-
override predicate hasSuccessor(AstNode pred, AstNode succ, Completion c) { none() }
115110
}
116111
}
117112

0 commit comments

Comments
 (0)