Skip to content

Commit 6f6a4cd

Browse files
committed
Check for duplicate process/workflow calls in strict syntax
Signed-off-by: Ben Sherman <[email protected]>
1 parent cfd0f30 commit 6f6a4cd

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

modules/nf-lang/src/main/java/nextflow/script/control/VariableScopeVisitor.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
package nextflow.script.control;
1717

1818
import java.util.HashMap;
19+
import java.util.HashSet;
1920
import java.util.List;
21+
import java.util.Set;
2022

2123
import nextflow.script.ast.ASTNodeMarker;
2224
import nextflow.script.ast.AssignmentExpression;
@@ -168,12 +170,15 @@ public void visitFeatureFlag(FeatureFlagNode node) {
168170
}
169171
}
170172

173+
private Set<String> workflowComponents;
174+
171175
private boolean inWorkflowEmit;
172176

173177
@Override
174178
public void visitWorkflow(WorkflowNode node) {
175179
vsc.pushScope(node.isEntry() ? EntryWorkflowDsl.class : WorkflowDsl.class);
176180
currentDefinition = node;
181+
workflowComponents = new HashSet<String>();
177182
node.setVariableScope(currentScope());
178183

179184
declareWorkflowInputs(node.takes);
@@ -185,6 +190,7 @@ public void visitWorkflow(WorkflowNode node) {
185190
visitWorkflowOutputs(node.emits, "emit");
186191
visitWorkflowOutputs(node.publishers, "output");
187192

193+
workflowComponents = null;
188194
currentDefinition = null;
189195
vsc.popScope();
190196
}
@@ -590,6 +596,14 @@ private void checkDataflowMethod(MethodCallExpression node, MethodNode mn) {
590596
vsc.addError(type + " cannot be called from within a closure", node);
591597
return;
592598
}
599+
if( mn instanceof ProcessNode || mn instanceof WorkflowNode ) {
600+
var name = node.getMethodAsString();
601+
if( workflowComponents.contains(name) ) {
602+
var type = mn instanceof ProcessNode ? "Process" : "Workflow";
603+
vsc.addError(type + " `" + name + "` cannot be called more than once in the same workflow -- use an alias instead", node);
604+
}
605+
workflowComponents.add(name);
606+
}
593607
}
594608

595609
private static String dataflowMethodType(MethodNode mn) {

modules/nf-lang/src/test/groovy/nextflow/script/control/ScriptResolveTest.groovy

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,28 @@ class ScriptResolveTest extends Specification {
256256
errors[0].getStartLine() == 10
257257
errors[0].getStartColumn() == 9
258258
errors[0].getOriginalMessage() == 'Processes cannot be called from within a closure'
259+
260+
when:
261+
errors = check(
262+
'''\
263+
process hello {
264+
script:
265+
"""
266+
echo hello
267+
"""
268+
}
269+
270+
workflow {
271+
hello()
272+
hello()
273+
}
274+
'''
275+
)
276+
then:
277+
errors.size() == 1
278+
errors[0].getStartLine() == 10
279+
errors[0].getStartColumn() == 5
280+
errors[0].getOriginalMessage() == 'Process `hello` cannot be called more than once in the same workflow -- use an alias instead'
259281
}
260282

261283
def 'should report an error for an invalid workflow invocation' () {
@@ -294,6 +316,24 @@ class ScriptResolveTest extends Specification {
294316
errors[0].getStartLine() == 6
295317
errors[0].getStartColumn() == 9
296318
errors[0].getOriginalMessage() == 'Workflows cannot be called from within a closure'
319+
320+
when:
321+
errors = check(
322+
'''\
323+
workflow hello {
324+
}
325+
326+
workflow {
327+
hello()
328+
hello()
329+
}
330+
'''
331+
)
332+
then:
333+
errors.size() == 1
334+
errors[0].getStartLine() == 6
335+
errors[0].getStartColumn() == 5
336+
errors[0].getOriginalMessage() == 'Workflow `hello` cannot be called more than once in the same workflow -- use an alias instead'
297337
}
298338

299339
}

0 commit comments

Comments
 (0)