我可以使用 Java 注释来定义编译时检查吗? [英] Can I use Java annotations to define compile time checks?

查看:53
本文介绍了我可以使用 Java 注释来定义编译时检查吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

例如,我想创建注解@Out 来定位参数.然后我会以某种方式使用编译器来检查是否在函数返回之前设置了参数值.这可能吗?

For example, I wanted to create the annotation @Out to target parameters. Then I would somehow use the compiler to check if the parameter value is set before the function returns. Is this possible?

还考虑使用@Immutable 批注,该批注不允许调用任何未使用 @Const 批注的方法或访问任何公共字段.(编译时间,可能还有运行时间?)

Also was thinking about a @Immutable annotation that would not allow any method not annotaded with @Const to be invoked or access to any public fields. (compile time and probably runtime?)

到目前为止,我有这个:

So far I have this:

//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.
}

这是另一个注释.再说一次,我没有完整的定义:

this is the other annotation. again, I have no complete definition for it:

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

}

我想我可以开始设计一个策略来在运行时使用反射来实现它,但我想指示编译器或预处理器为我检查这些东西,这样我的注释就会有零开销.

I think I can begin to devise a strategy to implement that at runtime using reflection, but I wanted to instruct the compiler or pre-processor to check that stuff for me instead, so my annotations would have zero overhead.

这是您认为如果这可以完成,它就已经存在,如果是,我可以从哪里获取"的事情之一.

This is one of those things that you think "if this could've been done, it would already be out there, and if it is, where can I grab it".

编辑:在进一步考虑@Const@Immutable 并记住java 按值传递指向对象的指针后,我扩展了定义@Const,去掉@Immutable,修改@Out的定义,如下:

Edit: After further thought about @Const and @Immutable and after remembering java passes pointers to objects by value, I expanded the definition of @Const, got rid of @Immutable, and altered the definition of @Out, as follows bellow:

/**
* 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 中.

I'm trying to implement this as an eclipse plugin, but I'm completely lost reading the manual. I wrote a plugin with the basic logic for accessing the AST and visiting methods and fields. I then made a bunch of dummy annotations that my plugin should detect, then I try to print the results, but I'm not even sure what to expect. My plugin is a "Incremental Build" plugin. Here's the code for it, If someone could take a look and just explain a few things to me. I'm completely lost in this API.

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

推荐答案

javac 编译器支持用户可定义的插件,称为注解处理器,可以完全满足您的需求.您可以将注释视为语言扩展.

The javac compiler supports user-definable plugins, called annotation processors, that accomplish exactly what you want. You can think of annotations as language extensions.

定义 public @interface Immutable { ... } 定义了语法:您可以在程序中编写的 @Immutable 注释.注释处理器(编译器插件)定义语义:它强制执行语义规则并在您的程序违反规则时发出编译器警告.

The definition public @interface Immutable { ... } defines the syntax: the @Immutable annotation that you can write in your program. The annotation processor (the compiler plug-in) defines the semantics: it enforces the semantic rules and issues compiler warnings when your program violates the rules.

Checker Framework 是一个可以轻松编写此类注释处理器的框架,它包含注释的定义,例如@NonNull@Immutable.这里有两个关于如何使用 Checker 框架验证代码的教程:教程 1教程 2.

One framework that makes it easy to write such annotation processors is the Checker Framework, and it contains definitions for annotations like @NonNull and @Immutable. Here are two tutorials about how to use the Checker Framework to validate code: tutorial 1, tutorial 2.

在每个声明上调用普通Java注解处理,例如类、字段、方法和方法参数,普通Java让注解处理器无法访问程序的完整AST.您可以将 Checker 框架视为扩展 Java 注释处理功能的库.它使您可以访问每个类的完整 AST,并允许您为程序中的每个语句定义规则.因此,当语句调用 @Immutable 对象上的非 @Const 方法时,您的注释处理器可以发出警告.

Ordinary Java annotation processing is invoked on each declaration, such as classes, fields, methods, and method parameters, and ordinary Java gives the annotation processor no access to the program's full AST. You can think of the Checker Framework as a library that extends the power of Java annotation processing. It gives you access to the full AST of each class, and it lets you define rules for every statement in your program. Thus, your annotation processor can issue warnings when a statement invokes a non-@Const method on an @Immutable object.

您的注释处理器应该是模块化的,一次处理一个类.注释处理器可以访问当前类的 AST,以及它使用的所有类的签名,包括注释.注释处理会为您提供这些信息(但不会一次性提供给整个项目的 AST).

Your annotation processor should be modular, working one class at a time. The annotation processor has access to the AST of the current class, plus the signatures, including annotations, of all classes that it uses. Annotation processing gives you that information (but not to the whole project's AST all at once).

这篇关于我可以使用 Java 注释来定义编译时检查吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆