访问顶级的自定义 gradle 任务失败,并显示“构造函数......应该用@Inject 注释”

Pet*_*rch 2 gradle kotlin

我正在尝试创建一个可重用的 gradle 任务,该任务从顶层访问某些内容。这有效:

val foo = 42

tasks.register("foosimple") {
    println(foo)
}
Run Code Online (Sandbox Code Playgroud)

但是使用来自开发自定义 Gradle 任务类型的修改示例不会:

open class Foo : DefaultTask() {
    @TaskAction
    fun foo() {
        println(foo)
    }
}
tasks.register<Foo>("foo")
Run Code Online (Sandbox Code Playgroud)

失败了:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'keycloak-spi'.
> Could not create task ':foo'.
   > Could not create task of type 'Foo'.
      > The constructor for type Build_gradle.Foo should be annotated with @Inject.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
Run Code Online (Sandbox Code Playgroud)

有人可以阐明我在这里做错了什么吗?如果我foo()println(42)它替换的内容,当然。但我实际上从顶层访问一些东西......

更多细节

--stacktrace 对我没有帮助:

* Exception is:
org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'keycloak-spi'.
        at org.gradle.execution.TaskNameResolver.getExistingTask(TaskNameResolver.java:116)
        at org.gradle.execution.TaskNameResolver.access$000(TaskNameResolver.java:32)
        at org.gradle.execution.TaskNameResolver$MultiProjectTaskSelectionResult.collect(TaskNameResolver.java:177)
        at org.gradle.execution.TaskNameResolver$MultiProjectTaskSelectionResult.collectTasks(TaskNameResolver.java:169)
        at org.gradle.execution.TaskNameResolver.selectWithName(TaskNameResolver.java:55)
        at org.gradle.execution.TaskSelector.getSelection(TaskSelector.java:104)
        at org.gradle.execution.TaskSelector.getSelection(TaskSelector.java:82)
        at org.gradle.execution.commandline.CommandLineTaskParser.parseTasks(CommandLineTaskParser.java:42)
Run Code Online (Sandbox Code Playgroud)

因此,我尝试@Inject在构造函数上添加一个注释,但显然,就像我一样,gradle 不知道@Inject

open class Foo @Inject constructor()  : DefaultTask() {
    @TaskAction
    fun foo() {
        println(foo)
    }
}
Run Code Online (Sandbox Code Playgroud)

失败了:

Line 70: class Foo @Inject constructor() {}
                  ^ Unresolved reference: Inject
Run Code Online (Sandbox Code Playgroud)

这是 Intellij 的唯一建议:

open class Foo @javax.inject.Inject constructor()  : DefaultTask() {
    @TaskAction
    fun foo() {
        println(foo)
    }
}
Run Code Online (Sandbox Code Playgroud)

现在它失败了:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'keycloak-spi'.
> Could not create task ':foo'.
   > Could not create task of type 'Foo'.
      > 0
Run Code Online (Sandbox Code Playgroud)

所以现在它接受了@Inject注释,但仍然不起作用。我现在放弃并问你们......

Daw*_*tel 5

Foo每次使用构建脚本中的变量时,Kotlin 编译器都会向生成的构造函数秘密添加一个参数。该参数是对封闭构建脚本的引用。

因此,任务类没有无参数构造函数,Gradle 假设依赖注入应该开始。但它不能,因为生成的构造函数Foo(BuildScript_XXX)没有@Inject注释。

如果要在任务中使用脚本变量,则应使用输入属性,例如:

val foo = 42

open class Foo : DefaultTask() {
    @Input
    var fooToPrint: Int = 0

    @TaskAction
    fun foo() {
        println(fooToPrint)
    }
}
tasks.register<Foo>("foo") {
    fooToPrint = foo
}
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的回答。这是有道理的,但报告的错误可能会更好。Gradle 实在太神奇了。 (2认同)
  • Gradle 功能强大,这也意味着您很容易搬起石头砸自己的脚。事实上,错误消息并不是很有帮助。@PeterV.Mørch 我的答案中是否缺少任何内容,导致您无法接受它? (2认同)