Gradle:機能拡張の方法三つ

これは、Gradle:プラグインを作り、既存プラグインの動作を変更する及びGradle:プロジェクト間の共通処理パターンを実現するで書いたことのまとめである。

Gradleにおいて機能拡張を行うには、いくつかの方法がある。ここで言う機能拡張とは、独自に以下のような構造を作成することだ。

kakucho {
  a = 123
  b = "xyz"
}

等のように最小限の記述を行い、これによって何らかの機能を果たさせるか、あるいは既存のプラグインの動作を変更したりする。

つまり、これらのプロパティの値を設定した後で、何らかのアクションを行いたい。ここでは単純にa、bの値を表示するだけとする。

※ちなみに、各オブジェクトにprojectを保持させているが、こうしておくと後々様々な操作が楽になる。例としては必要ない。

extにクロージャを設定する方法

extにクロージャを設定するだけでもこれは可能だ。

class Holder {
  Project project
  int a = 0;    
  String b = "";
  Holder(Project project) {
    this.project = project
  }
  void show() {
    println a + b
  }  
}

ext.kakucho = { c-> 
  Holder holder = new Holder(project);
  c.delegate = holder
  c()
  holder.show();  
}

convention.pluginsを使う方法

convension.pluginsを使うと、設定したクラスのメソッドを呼び出せるようになる。引数のクロージャを処理した後で、変数値を表示している。

class KakuchoConvension {
  Project project;
  int a = 0
  String b = ""
  KakuchoConvension(Project project) {
    this.project = project
  }  
  def kakucho(Closure c) {
    c.delegate = this
    c()
    println a + b
  }
}

project.convention.plugins.kakuchoConvention = new KakuchoConvension(project)

extensions.createを使う方法

説明によれば、convension.pluginsは古いので常に新しいextensions.createを使えとのことなのだが、このやり方では、「プロパティをすべて設定した後に何らかのアクションを行う」ことができない。クロージャの処理終了を捕まえることができないからだ(少なくともそれを行う方法は発見できなかった)。

設計の改悪だと思うだが。。。

class Kakucho {
  Project project
  int a = 0
  String b = ""
  Kakucho(Project project) {
    this.project = project
  }
}
project.extensions.create("kakucho", Kakucho, project)

参考