JavaParser使用介绍

原标题:JavaParser使用介绍

javapasser是一个可以将java源码解析为一棵语法树,然后基于这棵树对java代码进行分析和修改的工具。听起来有点玄乎,不过其实不是很复杂的东西,至少概念上来说是这样子的。

语法树

先说一下什么是语法树吧。我猜学过编译原理的都多少知道这个东西。语法树就是将代码根据语法规则分割并组织为一棵树形结构,比方说表达式“1 + 2 * 3”,根据语法规则,它应该这样子被拆解:

第一步: +, 1,(2 * 3)

第二步: +, 1,(*, 2, 3)

以树的方式表示,则变成:

当然,这是一个十分简单的表达式,我们平时的代码可能更加复杂,比如下面的代码:

它的语法树是下面这样子:

JavaParser的基本使用

理论上讲,我们自己也可以解析语法树,但需要做到标签切割、类型识别等等事情,我自己尝试过,反正挺麻烦,所以就直接依赖javapasser来做了。

再来看一个javapasser的例子。

这里面核心的代码是JavaParser.parse和VoidVisitorAdapter.visit两个方法,前者 是将一个java代码的文本解析为一棵CompilationUnit类型的树,后者是在指定的树上进行搜索,然后根据遇到的节点的类型调用具体的回调。 VoidVisitorAdapter有非常多的回调方法,上面的例子只是举出了3个,分别是类定义、方法定义和方法调用。

除了上面的办法,还可以直接根据具体类型一次性导出节点:

这个的结果和只重写VoidVisitorAdapter的特定回调一样,但是在具体的场景下可能更为自由。

除了分析,javaparser也提供修改和创造java代码的功能:

JavaParser的实际使用

自动代码规范检查

我 们去年做了一个安卓组的“代码格式检查工具”,就是基于JavaParser。当时我们考虑了几十个情况,有一些直接可以通过文本处理来完成判断,有一些 则不得不通过语法树来判断,比如“禁止在(字段或方法)名称前(或后)添加下划线”这种,如果不分析代码,根本不知道哪些字符是“字段”和“方法”。另外 一些,比如“禁止将自增自减符号置于变量前方”,就是说可以“a++”,但禁止“++a”。这种就需要同时结合语法分析和原始文本来判断了。下面列出一些 我觉得还不错的代码以供参考:

上面是一段对类字段检查的代码,如果代码可以进入“if”块,表示这一次字段定义中存在多个字 段名称,如“private int a, b, c;”。依照我们的安卓组的代码格式规范,这是违法的。而如果进入else里面的if块,则表示这个字段在定义的时候,还被赋值了一个匿名类,这个也会我 们的代码规范所禁止的。

这个代码是对Lambda语法使用的检测,我们禁止使用lambda语法,一方面是java的lambda语法很难看,另一方面是我们只允许使用jdk-6来进行开发。

最后这个是对字段获取的限制。我们的规范禁止SDK内的代码使用“R.xxx.xxx”的方式 来获取资源ID,而上面的代码,就是对这个操作的提醒。不过当然了,这个只是判断不能在一个叫做“R”的类中获取字段,但并没有弄清楚这个类是不是就是安 卓的那个集合资源ID的“R”。可是一般来说,也不会有人特地为一个类明明为“R”的。

自动代码格式化

JavaParser还可以用来做代码自动格式化的操作。

比如同样一段代码,有人喜欢这样子写:

而我喜欢这样子写:

并且,我不喜欢使用4个空格为缩进,而是使用tab来缩进。那么使用JavaParser,我可以这样子对代码进行格式化:

依赖关系分析

格 式控制只是小把戏,语法树主要是用在解析代码上的。我最初接触JavaParser,是通过google一个“parse java code”这个关键词来的。当时我正在寻找一套“通用且高效”的脚本语言,尝试了lua和js都发现各有缺陷,而最符合需求的groovy,又因为安卓系 统禁止直接从字节流加载class而遇到麻烦。所以打算自己做一套工具来解析java代码,并执行起来。不过很遗憾,最终这个事情做了一半停下来。但产出 了一些东西,比如对一套java代码的依赖关系进行分析。

由于篇幅关系,这里我不贴代码了,因为代码量挺多的,大概描述一下具体的思路:

经过这个流程,原来类似于下面的代码:

会变成:

你会发现原来的import和extends都变了。这是执行这些代码的第一步。

文/Mob开发者平台 技术副总监 余勋杰返回搜狐,查看更多

责任编辑:


原网址: 访问
创建于: 2021-12-28 20:02:21
目录: default
标签: 无

请先后发表评论
  • 最新评论
  • 总共0条评论