Custom Gradle Task results in " Class Build_gradle.MyTask is a non-static inner class."

Hi all,

I have generated this custom task within my build.gradle.kts,

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputDirectory
import org.gradle.process.ExecOperations
import org.gradle.api.Action
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import javax.inject.Inject

plugins {
    java
    checkstyle
    jacoco
    id("com.github.spotbugs")
    id("copy-configuration")
}

configurations {
    create("openapi")
}

dependencies {
    gradle.tool("MyBuildTool").forEach { dep -> 
        add("openapi", dep)
    }
}

abstract class OpenApiGenerateModel : DefaultTask() {
    @get:Inject
    abstract val execOperations: ExecOperations

    private val classPath: FileCollection by lazy {
        project.configurations.getByName("openapi")
    }

    @get:InputFile
    abstract val inputSpecFile: RegularFileProperty

    @get:OutputDirectory
    abstract val outputDir: DirectoryProperty

    @get:Input
    abstract val modelPackageName: Property<String>

    @get:InputFile
    abstract val modelsFile: RegularFileProperty

    @get:Input
    abstract val generatePrivateFields: Property<Boolean>

    @get:Input
    abstract val generateResourcePrivateFields: Property<Boolean>

    @TaskAction
    fun generate() {
        project.tasks.register<JavaExec>("generateOpenApiModel") {
            classpath = classPath
            mainClass.set("org.openapitools.codegen.OpenAPIGenerator")
            systemProperty("modelDocs", "true")
            systemProperty("generatePrivateFields", generatePrivateFields.get())
            systemProperty("generateResourcePrivateFields", generateResourcePrivateFields.get())
            args(
                "generate",
                "--generator-name=customName",
                "--input-spec=${inputSpecFile.get().asFile}",
                "--output=${outputDir.get().asFile}",
                "--model-package=${modelPackageName.get()}",
                "--config=${project.path}",
                "--template-dir=${project.path}"
            )
        }.get().exec()
    }
}

tasks.register<OpenApiGenerateModel>("openapi-generate-model") {
    inputSpecFile.set(file("${buildDir}/private/openapi/customModel.yaml"))
    outputDir.set(File(brazilGradle.buildDir, "${buildDir}/models/customDir"))
    modelPackageName.set("model.package.name")
    generatePrivateFields.set(true)
    generateResourcePrivateFields.set(false)
}

During the build, I receive the following error:

Could not determine the dependencies of task ':compileJava'.
> Could not create task ':openapi-generate-model'.
   > Could not create task of type 'OpenApiGenerateModel'.
      > Class Build_gradle.OpenApiGenerateModel is a non-static inner class.

I have written this same script in groovy with no issue, however in kotlin, i always seem to get this error. I have read on stack overflow here that this issue may arise when the task uses a variable or state from outside the class definition. I am not really sure where to go from here, any pointers in the right direction would be very helpful.

The SO post is correct.
Which line causes is is hard to tell.
Your snippet is incomplete as it does not even compile and if I make it compile, the error does not resemble.
If you could provide an MCVE I could maybe tell where the problem is.

But generally it is like you found out.
If that class uses anything from the build script like a local variable or similar, then the class becomes non-static inner class as it needs an instance of the script class to get that variable.
If it does not use something from outside, it is a static inner class and it would work.
You can also simply try to comment everything and then comment in part by part to find the exact line where the problem is.

Besides that, registering a task at execution time from another task (or doing any configuration change is a very bad idea.
And trying to execute a task manually is an even worse idea, as you for example miss the necessary task dependencies and so on.
Besides that using register just to right away do get() also does not make much sense, you could then also right away use create instead.

As you already injected execOperations but did not use it, what you actually want to do is using execOperations.javaExec { ... } instead of registering a new JavaExec task and executing it.