当前位置: 首页 > 面试题库 >

使Java编译器在使用带注释的方法时发出警告(例如@deprecated)

司寇瑾瑜
2023-03-14
问题内容

假设我定义了一个名为的自定义注释@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


 类似资料:
  • 那么,这是一种好的做法吗?有什么缺点吗?如果它像我现在看起来的那么好,为什么没有很多库以一种简单的方式来做到这一点(我找到的唯一一个是类索引)?相反,对于运行时处理,有这么多?

  • 忽略编译器警告 格式 #pragma clang push #pragma clang diagnostic ignored "错误类型" // 存在警告的代码 #pragma clang pop > 1.在需要忽略的警告处右键 -- Reveal in Log 2.会给出警告的详细信息,其中包括警告的类型 3.高亮选中的便是这个警告的类型 4.在警告代码处增加如下代码 Command

  • 当我有一个没有javadoc的公共方法时,Checkstyle会发出警告,这很好!当我重写一个公共方法时,我没有得到警告,因为javadoc已经在该方法的父类中可用。 现在,我的方法有了另一个注释,例如MyEvent。现在我确实收到了警告,但我不想要它,因为注释已经足够了。是否可以排除具有特定注释的方法的警告? 有一些解决方案涉及向我的代码中添加诸如或之类的注释,但这并不能使我的代码更好,我可以改

  • 我应该启用哪些确切的gcc标志来获得此警告? 为什么将声明为volatile会抑制该警告?

  • 我有以下Spring Boot类,用自定义注释注释: 注释定义如下: 我想要的是编写一个注释处理器,有效地使我的控制器像下面的代码一样工作。 我已经能够在运行时通过反射实现这一点,但这大大延长了启动时间。有没有办法只使用注释和自定义注释处理器来实现上述功能?换句话说,我想创建一个注释,将带注释的方法添加到类中,并将任意方法调用添加到现有方法中。 我知道注释处理并不真正支持修改源代码。我有兴趣知道任

  • 我已经创建了一个高阶组件,它应该为我的组件添加一些额外的功能。然而,当我在这个组件中使用反应钩子时,我会得到以下eslint警告。 不能在回调内调用React钩子“React.useffect”。必须在React函数组件或自定义React钩子函数中调用React钩子。(吊钩/吊钩规则) 为什么我会收到这个警告?在HoC中使用钩子被认为是不好的做法吗? 最简单的例子: Codesandbox:htt