11

マシンに依存関係がない状態でソースをコンパイルしたい。
例:ファイルA.java:

import some.pkg.B; 
public class A extends B {...}

Bソースが存在しないので、問題のシンボル(パッケージ'some.package'とクラスB)を取得するために、JavaFileManagerまたはカスタムClassLoaderのいずれかをフックして、ソースを取得するサービスを使用したいと思います。ストリング。

コンパイルコード:(inputFilesにはA.javaがあります)

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
CustomClassLoader classLoader = new CustomClassLoader();
StandardJavaFileManager standardfileManager = compiler.getStandardFileManager(this, null, null);
JavaFileManager fileManager = new CustomFileManager(standardfileManager, output, classLoader);
CompilationTask task = compiler.getTask(null, fileManager, this, null, null, inputFiles);
boolean result = task.call();

JavaFileManager(getFileForInput ..)およびクラスローダー(findClass、loadClass ..)のフックは、コンパイル時にトリガーされず、エラーメッセージが表示されました。

A.java:#: package some.pkg does not exist
A.java:#: cannot find symbol
symbol: class B

編集

APIをいじって、JavaCompiler(古いバージョン)のソースを調べ、コンパイルの概要を読んだ後でも、構文ツリーからシンボルを提供するために使用できるAPIフックが見つかりません。kschneidによって提案されているように、APIはパッケージ名に基づいてすべてのリソースを取得する必要があるようです。
私が考えた回避策の1つは、JavaCompilerを実行し、欠落しているシンボルのエラーメッセージを分析することです。そうすれば、どのシンボルが必要かを知り、それらを取得して再コンパイルします。
他の回避策/解決策はありますか?

4

2 に答える 2

4

(「package」というパッケージ名は違法であるため、実際には使用していないと思います...)

カスタムはそのメソッドを呼び出すJavaFileManager必要があります。listうまくいけば、この表記は理にかなっていますが、そのメソッドへの引数の組み合わせは次のようになります。

[PLATFORM_CLASS_PATH, some, [CLASS], false]
[CLASS_PATH, some, [SOURCE, CLASS], false]
[PLATFORM_CLASS_PATH, some.pkg, [CLASS], false]
[CLASS_PATH, some.pkg, [SOURCE, CLASS], false]

特定の環境で適切なインスタンスを作成するのがどれほど難しいかはわかりませんが、それがIterable<JavaFileObject>必要になると思います...

于 2012-05-29T20:16:31.683 に答える
1

コンパイル時にクラスをフックする良い方法は、GroovyAST変換を使用することです。ここで何ができるかを見ることができます

これは単純な古いJavaではありませんが、知っておくと便利なツールになります。

于 2012-06-04T07:58:17.330 に答える