2012-01-17 3 views
10

EclipseのJDTコンパイラは、というインターフェイスを提供しています。これは、メソッドを定義します。findType(...)は、カスケードコンパイルを可能にします。不思議なことに、標準のJDKコンパイラツールキットを使ってそれを行う方法があるかどうかを知りたいですか?javax.toolを使用したカスケードインメモリコンパイル

、シナリオは相互依存関係を持っているテンプレートファイル生成されたクラスのためにメモリのコンパイルで行うテンプレートエンジンであり、それはあなたがテンプレートファイルに遭遇した順序を予測することはできません、これFooかもしれないが、最初にコンパイルする必要がありますそれはすでにコンパイル親Barになる前に、したがって、あなたは別のソースBarを生成し、Fooのコンパイルを継続するために、最初にそれをコンパイルする必要がありFooのコンパイル時意味、カスケードコンパイルを行うための仕組みが必要になりますようにいくつかのコードは次のとおりです。

private NameEnvironmentAnswer findType(final String name) { 
    try { 
     if (!name.contains(TemplateClass.CN_SUFFIX)) { 
      return findStandType(name); 
     } 

     char[] fileName = name.toCharArray(); 
     TemplateClass templateClass = classCache.getByClassName(name); 

     // TemplateClass exists 
     if (templateClass != null) { 

      if (templateClass.javaByteCode != null) { 
       ClassFileReader classFileReader = new ClassFileReader(templateClass.javaByteCode, fileName, true); 
       return new NameEnvironmentAnswer(classFileReader, null); 
      } 
      // Cascade compilation 
      ICompilationUnit compilationUnit = new CompilationUnit(name); 
      return new NameEnvironmentAnswer(compilationUnit, null); 
     } 

     // So it's a standard class 
     return findStandType(name); 
    } catch (ClassFormatException e) { 
     // Something very very bad 
     throw new RuntimeException(e); 
    } 
} 

答えて

2

私たちのコメントの会話に基づいて、私は答えが明らかだと思います:いいえ、あなたはJDKコンパイラではできません。それはあなたがパッケージを要求するときにフックを与えますが、特定のクラスの依存関係は与えません。あなたは今のところ、私が知っているように得ることができる限り近い約

は次のとおりです。コードで

Here's a nice articleそれはメモリの授業で扱うように適応させる必要があるけれども。具体的には、記述する問題はJavaFileManager.list(...)メソッドで処理されます。メモリにキャッシュされているJavaFileObjectsをここに戻す必要があります。記事で説明したように、ForwardingJavaFileManagerというサブクラスを作成する必要があります。ただし、作業中のキャッシュされたクラスを処理するように変更されています。

これを使用して何かをコンパイルすることができます。エラーが返された場合は、regexを使って欠けているものを見つけてください。欠落したもののコードを生成/コンパイルした後、元のコードのコンパイルを再試行してください。

注:ある時点で、ForwardingFileManager.list(...)のpackageName引数として依存クラスのFQNを要求します。私はその時点でクラスを返そうとしていません。パッケージが不一致なので、うまくいかないかもしれませんが、おそらくそれはそうです。

+0

JDTの 'INameEnvironment.findType()'のポイントは、カスケードコンパイルを行うことができます。たとえば、クラス 'Bar'に依存する' Foo'クラスがあります。そして、私のアプリは 'Foo'をコンパイルする前に' Foo'をコンパイルしようとします。したがって 'Foo'のコンパイル時に、' Bar'のソースコードを生成してコンパイルし、 'Foo'のコンパイルを続けるロジックを実装できます。この種のものは 'ForwardJavaFileManager'でうまくいくのですか? –

+0

あなたは私が記述しているものの上にそのタイプのものを実装することができるかもしれません。私は似たようなことをしています。特定のエラーが発生した場合は、正規表現を使用して欠落しているものを見つけ出し、スタブを生成/コンパイルします。しかし、JDTがシンボルの欠落を見つけるためにコンパイルの途中であなたにフックを与えると言っているのであれば、私はJavacがそれを利用できるとは思いません。あなたは、事前に、またはエラー、または 'リスト(...とそれを把握する必要があります) 'コールはパッケージを対象としているので、あるパッケージのリクエストが何かを生成しなければならないということを知っていれば、そこでカスケードをコンパイルすることができます。 – mentics

+0

うーん...おそらく私は行く方法はありません。ポイントは私がBをコンパイルするとき、Aが見つからない、クラスAが欠けているだけでなく、ソースコードも準備ができていないことです。テンプレートファイル[a]からソースコードAを生成する必要があります。 JDTの 'findType'呼び出しは、ニーズに最適です。 –

1

このHelloWorldの例を読んで、問題が解決するかどうか確認してください。コードを掲示することなく、あなたの特定の問題が何であるかは言うまでもありません。

+0

ここがそうです。コンパイルするソースコードが2列あるとします。一つは "package foo; public class One {...}"で、もう一つは "package bar; import foo.One; public class Two {...}"です。 2つ目のクラス「2」をコンパイルするまでは、すべて問題ありません。 foo.Oneが見つかりませんでした。私は参照してください –

+0

参照してください。私はこれを残して、より良い解決策を探します。 URLクラスローダーが必要なようです。 –

+0

標準的なsun JDTコンパイラをあきらめ、ECJで終わります。新しい発見がありますか? –

関連する問題