Skip to content

Commit c07cc2e

Browse files
authored
Improve config syntax errors (nextflow-io#6721)
1 parent 51e0e03 commit c07cc2e

File tree

5 files changed

+44
-3
lines changed

5 files changed

+44
-3
lines changed

modules/nf-lang/src/main/java/nextflow/config/control/ConfigResolveVisitor.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.util.Collections;
1919
import java.util.List;
20+
import java.util.regex.Pattern;
2021

2122
import nextflow.config.ast.ConfigAssignNode;
2223
import nextflow.config.ast.ConfigIncludeNode;
@@ -78,6 +79,8 @@ public void visitConfigInclude(ConfigIncludeNode node) {
7879

7980
private class DynamicVariablesVisitor extends ConfigVisitorSupport {
8081

82+
private static final Pattern ENV_VAR_NAME = Pattern.compile("[A-Z_]+[A-Z0-9_]*");
83+
8184
@Override
8285
protected SourceUnit getSourceUnit() {
8386
return sourceUnit;
@@ -86,8 +89,12 @@ protected SourceUnit getSourceUnit() {
8689
@Override
8790
public void visitVariableExpression(VariableExpression node) {
8891
var variable = node.getAccessedVariable();
89-
if( variable instanceof DynamicVariable )
90-
resolver.addError("`" + node.getName() + "` is not defined", node);
92+
if( variable instanceof DynamicVariable ) {
93+
var message = "`" + node.getName() + "` is not defined";
94+
if( ENV_VAR_NAME.matcher(variable.getName()).matches() )
95+
message += " (hint: use `env('...')` to access environment variable)";
96+
resolver.addError(message, node);
97+
}
9198
}
9299
}
93100

modules/nf-lang/src/main/java/nextflow/config/parser/ConfigAstBuilder.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ private ConfigStatement configSelector(ConfigSelectorContext ctx) {
316316
var target = configPrimary(ctx.target);
317317
var statements = ctx.configBlockStatement().stream()
318318
.map(this::configBlockStatement)
319+
.filter(stmt -> stmt != null)
319320
.toList();
320321
return new ConfigBlockNode(kind, target, statements);
321322
}

modules/nf-lang/src/main/java/nextflow/script/parser/ScriptAstBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ private ModuleNode compilationUnit(CompilationUnitContext ctx) {
232232
if( hasDeclarations ) {
233233
for( var stmt : statements ) {
234234
if( !(stmt instanceof InvalidDeclaration) )
235-
collectSyntaxError(new SyntaxException("Statements cannot be mixed with script declarations -- move statements into a process or workflow", stmt));
235+
collectSyntaxError(new SyntaxException("Statements cannot be mixed with script declarations -- move statements into a process, workflow, or function", stmt));
236236
}
237237
}
238238

modules/nf-lang/src/test/groovy/nextflow/config/control/ConfigResolveTest.groovy

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ class ConfigResolveTest extends Specification {
6161
errors[0].getStartLine() == 1
6262
errors[0].getStartColumn() == 36
6363
errors[0].getOriginalMessage() == '`process` is not defined'
64+
65+
when:
66+
errors = check(
67+
'''\
68+
process.clusterOptions = "--cpus $PROCESS_CPUS"
69+
'''
70+
)
71+
then:
72+
errors.size() == 1
73+
errors[0].getStartLine() == 1
74+
errors[0].getStartColumn() == 34
75+
errors[0].getOriginalMessage() == "`PROCESS_CPUS` is not defined (hint: use `env('...')` to access environment variable)"
6476
}
6577

6678
def 'should report an error for an invalid config include' () {

modules/nf-lang/src/test/groovy/nextflow/config/parser/ConfigAstBuilderTest.groovy

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,27 @@ class ConfigAstBuilderTest extends Specification {
7373
errors[0].getStartColumn() == 1
7474
errors[0].getOriginalMessage() == "If statements cannot be mixed with config statements"
7575

76+
when:
77+
errors = check(
78+
'''\
79+
process {
80+
withName: 'HELLO' {
81+
if( true ) {
82+
cpus = 8
83+
}
84+
else {
85+
cpus = 4
86+
}
87+
}
88+
}
89+
'''
90+
)
91+
then:
92+
errors.size() == 1
93+
errors[0].getStartLine() == 3
94+
errors[0].getStartColumn() == 9
95+
errors[0].getOriginalMessage() == "If statements cannot be mixed with config statements"
96+
7697
when:
7798
errors = check(
7899
'''\

0 commit comments

Comments
 (0)