2013-04-25 9 views
16

ぼんやりと複雑な作業を処理するためにカスタムのgradleプラグインを作成しています。プラグインが適用されるタスクのいくつかを設定するためにプロパティを使用している間、不満を感じています。次のようにこのファイルを使用してから拡張機能をグラデーションで使用すると、プロパティのレイジー評価を処理できますか?

apply plugin: myPlugin 

//Provide properties for the applied plugin 
myPluginProps { 
    message = "Hello" 
} 

//Define a task that uses my custom task directly 
task thisTaskWorksFine(type: MyTask) { 
    input = myPluginProps.message 
} 

//Define a plugin that will apply a task of my custom type 
class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
      input = project.myPluginProps.message 
     } 
    } 
} 

//The extension used by my custom plugin to get input 
class MyPluginExtension { 
    def String message 
} 

//The task used by both the standard build section and the plugin 
class MyTask extends DefaultTask { 
    def String input 

    @TaskAction 
    def action() { 
     println "You gave me this: ${input}" 
    } 
} 

結果は以下のとおりです。

$ gradle thisTaskWorksFine thisTaskWorksIncorrectly 
:thisTaskWorksFine 
You gave me this: Hello 
:thisTaskWorksIncorrectly 
You gave me this: null 

BUILD SUCCESSFUL 

私は、これは非常に予想外であると考えています。私の考えでは、プラグインからタスクを適用し、直接入力すると、同じ入力が与えられたときに同じ出力が得られるはずです。この場合、両方のタスクには入力としてmyPluginProps.messageが与えられますが、プラグインによって適用されるタスクは貪欲で、早期にヌルに評価されます。今除いてかなりきれいに貪欲な評価の問題を解決し

//Define a plugin that will apply a task of my custom type 
class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
      input = { project.myPluginProps.message } 
     } 
    } 
} 

:(?適用フェーズ)

私が見つけた唯一の解決策は、そのようなプラグインのタスクの構成ブロックでクロージャを使用することですクロージャを期待して処理するためにカスタムタスクを修正する必要があります。それはすごく難しいことではありませんが、プラグインが「責任を負う」ため、閉鎖に対処するのはタスクの責任ではないと思います。

私はここで間違って拡張子を使用していますか?あるいは、彼らはちょうど十分ではありませんか?公式の姿勢はwe should use extensionsのように見えますが、私はまだ拡張機能が必要なものを実行できる例は見つけていません。私はクロージャーを使用して前進し、クロージャーと通常のタイプを扱うことができるクロージャー評価とセッターを行う定型文法ゲッターの集合を書くことができますが、それはgroovyの哲学、したがってgradleに非常に似ています。拡張機能を使用して自動的に怠惰な評価を得る方法があるなら、私はとても幸せになれます。

答えて

12

この問題に対する通常の解決策は、大会のマッピングを使用することです:

class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
      conventionMapping.input = { project.myPluginProps.message } 
     } 
    } 
} 

をし、タスクに:

class MyTask extends DefaultTask { 
    def String input 

    @TaskAction 
    def action() { 
     println "You gave me this: ${getInput()}" 
    } 

}

私は明示的にするためにゲッターを使用したことに注意してくださいinput - フィールドを直接参照する場合、コンベンションマッピングは実行されません。

+0

慣習マッピングと慣習の違いはありますか?あなたの答えはかなり滑らかに見えるので、私はほぼ確実にそれを使用しますが、コア開発者の一人は「要するに、拡張機能を使用するだけではコンベンションを使用しない」と言いました。たぶん私はそれを文字通り過ぎ去りました。 –

+2

Peterが言及している[規則(convention)](http://www.gradle.org/docs/current/dsl/org.gradle.api.Project.html#org.gradle.api.Project:convention)は古いメカニズムです拡張のために。違いは、あなたがdsl( 'myPluginProps {message =" Hello "}')を拡張機能で無償で入手し、あなたがそれを慣習で入手しなかったことです。コンベンションとコンベンションのマッピングは2つの異なるもので、[gradle code](https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/groovy/org/gradle/)で内部的に使用されています。 api/plugins/JavaPlugin.java#L131)がたくさんあります。 – erdi

+0

優れています。私の研究では、コンベンションという言葉に言及したすべてのものを覆していたが、それは急いでいた。助けてくれてありがとう! –

13

私の質問hereのPeterの答えは、conventionMapping機能が間違いなく消えることを示しています。それを避けるのが最善です。

遅延設定の問題を解決するためにafterEvaluateを使用すると、私のコードはconventionMappingのアプローチよりもはるかにクリーンになりました。

class MyPlugin implements Plugin<Project> { 
    void apply(Project project) { 
     project.extensions.create('myPluginProps', MyPluginExtension) 

     project.afterEvaluate { 
      project.task(type: MyTask, 'thisTaskWorksIncorrectly') { 
       input = project.myPluginProps.message 
      } 
     } 
    } 
} 
関連する問題