如何故意导致自定义Java编译器警告消息?

2022-08-31 11:12:59

我即将提交一个丑陋的临时黑客攻击,以便在我们等待外部资源修复时解决阻塞问题。除了用一个大的可怕的注释和一堆FIXME标记它之外,我还想让编译器抛出一个明显的警告消息作为提醒,这样我们就不会忘记把它拿出来。例如,类似下面的内容:

[javac] com.foo.Hacky.java:192: warning: FIXME temporary hack to work around library bug, remove me when library is fixed!

有没有办法用我选择的消息引起有意的编译器警告?如果做不到这一点,那么在代码中添加一个现有的警告,在违规行上可能有一个字符串中的消息,以便将其打印在警告消息中,这是最简单的方法吗?

编辑:弃用的标签似乎没有为我做任何事情:

/**
 * @deprecated "Temporary hack to work around remote server quirks"
 */
@Deprecated
private void doSomeHackyStuff() { ... }

eclipse或sun javac 1.6(从ant脚本运行)中没有编译器或运行时错误,它肯定正在执行该函数。


答案 1

我认为将由编译器处理的自定义注释是解决方案。我经常编写自定义注释以在运行时执行操作,但我从未尝试在编译时使用它们。因此,我只能为您提供有关您可能需要的工具的指示:

  • 编写自定义批注类型。本页说明如何编写批注。
  • 编写注释处理器,用于处理自定义注释以发出警告。运行此类注释处理器的工具称为 APT。您可以在此页面上找到一个说明。我认为APT API中您需要的是NotementProcessorEnvironment,它将允许您发出警告。
  • 从Java 6开始,APT被集成到javac中。也就是说,您可以在 javac 命令行中添加注释处理器。javac 手册的这一部分将告诉您如何调用自定义注释处理器。

我不知道这个解决方案是否真的可行。当我找到时间时,我会尝试自己实现它。

编辑

我成功实施了我的解决方案。作为奖励,我使用了java的服务提供商工具来简化它的使用。实际上,我的解决方案是一个包含2类的jar:自定义注释和注释处理器。要使用它,只需在项目的类路径中添加此jar,并注释您想要的任何内容!这在我的IDE(NetBeans)中工作正常。

注释的代码:

package fr.barjak.hack;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.LOCAL_VARIABLE, ElementType.METHOD, ElementType.PACKAGE, ElementType.PARAMETER, ElementType.TYPE})
public @interface Hack {

}

处理器代码 :

package fr.barjak.hack_processor;

import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;

@SupportedAnnotationTypes("fr.barjak.hack.Hack")
public class Processor extends AbstractProcessor {

    private ProcessingEnvironment env;

    @Override
    public synchronized void init(ProcessingEnvironment pe) {
        this.env = pe;
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (!roundEnv.processingOver()) {
            for (TypeElement te : annotations) {
                final Set< ? extends Element> elts = roundEnv.getElementsAnnotatedWith(te);
                for (Element elt : elts) {
                    env.getMessager().printMessage(Kind.WARNING,
                            String.format("%s : thou shalt not hack %s", roundEnv.getRootElements(), elt),
                            elt);
                }
            }
        }
        return true;
    }

}

要将生成的 jar 启用为服务提供程序,请将该文件添加到 jar 中。此文件是一个 acsii 文件,必须包含以下文本:META-INF/services/javax.annotation.processing.Processor

fr.barjak.hack_processor.Processor

答案 2

我见过的一种技术是将其与单元测试联系起来(你单元测试,对吧?)。基本上,您创建了一个单元测试,一旦实现外部资源修复,该测试就会失败。然后,您评论该单元测试,以告诉其他人如何在问题解决后撤消您的严重黑客攻击。

这种方法真正巧妙的是,撤消黑客攻击的触发器是核心问题本身的修复。


推荐