2012-12-03 10 views
17

annotation processorを作成して、メソッドとフィールドをクラスに挿入しようとしていますが、ドキュメントが非常に疎です。私は遠くに出てこないし、私が正しくそれに近づいているかどうかわからない。注釈プロセッサによるコードの置換

処理環境には、新しいソースおよびクラスファイルを作成するための便利なメソッドを持つFilerオブジェクトがあります。これらはうまく動作しますが、既存のソースファイルをどのように読み込むかを把握しようとしましたが、そのすべてが "getResource"です。だから私のプロセッサの実装では、私はこれをやった:

@Override 
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 
    try { 
     for (TypeElement te : annotations) { 
      for (Element element : roundEnv.getElementsAnnotatedWith(te)) { 
       FileObject in_file = processingEnv.getFiler().getResource(
        StandardLocation.SOURCE_PATH, "", 
        element.asType().toString().replace(".", "/") + ".java"); 

       FileObject out_file = processingEnv.getFiler().getResource(
        StandardLocation.SOURCE_OUTPUT, "", 
        element.asType().toString().replace(".", "/") + ".java"); 

       //if (out_file.getLastModified() >= in_file.getLastModified()) continue; 

       CharSequence data = in_file.getCharContent(false); 

       data = transform(data); // run the macro processor 

       JavaFileObject out_file2 = processingEnv.getFiler().createSourceFile(
        element.asType().toString(), element); 
       Writer w = out_file2.openWriter(); 
       w.append(data); 
       w.close(); 
      } 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
     processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage()); 
    } 
    return true; 
} 

私の最初の苦境は、私はelement.asType().toString().replace(".", "/") + ".java"が(修飾型名を取得し、パッケージとソースファイルパスに変換する)ではないことを感じて助けることができないです問題に近づく良い方法です。 APIの残りの部分は非常に工夫されていますが、元のソースコードを取得するための便利な方法ではないようです。

本当の問題は、コンパイラが出力ディレクトリ( "error:duplicate class")の2番目のソースファイルによって自発的に動揺してしまったことです。

これまでのところ、データの計算とフィールド値とメソッドの挿入のためのマクロ・レクサーとパーサーおよびその他のものは書かれていますが、コンパイラーの外部の初期ステップとして動作します。元のファイルに.java拡張子を付けることができないということを除いて(コンパイラがそれらを見るのを防ぐため)、これはうまく機能します。それから、アノテーションはコード生成を行うことができると聞きましたが、これはより適切で便利なものと思われますが、多くのガイダンスを見つけることはできません。

+1

参照:http://techbitsfromsridhar.blogspot.ca/2013/02/java-compiler-plug-ins-in-java-8-use.html –

答えて

16

アノテーションプロセッサの背後にある意図は、開発者が既存のクラスを置き換えるのではなく、新しいクラスを追加できるようにすることです。つまり、既存のクラスにコードを追加できるバグがあります。 Project Lombokにはleveragedがあります。これは、(特に)ゲッターとセッターをコンパイル済みのJavaクラスに追加するためのものです。

メソッド/フィールドを「置き換える」方法は、入力クラスから継承または継承します。これにより、呼び出しを対象クラスにオーバーライド/迂回させることができます。

だから、これはあなたの入力クラスの場合:

InputImpl.java:

InputReplacementImpl.java:

public class InputReplacementImpl implmements Input{ 

    private Input delegate; 

    //setup delegate.... 

    public void foo(){ 
     System.out.println("foo replacement"); 
    } 
    public void bar(){ 
     delegate.bar(); 
    } 
} 

public class InputImpl implmements Input{ 
    public void foo(){ 
     System.out.println("foo"); 
    } 
    public void bar(){ 
     System.out.println("bar"); 
    } 
} 

あなたはそれを "置き換え" には、以下の生成することができます

これは、どのようにしてInputReplacementImplティーフ(InputImpl)。ラッピングを実行するコードをいくつか生成するか、生成されると予想されるコードのコンストラクターを単に呼び出すことができます。

あなたの質問は本当にわかりませんが、私はこれがあなたの問題についていくつかの光を当てることを願っています。

+0

* Ah ha!*私は以前にロンボクを見たと思います。それは部分的に私はこれが不可能だと思う理由がなかったのです。この答えは、コンパイラのエラーについて説明し、私にいくつかの選択肢を与えます。私はASTのハッキングに夢中になることを望んでいません。現在、シンプルなregexpsがコードを見つけて私の代わりに使っています。元のクラスが完全ではなく、コンパイル可能でないため、クラスへの委任は私の場合は実際にはできません。私が見ている限り、アノテーションAPIのこの愚かなわずかな制限は、その複雑さにもかかわらず、私には役に立たないということを意味します。しかし今、私は何をすべきかを知っています。注釈を使わないでください!ご助力ありがとうございます。 – Boann

+0

確かに@Boann、あなたのプロジェクトで幸運。 –

関連する問題