読者です 読者をやめる 読者になる 読者になる

Xtendでアクティブアノテーションを作ってみる

Xtendは、Eclipse Foundationで開発されている言語です。JVM上で動く言語ですが、GroovyやScalaとは違いXtendのソースコードから、Javaソースコードを生成するというアプローチをとっています。

アクティブアノテーションという機能が追加されたみたいで、試してみました。Javaのpluggable annotation processing api(APTとも呼ばれる)みたいなものです。

Xtendの場合だと、コンパイル時のXtendコード→Javaコードの変換時の処理に、アノテーションをトリガーとしてユーザが介入できる感じでしょうか。
lombokにあるような、setter,getter生成のアノテーションは、Xtendにも最初から用意されています。

今回、クラスにjava.util.logging.Loggerのインスタンスを追加するだけの、Logアノテーション、プロセッサーを作ってみました。

まずは、Logアノテーション

// これは、xtendコード
package annotations

import org.eclipse.xtend.lib.macro.Active
import processors.LogProcessor

@Active(typeof(LogProcessor))
annotation Log {
}

コンパイル時にLogアノテーションが付いてるクラスに対して、LogProcessorの処理が実行されるようになります。

次に、LogProcessor

// これは、xtendコード
package processors

import org.eclipse.xtend.lib.macro.AbstractClassProcessor
import org.eclipse.xtend.lib.macro.TransformationContext
import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
import java.util.logging.Logger

class LogProcessor extends AbstractClassProcessor{

    override doTransform(MutableClassDeclaration annotatedClass, extension TransformationContext context) {
        val name = annotatedClass.simpleName;
        annotatedClass.addField("log") [
            type = typeof(Logger).newTypeReference()
            initializer = ['''Logger.getLogger("«name»")''']
            final = true
            static = true
        ];
    }
}

IDEの補完をたよりに、適当に書きました。説明をざっくり割愛しますが、なんとなくわかりますよね。。

次に処理対象となる、Barクラス

// これはXtendコード
package foo

import annotations.Log

@Log
class Bar {
    def hoge() {
        log.info("Hello, World!");
    }
}

コード上、logなんて変数どこにもありませんが、コンパイルエラーは、発生しません。LogProcessorが、コンパイル時に追加しているのです。

そして、生成されたBarクラスのJavaコード

// これは生成されたJavaコード
package foo;

import annotations.Log;
import java.util.logging.Logger;

@Log
@SuppressWarnings("all")
public class Bar {
  public void hoge() {
    Bar.log.info("Hello, World!");
  }
  
  private final static Logger log = Logger.getLogger("Bar");
}

logのフィールドが追加され、初期化されています。はい。
Xtendでは、文字列操作のテンプレート機能を持っているので、JavaのaptでJavaコード生成するより大分楽な感じがします。

コード

以上