Make the java compiler warn when an annotated method is used (like @deprecated)(使 java 编译器在使用带注释的方法时发出警告(如@deprecated))
问题描述
假设我定义了一个名为 @Unsafe
的自定义注解.
Let's say I define a custom annotation called @Unsafe
.
我想提供一个注释处理器,它将检测 对使用 @Unsafe
注释的方法的引用 并打印警告.
I'd like to provide an annotation processor which will detect references to methods annotated with @Unsafe
and print a warning.
例如,给定这段代码...
For example, given this code ...
public class Foo {
@Unsafe
public void doSomething() { ... }
}
public class Bar {
public static void main(String[] args) {
new Foo().doSomething();
}
}
...我希望编译器打印如下内容:
... I want the compiler to print something like:
WARN > Bar.java, line 3 : Call to Unsafe API - Foo.doSomething()
它与@Deprecated
在精神上非常相似,但我的注解传达了不同的东西,所以我不能直接使用@Deprecated
.有没有办法通过注释处理器来实现这一点?注释处理器 API 似乎更关注实体 应用 注释(在我的示例中为 Foo.java
),而不是 reference 注释成员的实体.
It is very similar in spirit to @Deprecated
, but my annotation is communicating something different, so I can't use @Deprecated
directly. Is there a way to achieve this with an annotation processor? The annotation processor API seems to be more focused on the entities applying the annotations (Foo.java
in my example) than entities which reference annotated members.
这个question 提供了一种使用 ASM 将其作为单独的构建步骤来实现的技术.但我想知道我是否可以用 javac & 以更自然的方式做到这一点注释处理?
This question provides a technique to achieve it as a separate build step using ASM. But I'm wondering if I can do it in a more natural way with javac & annotation processing?
推荐答案
我想我可以使用@mernst 的回复在技术上实现我的目标,所以我很欣赏这个建议.但是,我发现了另一条更适合我的路线,因为我正在开发商业产品,并且无法合并 Checker 框架(它的 GPL 许可证与我们的不兼容).
I think I could have technically achieved my goal using the response from @mernst, so I appreciate the suggestion. However, I found another route that worked better for me as I'm working on a commercial product and cannot incoporate the Checker Framework (its GPL license is incompatible with ours).
在我的解决方案中,我使用我自己的标准"Java 注释处理器来构建所有使用 @Unsafe
注释的方法的列表.
In my solution, I use my own "standard" java annotation processor to build a listing of all the methods annotated with @Unsafe
.
然后,我开发了一个 javac 插件.插件 API 可以轻松找到 AST 中任何方法的每次调用.通过使用 this question,我能够从 MethodInvocationTree AST 节点确定类和方法名称.然后我将这些方法调用与我之前创建的包含用 @Unsafe
注释的方法的列表"进行比较,并在需要时发出警告.
Then, I developed a javac plugin. The Plugin API makes it easy to find every invocation of any method in the AST. By using some tips from this question, I was able to determine the class and method name from the MethodInvocationTree AST node. Then I compare those method invocations with the earlier "listing" I created containing methods annotated with @Unsafe
and issue warnings where required.
这是我的 javac 插件的缩写版本.
Here is an abbreviated version of my javac Plugin.
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.Plugin;
import com.sun.source.util.TaskEvent;
import com.sun.source.util.TaskEvent.Kind;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeInfo;
import com.sun.source.util.TaskListener;
import com.sun.source.util.TreeScanner;
public class UnsafePlugin implements Plugin, TaskListener {
@Override
public String getName() {
return "UnsafePlugin";
}
@Override
public void init(JavacTask task, String... args) {
task.addTaskListener(this);
}
@Override
public void finished(TaskEvent taskEvt) {
if (taskEvt.getKind() == Kind.ANALYZE) {
taskEvt.getCompilationUnit().accept(new TreeScanner<Void, Void>() {
@Override
public Void visitMethodInvocation(MethodInvocationTree methodInv, Void v) {
Element method = TreeInfo.symbol((JCTree) methodInv.getMethodSelect());
TypeElement invokedClass = (TypeElement) method.getEnclosingElement();
String className = invokedClass.toString();
String methodName = methodInv.getMethodSelect().toString().replaceAll(".*\.", "");
System.out.println("Method Invocation: " + className + " : " + methodName);
return super.visitMethodInvocation(methodInv, v);
}
}, null);
}
}
@Override
public void started(TaskEvent taskEvt) {
}
}
注意 - 为了调用 javac 插件,您必须在命令行中提供参数:
Note - in order for the javac plugin to be invoked, you must provide arguments on the command line:
javac -processorpath build/unsafe-plugin.jar -Xplugin:UnsafePlugin
此外,您必须在 unsafe-plugin.jar 中有一个文件 META-INF/services/com.sun.source.util.Plugin
,其中包含插件的完全限定名称:
Also, you must have a file META-INF/services/com.sun.source.util.Plugin
in unsafe-plugin.jar containing the fully qualified name of the plugin:
com.unsafetest.javac.UnsafePlugin
这篇关于使 java 编译器在使用带注释的方法时发出警告(如@deprecated)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使 java 编译器在使用带注释的方法时发出警告(如@deprecated)
基础教程推荐
- 如何使用 Java 创建 X509 证书? 2022-01-01
- 降序排序:Java Map 2022-01-01
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01