Skip to content

Commit 8985078

Browse files
committed
Support ternary expression
1 parent c2faa30 commit 8985078

3 files changed

Lines changed: 112 additions & 28 deletions

File tree

src/main/java/nextflow/lsp/services/script/dag/DataflowVisitor.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,17 @@
3535
import nextflow.script.ast.WorkflowNode;
3636
import org.codehaus.groovy.ast.ASTNode;
3737
import org.codehaus.groovy.ast.MethodNode;
38-
import org.codehaus.groovy.ast.expr.*;
39-
import org.codehaus.groovy.ast.stmt.*;
38+
import org.codehaus.groovy.ast.expr.BinaryExpression;
39+
import org.codehaus.groovy.ast.expr.ClosureExpression;
40+
import org.codehaus.groovy.ast.expr.DeclarationExpression;
41+
import org.codehaus.groovy.ast.expr.Expression;
42+
import org.codehaus.groovy.ast.expr.MethodCallExpression;
43+
import org.codehaus.groovy.ast.expr.PropertyExpression;
44+
import org.codehaus.groovy.ast.expr.TernaryExpression;
45+
import org.codehaus.groovy.ast.expr.TupleExpression;
46+
import org.codehaus.groovy.ast.expr.VariableExpression;
47+
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
48+
import org.codehaus.groovy.ast.stmt.IfStatement;
4049
import org.codehaus.groovy.control.SourceUnit;
4150
import org.codehaus.groovy.syntax.Types;
4251

@@ -64,7 +73,7 @@ public DataflowVisitor(SourceUnit sourceUnit, ScriptAstCache ast) {
6473
this.sourceUnit = sourceUnit;
6574
this.ast = ast;
6675

67-
stackPreds.add(new HashSet<>());
76+
stackPreds.push(new HashSet<>());
6877
}
6978

7079
@Override
@@ -160,16 +169,15 @@ private void visitWorkflowPublishers(WorkflowNode node, Map<String,Node> result)
160169
@Override
161170
public void visitIfElse(IfStatement node) {
162171
// visit the conditional expression
163-
var preds = visitWithPreds(node.getBooleanExpression());
164-
var controlDn = addNode("", Node.Type.CONTROL, null, preds);
172+
var controlPreds = visitWithPreds(node.getBooleanExpression());
173+
var controlDn = current.addNode("", Node.Type.CONTROL, null, controlPreds);
165174

166175
// visit the if branch
167176
vc.pushScope();
168177
current.pushSubgraph(controlDn);
169178
visitWithPreds(node.getIfBlock());
170-
179+
current.popSubgraph();
171180
var ifScope = vc.popScope();
172-
var ifSubgraph = current.popSubgraph();
173181

174182
// visit the else branch
175183
Map<String,Variable> elseScope;
@@ -178,9 +186,8 @@ public void visitIfElse(IfStatement node) {
178186
vc.pushScope();
179187
current.pushSubgraph(controlDn);
180188
visitWithPreds(node.getElseBlock());
181-
182-
elseScope = vc.popScope();
183189
current.popSubgraph();
190+
elseScope = vc.popScope();
184191
}
185192
else {
186193
// if there is no else branch, then the set of active symbols
@@ -291,6 +298,23 @@ public void visitDeclarationExpression(DeclarationExpression node) {
291298
visitAssignment(node, true);
292299
}
293300

301+
@Override
302+
public void visitTernaryExpression(TernaryExpression node) {
303+
var controlPreds = visitWithPreds(node.getBooleanExpression());
304+
var controlDn = current.addNode("", Node.Type.CONTROL, null, controlPreds);
305+
306+
current.pushSubgraph(controlDn);
307+
var truePreds = visitWithPreds(node.getTrueExpression());
308+
current.popSubgraph();
309+
310+
current.pushSubgraph(controlDn);
311+
var falsePreds = visitWithPreds(node.getFalseExpression());
312+
current.popSubgraph();
313+
314+
currentPreds().addAll(truePreds);
315+
currentPreds().addAll(falsePreds);
316+
}
317+
294318
@Override
295319
public void visitClosureExpression(ClosureExpression node) {
296320
// skip closures since they can't contain dataflow logic
@@ -429,7 +453,7 @@ private Node getSymbol(String name) {
429453
return null;
430454
if( preds.size() == 1 )
431455
return preds.iterator().next();
432-
return addNode(name, Node.Type.NAME, null, preds);
456+
return current.addNode(name, Node.Type.NAME, null, preds);
433457
}
434458

435459
private Set<Node> currentPreds() {

src/main/java/nextflow/lsp/services/script/dag/MermaidRenderer.java

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ public String render(String name, Graph graph) {
8181
}
8282

8383
// render nodes
84-
var subgraphEdges = renderSubgraph(graph.peekSubgraph());
84+
var allSubgraphs = new HashSet<Subgraph>();
85+
renderSubgraph(graph.peekSubgraph(), allSubgraphs);
8586

8687
// render outputs
8788
if( outputs.size() > 0 ) {
@@ -118,8 +119,10 @@ public String render(String name, Graph graph) {
118119
append("v%d --> v%d", dnPred.id, dn.id);
119120
}
120121

121-
for( var edge : subgraphEdges ) {
122-
append("v%d --> s%d", edge.source(), edge.target());
122+
// render subgraph edges
123+
for( var subgraph : allSubgraphs ) {
124+
for( var dnPred : subgraph.preds )
125+
append("v%d --> s%d", dnPred.id, subgraph.id);
123126
}
124127

125128
decIndent();
@@ -129,11 +132,14 @@ public String render(String name, Graph graph) {
129132
}
130133

131134
/**
132-
* Render a subgraph and collect all incident edges.
135+
* Render a subgraph and collect all child subgraphs.
133136
*
134137
* @param subgraph
138+
* @param allSubgraphs
135139
*/
136-
private Set<Edge> renderSubgraph(Subgraph subgraph) {
140+
private void renderSubgraph(Subgraph subgraph, Set<Subgraph> allSubgraphs) {
141+
allSubgraphs.add(subgraph);
142+
137143
if( subgraph.id > 0 ) {
138144
append("subgraph s%d[\" \"]", subgraph.id);
139145
incIndent();
@@ -153,23 +159,14 @@ private Set<Edge> renderSubgraph(Subgraph subgraph) {
153159
append("click v%d href \"%s\" _blank", dn.id, dn.uri.toString());
154160
}
155161

156-
// render subgraphs and collect incident edges
157-
var incidentEdges = new HashSet<Edge>();
158-
for( var dnPred : subgraph.preds ) {
159-
incidentEdges.add(new Edge(dnPred.id, subgraph.id));
160-
}
161-
162-
for( var s : subgraph.subgraphs ) {
163-
var edges = renderSubgraph(s);
164-
incidentEdges.addAll(edges);
165-
}
162+
// render subgraphs
163+
for( var s : subgraph.subgraphs )
164+
renderSubgraph(s, allSubgraphs);
166165

167166
if( subgraph.id > 0 ) {
168167
decIndent();
169168
append("end");
170169
}
171-
172-
return incidentEdges;
173170
}
174171

175172
/**

src/test/groovy/nextflow/lsp/services/script/dag/PreviewDagTest.groovy

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class PreviewDagTest extends Specification {
3535
return true
3636
}
3737

38-
def 'should render the DAG preview for a workflow' () {
38+
def 'should handle an if-else statement' () {
3939
given:
4040
def service = getScriptService()
4141
def uri = getUri('main.nf')
@@ -100,6 +100,69 @@ class PreviewDagTest extends Specification {
100100
)
101101
}
102102

103+
def 'should handle a ternary expression' () {
104+
given:
105+
def service = getScriptService()
106+
def uri = getUri('main.nf')
107+
108+
expect:
109+
checkDagPreview(service, uri,
110+
'''\
111+
workflow {
112+
echo = params.echo
113+
? TOUCH(params.echo)
114+
: DEFAULT()
115+
APPEND(echo)
116+
}
117+
118+
process TOUCH {
119+
input:
120+
val x
121+
122+
script:
123+
true
124+
}
125+
126+
process DEFAULT {
127+
true
128+
}
129+
130+
process APPEND {
131+
input:
132+
val x
133+
134+
script:
135+
true
136+
}
137+
''',
138+
"""\
139+
flowchart TB
140+
subgraph " "
141+
subgraph params
142+
v0["echo"]
143+
end
144+
v1{ }
145+
v5([APPEND])
146+
click v5 href "$uri" _blank
147+
subgraph s1[" "]
148+
v2([TOUCH])
149+
click v2 href "$uri" _blank
150+
end
151+
subgraph s2[" "]
152+
v3([DEFAULT])
153+
click v3 href "$uri" _blank
154+
end
155+
v0 --> v1
156+
v0 --> v2
157+
v2 --> v5
158+
v3 --> v5
159+
v1 --> s1
160+
v1 --> s2
161+
end
162+
"""
163+
)
164+
}
165+
103166
def 'should handle variable reassignment in an if statement' () {
104167
given:
105168
def service = getScriptService()

0 commit comments

Comments
 (0)