倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

GroovyDSL と IntelliJ IDEA

IntelliJ IDEA にて、独自に定義したプロパティやメソッドを IDEA に認識させる方法を見ていきます。

  • プロパティ・メソッドの追加定義
  • GroovyDSL の作成
  • GroovyDSL スクリプトをリソースとして Jar ファイルに含めると・・・

プロパティ・メソッドの追加定義


Groovy ではメタクラスを使ってプロパティやメソッドを追加定義できるのでした。 たとえば Integer クラスに daysFromNow プロパティを追加するには以下のようにします:

// DayCounter.groovy
Integer.metaClass.getDaysFromNow = { ->
  Calendar today = Calendar.instance
  today.add(Calendar.DAY_OF_MONTH, delegate)
  today.time
}
 
println(5.daysFromNow)


プロパティを追加するにはそれに対応する getter/setter メソッドを追加するのですが(ここでは getter のみ追加)、それらのメソッドを追加するにはメタクラスClosure 型のプロパティを追加するってのはちょっとマワリクドイです(笑)

まぁ、コーディング自体はどうってことはないのですが、IDE で開発を行っている場合には独自のプロパティやメソッドは情報を解決できないため、不明なメンバに対する警告、コンテンツ・アシストなどの IDE の恩恵が受けられません。 たとえば、上記の画面は IntelliJ IDEA でサンプルの DayCounter.groovy を開いたところですが、Integer クラスに追加定義した daysFromNow プロパティが解決できないため、最後の行で「解決できないプロパティ」として下線が表示されています。

GroovyDSL の作成


IntelliJ IDEA には、独自に定義したプロパティやメソッドを IDEA に認識させるメカニズムが提供されています。 これは結構簡単で、適当なフォルダ上にGroovyDSL スクリプト(拡張子 .gdsl)を配置するだけです。 ファイル内容も形式的なので難しくはありません(数が多くなると面倒そうだけど)。

GroovyDSL スクリプトを作成する方法は IDEA 自体に提供されていて、このスクリプトを作成したいフォルダに対して

ポップアップメニュー : [New] → [Groovy Script]

を選択してダイアログを表示させ、Kind コンボボックスで「GroovyDSL script」を選択してスクリプトを作成します(下図参照):






GroovyDSL スクリプトの内容はこんな感じになります*1

// TestScript.groovy
def ctx = context(ctype: "java.lang.Integer")
 
contributor(ctx) {
  property name: "daysFromNow", type: "Calendar"
}

GroovyDSL スクリプトは Groovy スクリプトなので、Groovy の制御構造(if / for 文など)も使えます。 詳しいサンプルはこちら。 この内容を記述して、以下のようにDSL をアクティブにする







追加定義したプロパティやメソッドがキチンと認識され、コンテンツ・アシストも行えるようになります!

GroovyDSL スクリプトをリソースとして Jar ファイルに含めると・・・


上記の GroovyDSL スクリプトは、リソースとして Jar ファイルに含めておけば、他の Groovy プロジェクト*2でも IDEA が自動で読み取ってプロパティやメソッドを認識してくれます:

public な独自プロパティ・メソッドを開発して配布する際には GroovyDSL は必須項目かも。 少し注意が必要なのは、IDEA は GroovyDSL を自動で読み取ってくれはするものの、実際にプロパティやメソッドを追加するスクリプトなどは実行してくれないことでしょうか。 GroovyDSL スクリプトによってコンテンツ・アシストに表示されるプロパティやメソッドを使ってコーディングしても、実行時に MissingPropertyException / MissingMethodException が投げられてしまいます。 プロパティやメソッドの追加処理をシステマティック実行するためには、「Groovyでクラスを静的に動的拡張する方法」に載っているような方法が必要になってくるかと。

参考 URL

Intellij Idea In Action

Intellij Idea In Action


Groovy for Domain-specific Languages

Groovy for Domain-specific Languages

*1:後のサンプルのため、「GroovyDSL scripting framework」のサンプルから少々変更しています(スコープの指定を除去)。

*2:もちろん IntelliJ IDEA の Groovy プロジェクトですが。