原标题: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
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论