From 2e2c0da547eca07ca2cf1da818cca9c8560d86da Mon Sep 17 00:00:00 2001 From: Ben Sherman Date: Fri, 14 Nov 2025 10:40:41 -0600 Subject: [PATCH] Fix false error with task ext blocks in strict syntax Signed-off-by: Ben Sherman --- .../nextflow/config/ConfigValidator.groovy | 3 --- .../config/parser/v2/ConfigDsl.groovy | 6 ++++- .../nf-lang/src/main/antlr/ConfigParser.g4 | 2 +- .../config/parser/ConfigAstBuilder.java | 4 ++-- tests/checks/.IGNORE-PARSER-V2 | 1 + tests/checks/task-ext-block.nf/.checks | 7 ++++++ tests/task-ext-block.config | 22 +++++++++++++++++++ tests/task-ext-block.nf | 15 +++++++++++++ 8 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 tests/checks/task-ext-block.nf/.checks create mode 100644 tests/task-ext-block.config create mode 100644 tests/task-ext-block.nf diff --git a/modules/nextflow/src/main/groovy/nextflow/config/ConfigValidator.groovy b/modules/nextflow/src/main/groovy/nextflow/config/ConfigValidator.groovy index 78988e6f78..c83e40acbb 100644 --- a/modules/nextflow/src/main/groovy/nextflow/config/ConfigValidator.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/config/ConfigValidator.groovy @@ -106,16 +106,13 @@ class ConfigValidator { names.clear() if( value instanceof Map ) { - log.debug "validate config block ${names}" if( isSelector(key) ) names.removeLast() - log.debug " is map option ${isMapOption(names)}" if( isMapOption(names) ) continue validate(value, names) } else { - log.debug "validate config option ${names}" validateOption(names) } } diff --git a/modules/nextflow/src/main/groovy/nextflow/config/parser/v2/ConfigDsl.groovy b/modules/nextflow/src/main/groovy/nextflow/config/parser/v2/ConfigDsl.groovy index 96e01808c9..aeed4ec418 100644 --- a/modules/nextflow/src/main/groovy/nextflow/config/parser/v2/ConfigDsl.groovy +++ b/modules/nextflow/src/main/groovy/nextflow/config/parser/v2/ConfigDsl.groovy @@ -152,7 +152,11 @@ class ConfigDsl extends Script { if( names.size() == 1 && names.first() == 'plugins' ) return new PluginsDsl(this) - if( names.size() == 1 && names.first() == 'process' ) + final relativeNames = names.size() == 3 && names.first() == 'profiles' + ? List.of(names.last()) + : names + + if( relativeNames.size() == 1 && relativeNames.last() == 'process' ) return new ProcessDsl(this, names) if( names.size() == 1 && names.first() == 'profiles' ) diff --git a/modules/nf-lang/src/main/antlr/ConfigParser.g4 b/modules/nf-lang/src/main/antlr/ConfigParser.g4 index 5f30cd59fa..8fefc6099d 100644 --- a/modules/nf-lang/src/main/antlr/ConfigParser.g4 +++ b/modules/nf-lang/src/main/antlr/ConfigParser.g4 @@ -147,7 +147,7 @@ configBlockStatement ; configSelector - : kind=Identifier COLON target=configPrimary nls LBRACE nls (configAssign (sep configAssign)* sep?)? RBRACE + : kind=Identifier COLON target=configPrimary nls LBRACE nls (configBlockStatement (sep configBlockStatement)* sep?)? RBRACE ; // -- config "apply" block (e.g. plugins) diff --git a/modules/nf-lang/src/main/java/nextflow/config/parser/ConfigAstBuilder.java b/modules/nf-lang/src/main/java/nextflow/config/parser/ConfigAstBuilder.java index 2e02796360..b541ebba72 100644 --- a/modules/nf-lang/src/main/java/nextflow/config/parser/ConfigAstBuilder.java +++ b/modules/nf-lang/src/main/java/nextflow/config/parser/ConfigAstBuilder.java @@ -314,8 +314,8 @@ else if( ctx instanceof ConfigInvalidBlockStmtAltContext ciac ) { private ConfigStatement configSelector(ConfigSelectorContext ctx) { var kind = ctx.kind.getText(); var target = configPrimary(ctx.target); - var statements = ctx.configAssign().stream() - .map(this::configAssign) + var statements = ctx.configBlockStatement().stream() + .map(this::configBlockStatement) .toList(); return new ConfigBlockNode(kind, target, statements); } diff --git a/tests/checks/.IGNORE-PARSER-V2 b/tests/checks/.IGNORE-PARSER-V2 index da67ec4fdc..5f35801f98 100644 --- a/tests/checks/.IGNORE-PARSER-V2 +++ b/tests/checks/.IGNORE-PARSER-V2 @@ -7,6 +7,7 @@ eval-out-typed.nf nullable-path.nf output-dsl.nf params-dsl.nf +task-ext-block.nf topic-channel-typed.nf type-annotations.nf workflow-oncomplete-v2.nf \ No newline at end of file diff --git a/tests/checks/task-ext-block.nf/.checks b/tests/checks/task-ext-block.nf/.checks new file mode 100644 index 0000000000..3188e3b1d2 --- /dev/null +++ b/tests/checks/task-ext-block.nf/.checks @@ -0,0 +1,7 @@ +set -e + +echo '' +$NXF_RUN -c ../../task-ext-block.config -profile test | tee stdout + +grep 'FOO: \[foo:foo\]' stdout +grep 'BAR: \[bar:bar\]' stdout diff --git a/tests/task-ext-block.config b/tests/task-ext-block.config new file mode 100644 index 0000000000..1354da8510 --- /dev/null +++ b/tests/task-ext-block.config @@ -0,0 +1,22 @@ + +profiles { + test { + process { + withName:'FOO' { + ext { + foo = 'foo' + } + } + withName:'BAR' { + ext { + bar = 'bar' + } + } + withName:'DOES_NOT_MATCH_ANYTHING' { + ext { + test = 'test' + } + } + } + } +} diff --git a/tests/task-ext-block.nf b/tests/task-ext-block.nf new file mode 100644 index 0000000000..d56e60dadd --- /dev/null +++ b/tests/task-ext-block.nf @@ -0,0 +1,15 @@ + +workflow { + FOO() + BAR() +} + +process FOO { + exec: + println "FOO: ${task.ext}" +} + +process BAR { + exec: + println "BAR: ${task.ext}" +}