Skip to content

Commit b0cfeb3

Browse files
committed
docs: document ConfigScope discovery rules
The existing example shows the top-level scope class but does not mention registering it in `build.gradle` `extensionPoints`, which is required for the v2 syntax parser to discover and validate the scope. This addition: - Documents the `extensionPoints` registration step - Adds a nested-scope example showing that fields whose type implements `ConfigScope` are auto-discovered and do not need `@ConfigOption` - Notes that `@ConfigOption` fields are not inherited (the validator uses `Class.getDeclaredFields()`) - Notes that the `types` attribute on `@ConfigOption` should only list standard Nextflow types, not runtime classes like `GString` or `Map` These rules can be inferred from the source (`SpecNode.java`, `ConfigValidator.groovy`) or learned from reviewer feedback, but were not previously documented for plugin authors. Signed-off-by: Jonathan Manning <jonathan.manning@seqera.io>
1 parent d30e48d commit b0cfeb3

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

docs/plugins/developing-plugins.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,80 @@ class MyPluginConfig implements ConfigScope {
237237
}
238238
```
239239

240+
The top-level scope must also be registered as an extension point in `build.gradle`, so that Nextflow discovers it when validating the configuration:
241+
242+
```groovy
243+
nextflowPlugin {
244+
// ...
245+
extensionPoints = [
246+
'nextflow.myplugin.MyPluginConfig',
247+
// other extension points...
248+
]
249+
}
250+
```
251+
252+
Configuration options can be grouped by adding a nested `ConfigScope` as a field on the parent scope. Nextflow discovers nested scopes by walking fields whose declared type implements `ConfigScope`, so the field itself does not need a `@ConfigOption` annotation. Only the top-level scope needs `@ScopeName`, a no-arg constructor, and an entry in `extensionPoints`.
253+
254+
```groovy
255+
import java.nio.file.Path
256+
257+
import nextflow.config.spec.ConfigOption
258+
import nextflow.config.spec.ConfigScope
259+
import nextflow.config.spec.ScopeName
260+
import nextflow.script.dsl.Description
261+
262+
@ScopeName('myplugin')
263+
@Description('''
264+
The `myplugin` scope allows you to configure the `nf-myplugin` plugin.
265+
''')
266+
class MyPluginConfig implements ConfigScope {
267+
268+
@Description('''
269+
Configuration for the report file.
270+
''')
271+
final ReportConfig report
272+
273+
// no-arg constructor is required to enable validation of config options
274+
MyPluginConfig() {
275+
}
276+
277+
MyPluginConfig(Map opts) {
278+
this.report = new ReportConfig(opts.report as Map ?: [:])
279+
}
280+
}
281+
282+
@Description('''
283+
The `myplugin.report` scope allows you to configure the report file.
284+
''')
285+
class ReportConfig implements ConfigScope {
286+
287+
@ConfigOption
288+
@Description('''
289+
Path to the report file.
290+
''')
291+
final Path file
292+
293+
@ConfigOption
294+
@Description('''
295+
Whether report generation is enabled.
296+
''')
297+
final Boolean enabled
298+
299+
ReportConfig(Map opts) {
300+
this.file = opts.file as Path
301+
this.enabled = opts.enabled as Boolean ?: true
302+
}
303+
}
304+
```
305+
306+
:::{note}
307+
`@ConfigOption` fields are discovered with `Class.getDeclaredFields()`, which does not include fields inherited from a parent class. Each `ConfigScope` class must therefore declare its options directly. A shared parent class can still provide common logic, such as helper methods that compute default values, but the `@ConfigOption` declarations themselves must live on the concrete scope class.
308+
:::
309+
310+
:::{note}
311+
The `types` attribute on `@ConfigOption` is for declaring that an option accepts more than one type, and should only list [standard Nextflow types](https://docs.seqera.io/nextflow/reference/stdlib-types) (for example, `types=[String, List]`). Avoid using runtime classes such as `GString`, `Number` or `Map` here - they may produce confusing errors in the language server and do not correspond to configurable types.
312+
:::
313+
240314
This approach is not required to support plugin config options. However, it allows Nextflow to recognize plugin definitions when validating the configuration. See {ref}`config-scopes-page` for more information.
241315

242316
### Executors

0 commit comments

Comments
 (0)