Fregeプログラミング言語をサポートするためにEclipseプラグインを作成しています。IMPメタツールプラットフォームとEclipseIndigo(3.7)を使用しています。ランタイム環境はJava1.7です。
プラグインは、トークンの解析、構文解析などにバッチコンパイラと同じコードを使用します。ただし、eclipseプラグインから実行すると動作が異なることに気付き、以前にコンパイルされたモジュールのクラスファイルを読み取る次のメソッドにトレースしました。 Javaアノテーションの形式でそこに保存されているメタ情報を取得します。
public static MD.Operator[] getOperators(ClassLoader loader, String pack)
throws ClassNotFoundException {
Class<?> cl = null;
cl = loader.loadClass(pack);
MD.FregePackage os = cl.getAnnotation(MD.FregePackage.class);
if (os == null) return null; // <-- no annotation present
return os.ops();
}
URLClassLoader
コードは、引数として渡される独自のインスタンスを作成することに注意してください。クラスパスを正しく設定しないと、getOperatorsメソッドがClassNotFoundExceptionを正しくスローするため、クラスが読み込まれることを確信できます。トレースメッセージは、クラスローダーが次のパス(デフォルトでは単なるクラスパス)で構築されていることを示しています。
mkClassLoader:[C:\opt\eclipse\plugins\org.eclipse.equinox.launcher_1.2.0.v20110502.jar, X:\dev\frege\build]
fregeコンパイラによって作成されていないクラスファイルには通常MD.FregePackage
アノテーションを付けることができないため、これは通常、ユーザーがプレーンJavaクラスをインポートしようとしたことを示しており、実際にプラグインに次のメッセージが表示されます。
X:/dev/runtime-EclipseApplication/TestJFrege/src/Neu.fr:1: `frege.prelude.Base` is not a frege package
それでも、コマンドラインからこれをうまくコンパイルできます。問題の注釈が実際に同じ場所からロードできることの証拠として、これをここに含めました。
X:\dev\frege>java -cp ./build frege.compiler.Main X:/dev/runtimeEclipseApplication/TestJFrege/src/Neu.fr
mkClassLoader: [./build]
running: javac -cp ./build -d . -encoding UTF-8 ./Neu.java
事実を再開する:
- 注釈をロードすることになっているコードは、コンパイラがコマンドラインインターフェイスを介して呼び出されたときに正常に機能します。
- 注釈をロードすることになっているコードは、それがプラグインから呼び出されたのか、コマンドラインから呼び出されたのかを認識していません。実際、プラグインは先週まで存在していませんでしたが、コマンドラインインターフェイスは何ヶ月も正常に機能していました。
- もちろん、注釈には注釈があり
RetentionPolicy.RUNTIME
ます。そうでない場合、コマンドラインコンパイルでも注釈は認識されません。しかし、それは確かにそうです。
したがって、私が引き出すことができる唯一の結論は、Class.getAnnotation()
どういうわけか正しく機能していないということです。これは、モジュールシステムに必要な基本機能を効果的に破壊するため、非常に残念です。
これがとにかく重要な場合:プラグインが使用するFregeコンパイラコード自体はFregeで記述されており、frege.prelude.Base
上記のクラスはすべてのモジュールに必要な基本ライブラリであるため、プラグインのアクティブ化時にすでにロードされている必要があります。別のクラスローダー。
誰かが同じような経験をしていますか?これをどのように解決することは可能ですか?これを回避する方法の提案は大歓迎です。