2016-04-11 26 views
6

たとえば、パラメータをターゲットにするために注釈@Outを作成したいとします。次に、コンパイラを使用して、関数が返る前にパラメータ値が設定されているかどうかを確認します。これは可能ですか?Javaアノテーションを使用してコンパイル時のチェックを定義できますか?

@Constのアノテーションが付いていないメソッドや、公開フィールドへのアクセスを許可しない@Immutableアノテーションについても考えていました。 (時間をコンパイルし、おそらくランタイム?)

をこれまでのところ、私はこれがあります。

//I'm assuming Class retention is a subset of Runtime retention 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.PARAMETER) 
public @interface Out 
{ 
    //no idea what to go in here. 
} 

これは、他の注釈です。

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface Immutable 
{ 

} 

私はリフレクションを使用して、実行時にそれを実装するための戦略を考案し始めることができると思うが、私はその原料をチェックするために、コンパイラやプリプロセッサに指示したい:もう一度、私はそれのための完全な定義を持っていません代わりに私の注釈はゼロのオーバーヘッドを持つでしょう。

これは、「もしこれができたら、既にそこにいるだろうし、もしそうなら、どこでそれをつかまえることができるか」と思うものの一つです。

編集:さらに、約@Const@ImmutableとJavaは、値によってオブジェクトへのポインタを渡し思い出した後を考えた後、怒鳴る、次のように、私は、@Immutableを取り除き、そして@Outの定義を変更してしまった、@Constの定義を拡大:

/** 
* When Applied to a method, ensures the method doesn't change in any 
* way the state of the object used to invoke it, i.e., all the fields 
* of the object must remain the same, and no field may be returned, 
* unless the field itself is marked as {@code @Const}. A method 
* annotated with {@code @Const} can only invoke other {@code @Const} 
* methods of its class, can only use the class's fields to invoke 
* {@code @Const} methods of the fields classes and can only pass fields 
* as parameters to methods that annotate that formal parameter as 
* {@code @Const}. 
* 
* When applied to a formal parameter, ensures the method will not 
* modify the value referenced by the formal parameter. A formal 
* parameter annotated as {@code @Const} will not be aliased inside the 
* body of the method. The method is not allowed to invoke another 
* method and pass the annotated parameter, save if the other method 
* also annotates the formal parameter as {@code @Const}. The method is 
* not allowed to use the parameter to invoke any of its type's methods, 
* unless the method being invoked is also annotated as {@code @Const} 
* 
* When applied to a field, ensures the field cannot be aliased and that 
* no code can alter the state of that field, either from inside the 
* class that owns the field or from outside it. Any constructor in any 
* derived class is allowed to set the value of the field and invoke any 
* methods using it. As for methods, only those annotated as 
* {@code @Const} may be invoked using the field. The field may only be 
* passed as a parameter to a method if the method annotates the 
* corresponding formal parameter as {@code @Const} 
* 
* When applied to a local variable, ensures neither the block where the 
* variable is declared or any nested block will alter the value of that 
* local variable. The local variable may be defined only once, at any 
* point where it is in scope. Only methods annotated as 
* {@code @Const} may be invoked using this variable, and the variable 
* may only be passed as a parameter to another method if said method 
* annotates its corresponding formal parameter as {@code @Const} 
* 
*/ 
@Retention(RetentionPolicy.SOURCE) 
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, 
ElementType.LOCAL_VARIABLE}) 
@Inherited 
public @interface Const 
{ 

} 

@Out

/** 
* The formal parameter annotated with {@code @Out} must be undefined in 
* the scope of the caller, and it's the responsibility of the method to 
* define it. If allowNull is true, the parameter can be explicitly set 
* to null in the body of the method. 
*/ 
@Retention(RetentionPolicy.SOURCE) 
@Target(ElementType.PARAMETER) 
public @interface Out 
{ 
    boolean allowNull() default false; 
} 

編集:私はこれをEclipseプラグインとして実装しようとしていますが、私はマニュアルを完全に読んでいません。私は、ASTにアクセスし、メソッドとフィールドを訪問するための基本ロジックを持つプラグインを作成しました。私はその後、プラグインが検出しなければならないダミーの注釈を作ってから、結果を印刷しようとしますが、私は何を期待するか分かりません。私のプラグインは「インクリメンタルビルド」プラグインです。誰かが見て、ちょうど私にいくつかのことを説明できるなら、それのためのコードはあります。私はこのAPIで完全に失われています。

https://github.com/Starless2001/Plugin-for-Eclipse

+2

真剣に、私はあなたが望むことをするためには、何らかの形でユーザ定義可能なプラグインをサポートするコンパイラが必要だと思います。そして私はそこに何も知らない。コンパイラライターの立場から考えると、非常に難しいことです。 – ajb

+0

@ajbそれは残念です。注釈は言語拡張として機能するはずです。 – FinnTheHuman

+0

私はコンパイラのようなものを構築するかもしれません。プリコンパイラ、おそらく? – FinnTheHuman

答えて

6

javacコンパイラは、正確に何をしたい達成注釈プロセッサと呼ばれるユーザー定義可能なプラグインを、サポートしています。注釈は言語拡張として考えることができます。

定義public @interface Immutable { ... }は、プログラムで書くことができる@Immutable注釈の構文を定義します。アノテーション・プロセッサ(コンパイラ・プラグイン)はセマンティクスを定義します。セマンティック・ルールを強制し、プログラムがルールに違反したときにコンパイラの警告を出します。

このような注釈プロセッサーの作成を容易にする1つのフレームワークはChecker Frameworkであり、@NonNullおよび@Immutableのような注釈の定義を含んでいます。 Checker Frameworkを使用してコードを検証する方法については、tutorial 1,tutorial 2の2つのチュートリアルがあります。

通常のJava注釈処理は、クラス、フィールド、メソッド、メソッドパラメータなどの各宣言で呼び出され、通常のJavaでは注釈プロセッサにプログラムの完全なASTへのアクセス権が与えられません。 Checker Frameworkは、Javaアノテーション処理の能力を拡張するライブラリと考えることができます。各クラスの完全なASTへのアクセスを提供し、プログラム内のすべてのステートメントのルールを定義できます。したがって、ステートメントが@Immutableオブジェクトの非@Constメソッドを呼び出すと、注釈プロセッサは警告を発行できます。

注釈プロセッサはモジュール式で、一度に1つのクラスで作業する必要があります。注釈プロセッサは、現在のクラスのASTに加えて、それが使用するすべてのクラスの注釈(注釈を含む)にアクセスすることができる。アノテーション処理により、その情報が得られます(ただし、プロジェクト全体のASTは一度に処理されるわけではありません)。

+0

この方法で実装します。すべての助けに感謝します。私はチェッカーのフレームワークが遅く、不完全であるので好きではありません。不変性を定義するために複数のチェッカーが必要です。準備が整い次第、私は公開します。だれかが知っていると、誰かがそれが役に立つと思うかもしれません。 – FinnTheHuman

+0

これは素晴らしいですね。結果を共有してください。 – mernst

関連する問題