【发布时间】:2016-07-31 23:48:06
【问题描述】:
例如,我想为目标参数创建注解@Out。然后我会以某种方式使用编译器检查是否在函数返回之前设置了参数值。这可能吗?
还考虑了一个@Immutable 注释,它不允许调用任何未使用@Const 注释的方法或访问任何公共字段。 (编译时间和可能的运行时间?)
到目前为止,我有这个:
//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 中了。
【问题讨论】:
-
说真的,我认为要做你想做的事,你需要一个以某种方式支持用户可定义插件的编译器。我不知道那里有任何。从编译器编写者的角度来看,这听起来是一件非常困难的事情。
-
@ajb 这令人失望。注释应该作为语言扩展。
-
我可能会构建类似编译器的东西。一个预编译器,也许?
-
你可以定义一个注解处理器。注释的保留时间为
SOURCE。然后,您将创建一个Processor,并通过在META-INF/services/javax.annotation.processing.Processor中定义您的处理器实现的完全限定名称将其附加到您的项目中。您还必须启用注释处理。缺点是您必须在错误/警告出现之前保存文件,而不是像内置的编译时检查那样立即出现 -
这篇博文描述了 Project Lombok 如何挂钩到编译过程:notatube.blogspot.com/2010/11/…
标签: java eclipse eclipse-plugin annotations compiler-options