13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

P3c插件,是怎么检查出你不靠谱的代码?

本文转载自微信公众号「bugstack虫洞栈」,作者小傅哥。转载本文请联系bugstack虫洞栈公众号。

一、前言

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

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

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

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

二、P3C 插件是什么

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

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

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

三、P3C 插件源码

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

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

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

1. 插件配置 p3c.xml

 
 
 
 
  1.         popup="true" text="编码规约扫描" icon="P3cIcons.ANALYSIS_ACTION">
  2.     
  3.                        first-keystroke="shift ctrl alt J"/>
  4.     
  5.     
  6.     
  7.     

2. 编码规约扫描( AliInspectionAction)

 
 
 
 
  1. class AliInspectionAction : AnAction() {
  2.     override fun actionPerformed(e: AnActionEvent) {
  3.         val project = e.project ?: return
  4.         val analysisUIOptions = ServiceManager.getService(project, AnalysisUIOptions::class.java)!!
  5.         analysisUIOptions.GROUP_BY_SEVERITY = true
  6.         val managerEx = InspectionManager.getInstance(project) as InspectionManagerEx
  7.         val toolWrappers = Inspections.aliInspections(project) {
  8.             it.tool is AliBaseInspection
  9.         }
  10.         val psiElement = e.getData(CommonDataKeys.PSI_ELEMENT)
  11.         val psiFile = e.getData(CommonDataKeys.PSI_FILE)
  12.         val virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE)
  13.         
  14.   ...
  15.   
  16.   createContext(
  17.      toolWrappers, managerEx, element,
  18.      projectDir, analysisScope
  19.   ).doInspections(analysisScope)
  20. }  

这是一个基于 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 是什么呢?

 
 
 
 
  1. ViolationUtils.addViolationWithPrecisePosition(this, node, data,
  2.     I18nResources.getMessage("java.naming.ClassNamingShouldBeCamelRule.violation.msg",
  3.         node.getImage()));

p3c-pmd 插件是基于 PMD 实现的,更具体的来说是基于 pmd-java 的,因为 PMD 不仅支持 Java 代码分析,还支持其他多种语言。

具体自定义规则的方式,通过自定义Java类和XPATH规则实现。

四、规约监测案例

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

1. 测试工程

 
 
 
 
  1. guide-pmd
  2. └── src
  3.     ├── main
  4.     │   ├── java
  5.     │   │   └── cn.itedus.guide.pmd.rule
  6.     │   │       ├── naming
  7.     │   │       │   ├── ClassNamingShouldBeCamelRule.java
  8.     │   │       │   ├── ConstantFieldShouldBeUpperCaseRule.java
  9.     │   │       │   └── LowerCamelCaseVariableNamingRule.java
  10.     │   │       ├── utils
  11.     │   │       │   ├── StringAndCharConstants.java
  12.     │   │       │   └── ViolationUtils.java    
  13.     │   │       └── I18nResources
  14.     │   └── resources
  15.     │       ├── rule 
  16.     │       │   └── ali-naming.xml  
  17.     │       ├── messages.xml   
  18.     │       └── namelist.properties  
  19.     └── test
  20.         └── java
  21.             └── cn.itedus.demo.test
  22.                 ├── ApiTest.java
  23.                 └── TErrDto.java

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

2. 驼峰命名规约

 
 
 
 
  1. public class ClassNamingShouldBeCamelRule extends AbstractJavaRule {
  2.     private static final Pattern PATTERN
  3.             = Pattern.compile("^I?([A-Z][a-z0-9]+)+(([A-Z])|(DO|DTO|VO|DAO|BO|DAOImpl|YunOS|AO|PO))?$");
  4.     @Override
  5.     public Object visit(ASTClassOrInterfaceDeclaration node, Object data) {
  6.         if (PATTERN.matcher(node.getImage()).matches()) {
  7.             return super.visit(node, data);
  8.         }
  9.         
  10.         ViolationUtils.addViolationWithPrecisePosition(this, node, data,
  11.                 I18nResources.getMessage("java.naming.ClassNamingShouldBeCamelRule.violation.msg",
  12.                         node.getImage()));
  13.         return super.visit(node, data);
  14.     }
  15. }

3. ali-naming.xml 配置

 
 
 
 
  1.       language="java"
  2.       since="1.6"
  3.       message="java.naming.ClassNamingShouldBeCamelRule.rule.msg"
  4.       class="cn.itedus.guide.pmd.rule.naming.ClassNamingShouldBeCamelRule">
  5.     3

4. 测试验证规约

问题类示例

 
 
 
 
  1. public class TErrDto {
  2.     public static final Long max = 50000L;
  3.     public void QueryUserInfo(){
  4.         boolean baz = true;
  5.         while (baz)
  6.             baz = false;
  7.     }
  8. }

单元测试

 
 
 
 
  1. @Test
  2. public void test_naming(){
  3.     String[] str = {
  4.             "-d",
  5.             "E:\\itstack\\git\\github.com\\guide-pmd\\src\\test\\java\\cn\\itedus\\demo\\test\\TErrDto.java",
  6.             "-f",
  7.             "text",
  8.             "-R",
  9.             "E:\\itstack\\git\\github.com\\guide-pmd\\src\\main\\resources\\rule\\ali-naming.xml"
  10.             // "category/java/codestyle.xml"
  11.     };
  12.     PMD.main(str);
  13. }

测试结果

 
 
 
 
  1. TErrDto.java:3: 【TErrDto】不符合UpperCamelCase命名风格
  2. TErrDto.java:5: 常量【max】命名应全部大写并以下划线分隔
  3. TErrDto.java:7: 方法名【QueryUserInfo】不符合lowerCamelCase命名风格
  4. Process finished with exit code 4

从测试结果可以看到,我们写的三个代码规约分别监测出了代码的命名风格、常量大写、方法名不符合驼峰标识。

同时你还可以测试 category/java/codestyle.xml 这个是 PMD 自身提供好的规约监测。

五、扩展了解 Sonar

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

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

六、总结

PMD 是一款采用 BSD 协议的代码检查工具,你可以扩展实现为自己的标准和规范以及完善个性的提醒和修复操作。

另外基于 IDEA 插件实现的代码检查或者有审计要求的处理,也可以基于 IDEA 插件做更多的扩展,比如提醒修复、提供修复操作、自身业务逻辑的检查。例如momo开源库下的一款IDEA静态代码安全审计及漏洞一键修复插件 https://github.com/momosecurity/momo-code-sec-inspector-java

这里补充一点,kotlin 语言可以在 IDEA 中转换为 Java 语言,这样你在阅读类似这样的代码时候,如果不好看懂也可以转换一下在阅读。此外 IDEA 插件开发需要基于 Gradle 或者本身提供都模版进行创建,如果感兴趣也可以阅读我写的 IDEA 插件开发文章。


本文名称:P3c插件,是怎么检查出你不靠谱的代码?
分享地址:http://cdbrznjsb.com/article/cdghhid.html

其他资讯

让你的专属顾问为你服务