使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

回到顶部