Skip to content

Commit bd8de5c

Browse files
authored
Fix optional param in params block (#6657)
1 parent 7b38602 commit bd8de5c

File tree

3 files changed

+46
-27
lines changed

3 files changed

+46
-27
lines changed

modules/nextflow/src/main/groovy/nextflow/script/ParamsDsl.groovy

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,8 @@ class ParamsDsl {
3636

3737
private Map<String,Param> declarations = [:]
3838

39-
void declare(String name, Class type) {
40-
declarations[name] = new Param(name, type, Optional.empty())
41-
}
42-
43-
void declare(String name, Class type, Object defaultValue) {
44-
declarations[name] = new Param(name, type, Optional.of(defaultValue))
39+
void declare(String name, Class type, boolean optional, Object defaultValue = null) {
40+
declarations[name] = new Param(name, type, optional, defaultValue)
4541
}
4642

4743
void apply(Session session) {
@@ -56,17 +52,24 @@ class ParamsDsl {
5652
final params = new HashMap<String,?>()
5753
for( final name : declarations.keySet() ) {
5854
final decl = declarations[name]
59-
if( cliParams.containsKey(name) )
55+
if( cliParams.containsKey(name) ) {
6056
params[name] = resolveFromCli(decl, cliParams[name])
61-
else if( configParams.containsKey(name) )
57+
}
58+
else if( configParams.containsKey(name) ) {
6259
params[name] = resolveFromCode(decl, configParams[name])
63-
else if( decl.defaultValue.isPresent() )
64-
params[name] = resolveFromCode(decl, decl.defaultValue.get())
65-
else
60+
}
61+
else if( decl.defaultValue != null ) {
62+
params[name] = resolveFromCode(decl, decl.defaultValue)
63+
}
64+
else if( decl.optional ) {
65+
params[name] = null
66+
}
67+
else {
6668
throw new ScriptRuntimeException("Parameter `$name` is required but was not specified on the command line, params file, or config")
69+
}
6770

68-
final actualType = params[name].getClass()
69-
if( !isAssignableFrom(decl.type, actualType) )
71+
final actualType = params[name]?.getClass()
72+
if( actualType != null && !isAssignableFrom(decl.type, actualType) )
7073
throw new ScriptRuntimeException("Parameter `$name` with type ${Types.getName(decl.type)} cannot be assigned to ${params[name]} [${Types.getName(actualType)}]")
7174
}
7275

@@ -130,7 +133,8 @@ class ParamsDsl {
130133
private static class Param {
131134
String name
132135
Class type
133-
Optional<?> defaultValue
136+
boolean optional
137+
Object defaultValue
134138
}
135139

136140
}

modules/nextflow/src/test/groovy/nextflow/script/ParamsDslTest.groovy

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,27 @@ class ParamsDslTest extends Specification {
2222

2323
when:
2424
def dsl = new ParamsDsl()
25-
dsl.declare('input', Path)
26-
dsl.declare('chunk_size', Integer, 1)
27-
dsl.declare('save_intermeds', Boolean, false)
25+
dsl.declare('input', Path, false)
26+
dsl.declare('chunk_size', Integer, false, 1)
27+
dsl.declare('save_intermeds', Boolean, false, false)
2828
dsl.apply(session)
2929
then:
3030
session.binding.getParams() == [input: FileHelper.asPath('./data'), chunk_size: 3, save_intermeds: false, outdir: 'results']
3131
}
3232

33+
def 'should allow optional param'() {
34+
given:
35+
def session = new Session()
36+
session.init(null)
37+
38+
when:
39+
def dsl = new ParamsDsl()
40+
dsl.declare('input', Path, true)
41+
dsl.apply(session)
42+
then:
43+
noExceptionThrown()
44+
}
45+
3346
def 'should report error for missing required param'() {
3447
given:
3548
def cliParams = [:]
@@ -39,8 +52,8 @@ class ParamsDslTest extends Specification {
3952

4053
when:
4154
def dsl = new ParamsDsl()
42-
dsl.declare('input', Path)
43-
dsl.declare('save_intermeds', Boolean, false)
55+
dsl.declare('input', Path, false)
56+
dsl.declare('save_intermeds', Boolean, false, false)
4457
dsl.apply(session)
4558
then:
4659
def e = thrown(ScriptRuntimeException)
@@ -56,8 +69,8 @@ class ParamsDslTest extends Specification {
5669

5770
when:
5871
def dsl = new ParamsDsl()
59-
dsl.declare('input', Path)
60-
dsl.declare('save_intermeds', Boolean, false)
72+
dsl.declare('input', Path, false)
73+
dsl.declare('save_intermeds', Boolean, false, false)
6174
dsl.apply(session)
6275
then:
6376
def e = thrown(ScriptRuntimeException)
@@ -73,8 +86,8 @@ class ParamsDslTest extends Specification {
7386

7487
when:
7588
def dsl = new ParamsDsl()
76-
dsl.declare('input', Path)
77-
dsl.declare('save_intermeds', Boolean, false)
89+
dsl.declare('input', Path, false)
90+
dsl.declare('save_intermeds', Boolean, false, false)
7891
dsl.apply(session)
7992
then:
8093
def e = thrown(ScriptRuntimeException)
@@ -89,7 +102,7 @@ class ParamsDslTest extends Specification {
89102

90103
when:
91104
def dsl = new ParamsDsl()
92-
dsl.declare('factor', Float, DEF_VALUE)
105+
dsl.declare('factor', Float, false, DEF_VALUE)
93106
dsl.apply(session)
94107
then:
95108
noExceptionThrown()
@@ -106,7 +119,7 @@ class ParamsDslTest extends Specification {
106119

107120
when:
108121
def dsl = new ParamsDsl()
109-
dsl.declare('factor', Integer, DEF_VALUE)
122+
dsl.declare('factor', Integer, false, DEF_VALUE)
110123
dsl.apply(session)
111124
then:
112125
noExceptionThrown()

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Set;
2121
import java.util.stream.Collectors;
2222

23+
import nextflow.script.ast.ASTNodeMarker;
2324
import nextflow.script.ast.AssignmentExpression;
2425
import nextflow.script.ast.FeatureFlagNode;
2526
import nextflow.script.ast.FunctionNode;
@@ -122,9 +123,10 @@ public void visitParams(ParamBlockNode node) {
122123
.map((param) -> {
123124
var name = constX(param.getName());
124125
var type = classX(param.getType());
126+
var optional = constX(type.getNodeMetaData(ASTNodeMarker.NULLABLE) != null);
125127
var arguments = param.hasInitialExpression()
126-
? args(name, type, param.getInitialExpression())
127-
: args(name, type);
128+
? args(name, type, optional, param.getInitialExpression())
129+
: args(name, type, optional);
128130
return stmt(callThisX("declare", arguments));
129131
})
130132
.toList();

0 commit comments

Comments
 (0)