Corentin Hervaud
06/02/2026, 6:36 AMkotlin source set via the generated.sources plugin API.
I'm now at the point where there are a handful of things I can't implement cleanly without a bit more from the Kotlin Toolchain side. I will list them as responses in the thread.
Thanks for the great tooling!Corentin Hervaud
06/02/2026, 6:37 AMapiTests=false, modelTests=false) because the Kotlin Toolchain picks up the entire output directory as a single source set, and the test files fail to compile (no JUnit on the main classpath). Is there a way to declare a generated test source set from a plugin, or is that something on the roadmap?
2. Optional @Input paths
Some generator settings are optional file/directory paths โ for example templateDir (custom Mustache templates), configFile (external JSON config), or ignoreFileOverride. I'd like to mark these as @Input so the toolchain can track them for up-to-date checks, but nullable Path? annotated with @Input doesn't seem to be supported. What's the recommended way to handle optional path inputs in a task action?
3. Publishing
I know plugin publishing support is on the way โ I'd love to be an early tester when it's ready! Is there anything I can do now to prepare, or a channel/issue to follow to stay in the loop?Fedor Ihnatkevich
06/02/2026, 8:28 AMFedor Ihnatkevich
06/02/2026, 8:29 AM@Input Path? are supported. If something goes wrong, that's probably a bug then. Can you describe what happens if you try to use a nullable input path?Fedor Ihnatkevich
06/02/2026, 8:34 AMfragment block, like this:
generated:
sources:
- directory: ${<your-dir-ref>}
fragment:
isTest: true
You can try it out, see if this works for you.mbonnin
06/02/2026, 8:58 AMCorentin Hervaud
06/02/2026, 9:39 AMCorentin Hervaud
06/02/2026, 6:34 PMgenerated.sources.fragment in my plugin.
Currently, the plugin is generating a bunch of files in the ${taskOutputDir} : build.gradle, src/main/kotlin/..., src/test/kotlin/....
But I can't make specify a "sub directory" in generated.sources.directory.
I tried doing
generated:
sources:
- language: kotlin
directory: ${tasks.generateOpenAPI.action.outputDir}/src/main/kotlin/
But this give me the following error from the kotlin-toolchain:
The `directory` path `/Users/corentin/dev/openapi-generator-kotlintoolchain-plugin/build/tasks/_sub-package_generateOpenAPI@openapi-generator/src/main/kotlin` in must be an `@Output` of some task registered in this plugin
What am I supposed to do in this case?
PS: Just so you know, I can't find any doc on the website about the generated.sources.fragmentCorentin Hervaud
06/02/2026, 6:44 PM@Input part
Making the Path nullable in the @TaskAction @Input inputSpec: Path?, implies that I also make it nullable on the settings class
@Configurable
interface Settings {
val inputSpec: String?
}
And this fails with the following:
The value of type `string | null` cannot be used in string interpolationFedor Ihnatkevich
06/03/2026, 9:04 AMFor the test source sets
I have trouble using thein my plugin.generated.sources.fragment
Currently, the plugin is generating a bunch of files in the:${taskOutputDir},build.gradle,src/main/kotlin/....src/test/kotlin/...
But I can't make specify a "sub directory" inI see, thanks for reporting back! Yes, that is currently a UX limitation, that the.generated.sources.directory
generated.sources.directory must be exactly one of the @Output paths from the task, not a child path. The way to work around it now is to pass different @Input path parameters for generated directories, and then the generated.sources will allow referencing them.
So basically instead of
tasks:
myTask:
action: !someAction
outputDir: ${taskOutputDir}
generated:
sources:
- directory: ${tasks.myTask.action.outputDir}/kotlin
sources:
- directory: ${tasks.myTask.action.outputDir}/java
language: java
you will have
tasks:
myTask:
action: !someAction
kotlinOutputDir: ${taskOutputDir}/kotlin
javaOutputDir: ${taskOutputDir}/java
generated:
sources:
- directory: ${tasks.myTask.action.kotlinOutputDir}
sources:
- directory: ${tasks.myTask.action.javaOutputDir}
language: java
We are aware of this friction point, we might improve this aspect later!Fedor Ihnatkevich
06/03/2026, 9:09 AM@Input part
> Making the Path nullable in the @TaskAction @Input inputSpec: Path?, implies that I also make it nullable on the settings class
> @Configurable
> interface Settings {
> val inputSpec: String?
> }
> And this fails with the following:
> The value of type `string | null` cannot be used in string interpolation
So the @Input path indeed can be nullable. What is not valid though, judging by the error message you get, is to use nullable string in a string/path interpolation. I'd very much like to see what exactly are you trying to do there, so I can understand what we can implement to enable use-cases like yours if there is no nice workaround possible. Can you share more snippets/code around this?Corentin Hervaud
06/03/2026, 9:34 PMconfigFile setting, which is nullable in the Settings interface (as a String) and in the openApiGenerate @TaskAction (as a Path)Corentin Hervaud
06/09/2026, 10:18 AMFedor Ihnatkevich
06/09/2026, 4:42 PMconfigFile: String? in the settings, configFile: Path? in the task, configFile: ${pluginSettings.configFile} in the plugin.yaml) then I get `The value of type string | null cannot be assigned to the type `path | null``
There is no string interpolation involved. If I append, say, / to the end (like this: configFile: ${pluginSettings.configFile}/ ) - then it becomes a string interpolation and I indeed see the error that you mentioned.
So, nullable values can't be used in string-interpolation - it's the desired behavior for now. Unless we choose to introduce cascading-nullability into the type-system, or some tools like that. But it hasn't been designed yet and we need to consider cases and options there.
Now, to the underlying problem that I see. According to our own simple "type-system" on top of YAML, string is not assignable to path, as it may contain invalid characters, wrong separators, etc. But this doesn't hold for string interpolations, so myPath: ${myString} is wrong, but myPath: ${myString}/ is suddenly okay. So, currently, one indeed can use string interpolation to assign to a path property (not in the nullable case though, see above). This is a "gray zone" in the type-system and is inconsistent, so it has to be fixed.
I've filed the issue about it - you can read more there - AMPER-5424 inconsistent: string is not assignable to path but string interpolation is.Fedor Ihnatkevich
06/09/2026, 4:43 PMconfigFile a Path in the plugin settings? Then we avoid this whole shady string/path conversion story.Corentin Hervaud
06/09/2026, 7:46 PMwhat prevents you from making yourIndeed I will ๐ I just didn't knew it was possible ๐ Because I followed the doc to write my settings file and in this doc, theaconfigFilein the plugin settings?Path
Path parameter is set as a String in the settings class, so I did the sameFedor Ihnatkevich
06/09/2026, 8:28 PMBecause I followed the doc to write my settings fileI see. We used
string in the doc just for the file name, because you can't specify relative paths or path components (like just a file name) for now (AMPER-5403). But for paths that are expected to be specified fully by the client, you can use path no problem.
Again, thanks for the feedback, I'll try to make the docs more clear about this!