diff --git a/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy b/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy index eccaf1c3aa..c97c70742e 100644 --- a/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/processor/TaskProcessor.groovy @@ -1335,8 +1335,10 @@ class TaskProcessor { value = value instanceof Path ? value.text : value?.toString() case OptionalParam: - if( !value && param instanceof OptionalParam && param.optional ) { - final holder = [] as MissingParam; holder.missing = param + def parentParam = config.outputs[param.index] + if( value == null && parentParam instanceof OptionalParam && parentParam.optional ) { + final holder = [] as MissingParam + holder.missing = param tuples[param.index] = holder break } @@ -1524,7 +1526,13 @@ class TaskProcessor { } } - task.setOutput( param, allFiles.size()==1 ? allFiles[0] : allFiles ) + if( param.optional && allFiles.size() == 0 ) { + task.setOutput( param, null ) + } else if( allFiles.size() == 1 ) { + task.setOutput( param, allFiles[0] ) + } else { + task.setOutput( param, allFiles ) + } } diff --git a/modules/nextflow/src/main/groovy/nextflow/script/params/OptionalParam.groovy b/modules/nextflow/src/main/groovy/nextflow/script/params/OptionalParam.groovy index 9dee49b2b1..aeafbd6216 100644 --- a/modules/nextflow/src/main/groovy/nextflow/script/params/OptionalParam.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/script/params/OptionalParam.groovy @@ -25,7 +25,7 @@ package nextflow.script.params */ trait OptionalParam { - boolean optional + boolean optional = false boolean getOptional() { optional } diff --git a/modules/nextflow/src/main/groovy/nextflow/script/params/TupleOutParam.groovy b/modules/nextflow/src/main/groovy/nextflow/script/params/TupleOutParam.groovy index e3e12aba50..a7b957a2c8 100644 --- a/modules/nextflow/src/main/groovy/nextflow/script/params/TupleOutParam.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/script/params/TupleOutParam.groovy @@ -100,8 +100,10 @@ class TupleOutParam extends BaseOutParam implements OptionalParam { @Override void lazyInit() { super.lazyInit() - inner.each { opt -> - if( opt instanceof FileOutParam ) opt.optional(this.optional) + if ( this.optional ) { + inner.each { opt -> + if( opt instanceof FileOutParam ) opt.optional(this.optional) + } } } diff --git a/modules/nextflow/src/test/groovy/nextflow/script/params/ParamsOutTest.groovy b/modules/nextflow/src/test/groovy/nextflow/script/params/ParamsOutTest.groovy index 3d0f034ba4..9ad19400bf 100644 --- a/modules/nextflow/src/test/groovy/nextflow/script/params/ParamsOutTest.groovy +++ b/modules/nextflow/src/test/groovy/nextflow/script/params/ParamsOutTest.groovy @@ -1207,8 +1207,43 @@ class ParamsOutTest extends Specification { when: def process = parseAndReturnProcess(text, [:]) TupleOutParam out0 = process.config.getOutputs().get(0) + out0.lazyInit() then: out0.inner[0] instanceof FileOutParam + out0.inner[1] instanceof FileOutParam + and: + (out0.inner[0] as FileOutParam).getName() == 'x' + (out0.inner[0] as FileOutParam).getMaxDepth() == 1 + (out0.inner[0] as FileOutParam).getOptional() == false + and: + (out0.inner[1] as FileOutParam).getName() == 'y' + (out0.inner[1] as FileOutParam).getMaxDepth() == 2 + (out0.inner[1] as FileOutParam).getOptional() == true + } + + def 'check whether file optional value is overridden when tuple is optional' () { + given: + def text = ''' + process foo { + output: + tuple path(x,maxDepth:1,optional:false), path(y,maxDepth:2,optional:true) optional false + tuple path(x,maxDepth:2,optional:false), path(y,maxDepth:1,optional:true) optional true + + return '' + } + ''' + + when: + def process = parseAndReturnProcess(text, [:]) + TupleOutParam out0 = process.config.getOutputs().get(0) + TupleOutParam out1 = process.config.getOutputs().get(1) + out0.lazyInit() + out1.lazyInit() + then: + out0.inner[0] instanceof FileOutParam + out0.inner[1] instanceof FileOutParam + out1.inner[0] instanceof FileOutParam + out1.inner[1] instanceof FileOutParam and: (out0.inner[0] as FileOutParam).getName() == 'x' (out0.inner[0] as FileOutParam).getMaxDepth() == 1 @@ -1217,6 +1252,14 @@ class ParamsOutTest extends Specification { (out0.inner[1] as FileOutParam).getName() == 'y' (out0.inner[1] as FileOutParam).getMaxDepth() == 2 (out0.inner[1] as FileOutParam).getOptional() == true + and: + (out1.inner[0] as FileOutParam).getName() == 'x' + (out1.inner[0] as FileOutParam).getMaxDepth() == 2 + (out1.inner[0] as FileOutParam).getOptional() == true + and: + (out1.inner[1] as FileOutParam).getName() == 'y' + (out1.inner[1] as FileOutParam).getMaxDepth() == 1 + (out1.inner[1] as FileOutParam).getOptional() == true }