作者:小傅哥
博客:https://bugstack.cn
原文:https://mp.weixin.qq.com/s/RwzprbY2AhdgslY8tbVL-A

一、前言

你会对你用到都技术,好奇吗?

虽然我们都被称为码农,也都是写着代码,但因为所处场景需求的不同,所以各类码农也都做着不一样都事情。

有些人统一规范、有些人开发组件、有些人编写业务、有些人倒腾验证,但越是工作内容简单如CRUD一样的码农,用到别人提供好的东西却是越多。一会安装个插件、一会引入个Jar包、一会调别人个接口,而自己的工作就像是装配工,东拼拼西凑凑,就把产品需求写完了。

坏了,这么干可能几年下来,也不会有什么技术上都突破。因为你对那些使用都技术不好奇,不想知道它们是怎么实现的。就像阿里的P3C插件,是怎么检查代码分析出来我写的拉胯的呢?

二、P3C 插件是什么

P3C 是阿里开源代码库的插件工程名称,它以阿里巴巴Java开发手册为标准,用于监测代码质量的 IDEA/Eclipse 插件。

  • 源码:https://github.com/alibaba/p3c

插件安装完成后,就可以按照编程规约,静态分析代码中出现的代码:命名风格、常量定义、集合处理、并发处理、OOP、控制语句、注释、异常等各项潜在风险,同时会给出一些优化操作和实例。

  • 在遵守开发手册标准并按照插件检查都情况下,还是可以非常好的统一编码标准和风格都,也能剔除掉一些潜在都风险。
  • 如果你是新手编程用户或者想写出标准都代码,那么非常建议你按照这样都插件来辅助自己做代码开发。当然如果你所在的公司也有相应都标准手册和插件,也可以按照后遵守它都约定的。

三、P3C 插件源码

在最开始使用这类代码检查都插件的时候,就非常好奇它是怎么发现我的屎山代码的,用了什么样都技术原理呢,如果我能分析下是不是也可以把这样都技术手段用到其他地方。

在分析这样一个代码检查插件前,先思考要从 IDEA 插件都源码查起,看看它是什么个逻辑,之后分析具体是如何使用都。其实这与一些其他的框架性源码学习都是类似的,拿到官网都文档、GitHub 对应的源码,按照步骤进行构建、部署、测试、调试、分析,进而找到核心原理。

P3C 以 IDEA 插件开发为例,主要涉及到插件部分和规约部分,因为是把规约检查的能力与插件技术结合,所以会涉及到一些 IDEA 开发的技术。另外 P3C 插件涉及到都技术语言不只是 Java 还有一部分 kotlin 它是一种在 Java 虚拟机上运行的静态类型编程语言。

  • 插件源码:https://github.com/alibaba/p3c/blob/master/idea-plugin
  • 规约源码:https://github.com/alibaba/p3c/tree/master/p3c-pmd

1. 插件配置 p3c.xml

<action class="com.alibaba.p3c.idea.action.AliInspectionAction" id="AliP3CInspectionAction"popup="true" text="编码规约扫描" icon="P3cIcons.ANALYSIS_ACTION"><keyboard-shortcut keymap="$default"first-keystroke="shift ctrl alt J"/><add-to-group group-id="MainToolBar" anchor="last"/><add-to-group group-id="ProjectViewPopupMenu" anchor="last"/><add-to-group group-id="ChangesViewPopupMenu" anchor="last"/><add-to-group group-id="EditorPopupMenu" anchor="last"/>
</action>
  • 翻看源码最重要是要找到入口,这个入口通常也是你在使用插件、程序、接口等时候,最直接进入都那部分。
  • 那么我们在使用 P3C 插件的时候,最明显的就是 编码规约扫描 通过源码中找到这个关键字,看它都涉及了哪个类都配置。
  • action 是 IDEA 插件中用于配置窗体事件入口都地方,以及把这个操作配置到哪个按钮下和对应都快捷键。

2. 编码规约扫描( AliInspectionAction)

class AliInspectionAction : AnAction() {override fun actionPerformed(e: AnActionEvent) {val project = e.project ?: returnval analysisUIOptions = ServiceManager.getService(project, AnalysisUIOptions::class.java)!!analysisUIOptions.GROUP_BY_SEVERITY = trueval managerEx = InspectionManager.getInstance(project) as InspectionManagerExval toolWrappers = Inspections.aliInspections(project) {it.tool is AliBaseInspection}val psiElement = e.getData<PsiElement>(CommonDataKeys.PSI_ELEMENT)val psiFile = e.getData<PsiFile>(CommonDataKeys.PSI_FILE)val virtualFile = e.getData<VirtualFile>(CommonDataKeys.VIRTUAL_FILE)...createContext(toolWrappers, managerEx, element,projectDir, analysisScope).doInspections(analysisScope)
}
  • 这是一个基于 kotlin 语言开发的插件代码逻辑,它通过 actionPerformed 方法获取到工程信息、类信息等,接下来就可以执行代码检查了 doInspections

3. 规约 p3c-pmd

当我们再往下翻看阅读的时候,就看到了一个关于 pmd 的东西。PMD 是一款采用 BSD 协议发布的Java 程序静态代码检查工具,当使用PMD规则分析Java源码时,PMD首先利用JavaCC和EBNF文法产生了一个语法分析器,用来分析普通文本形式的Java代码,产生符合特定语法结构的语法,同时又在JavaCC的基础上添加了语义的概念即JJTree,通过JJTree的一次转换,这样就将Java代码转换成了一个AST,AST是Java符号流之上的语义层,PMD把AST处理成一个符号表。然后编写PMD规则,一个PMD规则可以看成是一个Visitor,通过遍历AST找出多个对象之间的一种特定模式,即代码所存在的问题。该软件功能强大,扫描效率高,是 Java 程序员 debug 的好帮手。

那么 p3c-pmd 是什么呢?

ViolationUtils.addViolationWithPrecisePosition(this, node, data,I18nResources.getMessage("java.naming.ClassNamingShouldBeCamelRule.violation.msg",node.getImage()));
  • p3c-pmd 插件是基于 PMD 实现的,更具体的来说是基于 pmd-java 的,因为 PMD 不仅支持 Java 代码分析,还支持其他多种语言。
  • 具体自定义规则的方式,通过自定义Java类和XPATH规则实现。

四、规约监测案例

讲道理,说一千道一万,还得是拿出代码跑一下,才知道 PMD 具体是什么个样子。

1. 测试工程

guide-pmd
└── src├── main│   ├── java│   │   └── cn.itedus.guide.pmd.rule│   │       ├── naming│   │       │   ├── ClassNamingShouldBeCamelRule.java│   │       │   ├── ConstantFieldShouldBeUpperCaseRule.java│   │       │   └── LowerCamelCaseVariableNamingRule.java│   │       ├── utils│   │       │   ├── StringAndCharConstants.java│   │       │   └── ViolationUtils.java    │   │       └── I18nResources│   └── resources│       ├── rule │       │   └── ali-naming.xml  │       ├── messages.xml   │       └── namelist.properties  └── test└── java└── cn.itedus.demo.test├── ApiTest.java└── TErrDto.java
  • 源码:https://github.com/fuzhengwei/guide-pmd

这是一个类似 p3c-pmd 的测试工程,通过自行扩展重写代码监测规约的方式,来处理自己关于代码的审核标准处理。

  • naming 下的类是用于处理一些和名称相关的规则,类名、属性名、方法名等
  • resources 下 ali-naming.xml 是规约的配置文件

2. 驼峰命名规约

public class ClassNamingShouldBeCamelRule extends AbstractJavaRule {private static final Pattern PATTERN= Pattern.compile("^I?([A-Z][a-z0-9]+)+(([A-Z])|(DO|DTO|VO|DAO|BO|DAOImpl|YunOS|AO|PO))?$");@Overridepublic Object visit(ASTClassOrInterfaceDeclaration node, Object data) {if (PATTERN.matcher(node.getImage()).matches()) {return super.visit(node, data);}ViolationUtils.addViolationWithPrecisePosition(this, node, data,I18nResources.getMessage("java.naming.ClassNamingShouldBeCamelRule.violation.msg",node.getImage()));return super.visit(node, data);}
}
  • 通过继承 PMD 提供的 AbstractJavaRule 抽象类,重写 visit 方法,使用正则的方式进行验证。
  • visit 方法都入参类型非常多,分别用于处理类、接口、方法、代码等各项内容的监测处理,只要重写需要的方法,在里面进行自己都处理就可以。
  • ClassNamingShouldBeCamelRule、ConstantFieldShouldBeUpperCaseRule、LowerCamelCaseVariableNamingRule 三个类都功能类似,这里就不一一展示了,可以直接参考源码。

3. ali-naming.xml 配置

<rule name="ClassNamingShouldBeCamelRule"language="java"since="1.6"message="java.naming.ClassNamingShouldBeCamelRule.rule.msg"class="cn.itedus.guide.pmd.rule.naming.ClassNamingShouldBeCamelRule"><priority>3</priority>
</rule>
  • 在 ali-naming.xml 用于配置规约处理类、priority 级别、message 提醒文字。
  • 同时还可以配置代码示例,使用 <example> 标签,在里面写好标准代码即可。

4. 测试验证规约

问题类示例

public class TErrDto {public static final Long max = 50000L;public void QueryUserInfo(){boolean baz = true;while (baz)baz = false;}}

单元测试

@Test
public void test_naming(){String[] str = {"-d","E:\\itstack\\git\\github.com\\guide-pmd\\src\\test\\java\\cn\\itedus\\demo\\test\\TErrDto.java","-f","text","-R","E:\\itstack\\git\\github.com\\guide-pmd\\src\\main\\resources\\rule\\ali-naming.xml"// "category/java/codestyle.xml"};PMD.main(str);
}
  • 规约的测试验证可以直接使用 PMD.main 方法,在方法中提供字符串数组入参,这里的代码监测地址和规约配置需要是绝对路径。

测试结果

TErrDto.java:3:  【TErrDto】不符合UpperCamelCase命名风格
TErrDto.java:5: 常量【max】命名应全部大写并以下划线分隔
TErrDto.java:7: 方法名【QueryUserInfo】不符合lowerCamelCase命名风格Process finished with exit code 4
  • 从测试结果可以看到,我们写的三个代码规约分别监测出了代码的命名风格、常量大写、方法名不符合驼峰标识。
  • 同时你还可以测试 category/java/codestyle.xml 这个是 PMD 自身提供好的规约监测。

五、扩展了解 Sonar

其实有了 PMD 静态代码检查规约,能做都事情就很多,不是只对正在写的代码进行检查,还可以对不同阶段的代码进行分析和风险提醒,比如:准备提测阶段、已经上线完成,都可以做相应的监测处理。

而 Sonar 就是一个这样都工具,它是一个Web系统,可以展现静态代码扫描的结果,结果是可以自定义的,支持多种语言的原理是它的扩展性。https://www.sonarqube.org/

  • 不遵循代码标准:sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具规范代码编写。
  • 潜在的缺陷:sonar可以通过PMD,CheckStyle,Findbugs等等代码规则检测工具检 测出潜在的缺陷。
  • 糟糕的复杂度分布:文件、类、方法等,如果复杂度过高将难以改变,这会使得开发人员 难以理解它们, 且如果没有自动化的单元测试,对于程序中的任何组件的改变都将可能导致需要全面的回归测试。
  • 重复:显然程序中包含大量复制粘贴的代码是质量低下的,sonar可以展示 源码中重复严重的地方。
  • 注释不足或者过多:没有注释将使代码可读性变差,特别是当不可避免地出现人员变动 时,程序的可读性将大幅下降 而过多的注释又会使得开发人员将精力过多地花费在阅读注释上,亦违背初衷。
  • 缺乏单元测试:sonar可以很方便地统计并展示单元测试覆盖率。
  • 糟糕的设计:通过sonar可以找出循环,展示包与包、类与类之间的相互依赖关系,可以检测自定义的架构规则 通过sonar可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况, 检测耦合。
  • 提高代码质量:了解自己在编码过程中犯过的错误,让自己的代码更具有可读性和维护性。

六、总结

  • PMD 是一款采用 BSD 协议的代码检查工具,你可以扩展实现为自己的标准和规范以及完善个性的提醒和修复操作。
  • 另外基于 IDEA 插件实现的代码检查或者有审计要求的处理,也可以基于 IDEA 插件做更多的扩展,比如提醒修复、提供修复操作、自身业务逻辑的检查。例如momo开源库下的一款IDEA静态代码安全审计及漏洞一键修复插件 https://github.com/momosecurity/momo-code-sec-inspector-java
  • 这里补充一点,kotlin 语言可以在 IDEA 中转换为 Java 语言,这样你在阅读类似这样的代码时候,如果不好看懂也可以转换一下在阅读。此外 IDEA 插件开发需要基于 Gradle 或者本身提供都模版进行创建,如果感兴趣也可以阅读我写的 IDEA 插件开发文章。

七、系列推荐

  • 基于IDEA插件开发和字节码插桩技术,实现研发交付质量自动分析
  • 技术调研,IDEA 插件怎么开发「脚手架、低代码可视化编排、接口生成测试」?
  • 《SpringBoot 中间件设计和开发》
  • 笔记整理:技术架构涵盖内容和演变过程总结
  • 给学习加点实践,开发一个分布式IM(即时通信)系统!

p3c 插件,是怎么检查出你那屎山的代码?相关推荐

  1. 阿里代码检测p3c插件安装使用规则

    阿里在杭州云栖大会上,正式发布众所期待的<阿里巴巴Java开发规约>扫描插件! 该插件由阿里巴巴P3C项目组研发.这个项目组是阿里巴巴开发爱好者自发组织形成的虚拟项目组,把<阿里巴巴 ...

  2. bim综合建模插件 进行碰撞检查只需六步!

    一般我们bim建模进行碰撞检查的时候操作往往会比较的繁琐: 打开建筑模型>找到"协作"菜单栏下的"碰撞检查"工具>单击"运行碰撞检查&qu ...

  3. b超可以看出什么_【b超能检查出什么】b超能看出男女吗_b超能查出什么妇科病 - 妈妈网百科...

    肝胆原来也是可以通过B超来检查的,不仅能用B超检查,还能检查出不少疾病呢!如肝纤维化.肝硬化等.对于去过肝胆科的朋友们相信对肝胆B超都不陌生了,下面就来详细了解下肝胆B超都能检查什么病! 1.肝纤维化 ...

  4. Bootstrap入门(二十九)JS插件6:弹出框

    Bootstrap入门(二十九)JS插件6:弹出框 加入小覆盖的内容,像在iPad上,用于存放非主要信息 弹出框是依赖于工具提示插件的,那它也和工具提示是一样的,是需要初始化才能够使用的 首先我们引入 ...

  5. 头部ct能检查出什么_脑部ct能检查出什么

    全国体检预约平台 脑部 ct 能检查出什么 颅脑的 CT 检查具有无痛苦,方便.安全,适宜任何人群和年龄段的患者.这种检查手段也 越来越广泛的运用在各种疾病的的临床诊断检查中.因为很多脑部的一些疾病和 ...

  6. 体检做B超可以检查出肿瘤吗?

    B超是现在医学上被广泛运用的检查方式之一,有了B超检查可以说是很大程度的降低了对病人的伤害,同时获得医生想要的数据,而现在的肿瘤疾病发病率越来越高,B超是否可以检查出肿瘤呢? B超检查可以帮助我们检查 ...

  7. 前端常用插件之artDialog弹出框

    前端常用插件之artDialog弹出框 最近,发现一个插件--好看精致的页面弹出框,个人觉得有必要与大家分享一下,它就是artDialog弹出框. 引用上一篇文章<前端常用插件之art-temp ...

  8. B超检查能100%检查出胎儿畸形吗?

    来源:中国数字科技馆 随着超声诊断技术及超声仪器不断发展和临床经验的积累,人们优生观念日益增强,孕期超声检查也已成为评价胎儿生长发育.检测胎儿结构异常的重要手段.但这一检查能否100%检查出胎儿畸形? ...

  9. Mobiscroll插件-根据时间选择弹出星座

    根据Mobiscroll插件-根据时间选择弹出星座,没办法,博客发文长度有限制,只有添加到外链.有需要的话把外链的下载过来 自己修改整理一下. 基于插件粗鲁修改的,没有优化.用的时候自己优化一下吧! ...

最新文章

  1. ZABBIX(八) Zabbix 通知媒介
  2. 信息熵是什么 转 理论吃透的创新解释
  3. SQL 判断两个时间段是否有交叉
  4. 小程序确定取消弹窗_微信小程序定制开发价格确定条件?
  5. css背景上能添加文字,CSS3怎么为文字添加背景?
  6. 华中科技大学应用高等工程数学_专业解析【第152期】| 机械电子工程课程设置及研究方向...
  7. 谈谈一些有趣的CSS题目(十六)-- 奇妙的 background-clip: text
  8. 【Blog.Core开源】将Program升级为.NET6.0版本
  9. 7款最流行的在线项目管理工具推荐
  10. Spring-bean的循环依赖以及解决方式___Spring源码初探--Bean的初始化-循环依赖的解决
  11. 怎样在半年内把一个团队带垮?
  12. Android 对Layout_weight属性完全解析以及使用ListView来实现表格
  13. 学会 配置文件+反射,走遍全球都不怕.
  14. 联合查询(union)——MySQL
  15. Android编译环境搭建
  16. 数据中台-标签体系介绍
  17. Android 2.3应用开发实战
  18. 为你开发的应用赋能文档协作功能
  19. BUUCTF——rsa系列(4)
  20. 我把皮小浪の的 蓝色妖姬系列做进了java窗口

热门文章

  1. 让你永远忘不了的傅里叶变换解析
  2. Unity AzureKinect 初识(二) 姿势识别
  3. Oracle 外部表
  4. 网络安全面试题目及详解
  5. ThreadPoolTaskScheduler实现动态管理定时任务
  6. win10monkey安装教程_详解win10下pytorch-gpu安装以及CUDA详细安装过程
  7. uefi怎么念_UEFI模式和32位64位系统安装的简单说明
  8. OUTLOOK 邮箱发件人请求已读回执
  9. 某招聘网站“数据分析”相关岗位招聘信息爬取并分析
  10. Hadoop Ha集群配置