如果使用带有自定义 Java 注释的类,如何引发注释处理错误
我想使用注释处理器创建 @Internal 注释,如果在库外部使用内部库类,该注释会引发错误。
但是,我不确定如何找到引用类的位置并抛出错误。
例如,对于这两个库类:
//Implementation
@Internal
public class InternalClass implements SomeInterface {
}
//API class
public interface SomeInterface {
static SomeInterface getInstance() {
return new InternalClass();
}
}
public class Test {
public static void main(String[] args) {
InternalClass annotated = new InternalClass(); //ERROR
SomeInterface interface = SomeInterface.getInstance(); //FINE
}
}
我该怎么做?
public class InternalProcessor extends AbstractProcessor {
@Override
public boolean process(final Set<? extends TypeElement> annotations,
final RoundEnvironment roundEnv) {
//What goes in here?
}
}
I want to use an annotation processor to create an @Internal annotation which throws an error if an internal library class is used outside the library.
However, I'm not sure how to find where a class is referenced and throw an error then.
For example, with these 2 library classes:
//Implementation
@Internal
public class InternalClass implements SomeInterface {
}
//API class
public interface SomeInterface {
static SomeInterface getInstance() {
return new InternalClass();
}
}
public class Test {
public static void main(String[] args) {
InternalClass annotated = new InternalClass(); //ERROR
SomeInterface interface = SomeInterface.getInstance(); //FINE
}
}
How would I do that?
public class InternalProcessor extends AbstractProcessor {
@Override
public boolean process(final Set<? extends TypeElement> annotations,
final RoundEnvironment roundEnv) {
//What goes in here?
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果没有黑客技术,这是相当困难的。您可以访问一些东西:
请注意,您无法轻松做到这一点:您想要访问您无法获得的方法体。您唯一的选择是打开所有源文件,将它们放入 java 解析器(java 不附带该解析器;您有多种选择,但它们都有缺点。
javac
是完整且开放的源代码,但受到限制性许可,并且并非所有内容都可以轻松遍历。ecj
每隔一分钟就会更改一次 API,它是完整的、许可的开源代码,而且速度很快,而且 API 更加稳定。 API 的设计很糟糕所有其他 java 解析器都是不完整的,从某种意义上说,没有严肃的项目使用它,因此您应该预料到 javac 和 ecj 可以处理的各种语言结构都会使这样的解析器崩溃,因此它们也往往具有糟糕的错误恢复能力。在源文件中的任何地方使用奇怪的或新的构造意味着整个文件都会出错,并且您无法执行分析,当您编辑文件并保存时,会出现增量编译的概念。 就是这样文件被重新编译,其余部分不变。这是一件大事:我可以修改源文件并开始使用其中的“@Internal”标记的内容,然后运行编译器(IDE 在您保存时运行它们),然后那个
@Internal
注释不会触发任何内容,因为没有包含该注释的代码正在被编译(相反,使用这样标记的类的代码正在被编译)。无论注释如何,AP 都可以在任何编译上触发,因此您在这方面并非完全不走运,但您需要处理所有内容并扫描所有使用的类型。因此,您要做的是一个疯狂复杂的项目,一个专业的 java 程序员至少需要一周以上的时间才能完成。你的工作需要:
退后一步,只是阻止访问某些方法:诸如 OSGi 和 java 的 module-info 之类的模块系统也旨在做到这一点,听起来您想重新发明一些轮子。也许只使用现有的模块系统?
Without hackery, this is rather difficult. You get access to a few things:
Note how you just can't do it easily then: You want access to method bodies which you don't get. Your only option is to open all the source files, throw them through a java parser (which java doesn't ship with; you have various options but they all have downsides.
javac
's is complete and open source but restrictively licensed and not all that easily traversed. They also change that API every other minute.ecj
's is complete, permissively licensed open source, and fast, with a much more stable API, but that API is deplorably designed and badly documented. All other java parsers are incomplete, in the sense that no serious project uses it and thus you should expect that various language constructs that javac and ecj can handle will crash such a parser. They also tend to have bad error recovery so one weird or new construct used anywhere in a source file means that entire file just errors out for you and there's no analysis you can perform.To make matters even more complicated, there's the notion of incremental compilation. When you edit a file, and save, Just that file gets recompiled, the rest isn't touched. This is a big deal: I can modify a source file and start using '@Internal' marked stuff in it, and then run compilers (IDEs run them as you save), and that
@Internal
annotation does not trigger anything because no code with it is being compiled (instead, code that uses a class so marked is being compiled). APs can just trigger on any compilation regardless of annotations, so you're not completely out of luck on this regard, but you need to process everything and scan all used types.What you want to do is therefore a crazy complicated project that an expert java programmer will need more than a week to put together at least. Your job would entail:
Taking a step back, just preventing access to certain methods: Module systems such as OSGi and java's
module-info
aim to do that too, it sounds like you want to badly reinvent some wheels. Maybe just use an existing module system?