java - 我可以使用 Java 注释来定义编译时检查吗?

标签 java eclipse eclipse-plugin annotations compiler-options

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

还考虑了一个@Immutable 注释,它不允许调用任何未用@Const 注释的方法或访问任何公共(public)字段。 (编译时间和可能的运行时间?)

到目前为止我有这个:

//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 按值将指针传递给对象之后,我扩展了定义@Const,去掉了@Immutable,修改了@Out的定义,如下:

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

最佳答案

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

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

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

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

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

关于java - 我可以使用 Java 注释来定义编译时检查吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36538133/

相关文章:

java - 使用 arquilian 测试时何时构建数据库结构?

java - 无法使用ip地址访问tomcat

android - PhoneGap 3.3.0 又名 Cordova 与 PhoneGap 3.2.0

java - 如何扩展 HTML 的 StructuredTextEditor(或文本编辑器)内容助手

java - 可以在 Eclipse 命令行应用程序中隐藏 JVM 终止向导

java - 从带有对象的 ArrayList 中删除对象时出现问题

java - Gradle 构建失败

java - 是否可以在Eclipse中自动将依赖的项目编译成jar?

eclipse - 在eclipse(mars)上安装了一个插件,现在eclipse无法启动。如何卸载该插件?

eclipse - 两个 Eclispse 项目 -> 一个 Eclipse 插件