使Java编译器在使用带注释的方法时发出警告(例如@deprecated)
假设我定义了一个名为的自定义注释@Unsafe
。
我想提供一个注释处理器,它将检测 对 带有注释的方法的 引用@Unsafe
并显示警告。
例如,给出此代码…
public class Foo { @Unsafe
public void doSomething() { ... }
}
public class Bar {
public static void main(String[] args) {
new Foo().doSomething();
}
}
…我希望编译器打印如下内容:
WARN > Bar.java, line 3 : Call to Unsafe API - Foo.doSomething()
它在本质上与相似@Deprecated
,但是我的注释传达的是不同的东西,所以我不能@Deprecated
直接使用。有没有一种方法可以通过注释处理器来实现?注释处理器API似乎比
引用 注释成员的实体更侧重于 应用 注释的实体(Foo.java
在我的示例中)。 __
这个问题提供了一种使用ASM作为单独的构建步骤来实现它的技术。但是我想知道是否可以使用javac和注释处理以更自然的方式做到这一点?
回答:
我想我可以使用@mernst的回复从技术上实现我的目标,因此,我对此表示赞赏。但是,我发现了另一条对我来说更有效的途径,因为我正在开发一种商业产品,并且无法加入Checker框架(其GPL许可与我们的GPL许可不兼容)。
在我的解决方案中,我使用自己的“标准” java注释处理器来构建所有带有注释的方法的清单@Unsafe
。
然后,我开发了一个javac插件。使用Plugin
API,可以轻松地找到AST中任何方法的每次调用。通过使用此问题的一些技巧,我能够从MethodInvocationTree
AST节点确定类和方法名称。然后,我将这些方法调用与我创建的较早的“列表”进行比较,该“列表”包含用注释的方法,@Unsafe
并在需要时发出警告。
这是我的javac插件的缩写版本。
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插件,必须在命令行上提供参数:
javac -processorpath build/unsafe-plugin.jar -Xplugin:UnsafePlugin
另外,您必须META-INF/services/com.sun.source.util.Plugin
在unsafe-
plugin.jar中包含一个包含插件的完全限定名称的文件:
com.unsafetest.javac.UnsafePlugin
以上是 使Java编译器在使用带注释的方法时发出警告(例如@deprecated) 的全部内容, 来源链接: utcz.com/qa/407741.html