最近在做抽象语法树的功能,一开始很懵逼,非常感谢大佬提供的类属性解释文章,这才开始明白如何去写。
博客地址:https://www.jianshu.com/p/68027eaf45ad
关于如何创建注解处理器我这儿就不说了,网上有很多方式,如下:
https://blog.csdn.net/a1527238987/article/details/80379834
废话不多说,现在有一些需求,需要在编译期间动态添加某个导包怎么办,经过上面的博客我查到JcImport是表示导包的类,但是要如何使用呢,一开始我用的是
defs这个属性,试图通过添加一个JcImport进去,然后运行各种报错,经过调试发现,他只表示某些方法,错误写法:
java.util.List defs = new ArrayList();
JCTree.JCIdent ident = _maker.Ident(_names.fromString(TRACKER_PACKAGE));
JCTree.JCImport jcImport = _maker.Import(_maker.Select(ident, _names.fromString(TRACKER_CLASS)), false);
defs.add(jcImport);
jcClassDecl.defs = List.from(defs);
后来经过查资料,我发现了一个类JCCompilationUnit,发现它里面包含很多信息
它里面包含很多信息,这里面的defs正是包含import导包和定义的class信息,如图:
这个时候我就想要怎么拿到这个信息,于是google搜索资料,发现根本没啥资料
然后看到一个网址有一些code example,如下网址:
https://www.programcreek.com/java-api-examples/?class=com.sun.tools.javac.tree.JCTree&method=JCCompilationUnit
在Example 10中我发现JCCompilationUnit是TreePath中获取的,于是我知道TreePath又是由element获取来的
_trees = Trees.instance(processingEnv);
TreePath treePath = _trees.getPath(element)
最终代码:
private void addImportInfo(Element element) {
TreePath treePath = _trees.getPath(element);
Tree leaf = treePath.getLeaf();
if (treePath.getCompilationUnit() instanceof JCTree.JCCompilationUnit && leaf instanceof JCTree) {
JCTree.JCCompilationUnit jccu = (JCTree.JCCompilationUnit) treePath.getCompilationUnit();
for (JCTree jcTree : jccu.getImports()) {
if (jcTree != null && jcTree instanceof JCTree.JCImport) {
JCTree.JCImport jcImport = (JCTree.JCImport) jcTree;
if (jcImport.qualid != null && jcImport.qualid instanceof JCTree.JCFieldAccess) {
JCTree.JCFieldAccess jcFieldAccess = (JCTree.JCFieldAccess) jcImport.qualid;
try {
if (TRACKER_PACKAGE.equals(jcFieldAccess.selected.toString()) && TRACKER_CLASS.equals(jcFieldAccess.name.toString())) {
return;
}
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
}
java.util.List<JCTree> trees = new ArrayList<>();
trees.addAll(jccu.defs);
JCTree.JCIdent ident = _maker.Ident(_names.fromString(TRACKER_PACKAGE));
JCTree.JCImport jcImport = _maker.Import(_maker.Select(
ident, _names.fromString(TRACKER_CLASS)), false);
if (!trees.contains(jcImport)) {
trees.add(0, jcImport);
}
jccu.defs = List.from(trees);
}
}
这里的Element.getKind == ElementKind.CLASS
这样就可以看到你对应的import代码加进去了,这是我的分析过程可能有点啰嗦,将就着看吧。
项目地址:github地址