- 背景
在软件开发过程中,不规范的代码和违规组件的引⼊常常会导致代码质量下降和给项⽬引⼊⻛险。⽽在持续集成业务中,现有代码规范扫描拦截发⽣在代码push时候,违规组件拦截发⽣在⽣成构建产物后,发现问题时间点较晚,为了将质量卡点进⼀步左移、降低研发⼈员因代码准⼊失败造成的返⼯成本、提⾼代码编写质量,需要寻求上述问题场景的解决⽅案。
2. ⽅案
经过插件⽅案的调研与验证,我们基于intellij平台开发了Aladdin研发插件,插件主要提供增量代码扫描,扫描规则基于Alibaba编码规范条款,和研发中⼼组件使⽤规约,提供多种扫描⽅式为:实时增量代码扫描、编译时增量代码扫描、提交前增量扫描、⼿动全局代码扫描、⼿动增量代码扫描。同时提供提交问题拦截和扫描⽅式配置。
- 插件功能实现原理
3.1 注册Inspection
想要对代码进⾏扫描,我们需要向idea注册⼀个Inspection检查器,当编辑器中代码发⽣变动或者保存代码时,都会调⽤这个检查器,扫描代码,注册渲染问题描述到对应代码中。
● 开发⼀个⾃定义inspection , ⾸先要注册我们的增量inspection, 在插件项⽬中
\src\main\resources\META-INF\plugin.xml 插件配置⽂件中配置我们的增量⾼危代码分析inspection
XML
1
<extensions defaultExtensionNs="com.intellij">
2
<localInspection language="JAVA"
3
shortName="AladdinCodeStyleP1Incr"
4
displayName="增量⾼危代码分析"
5
hasStaticDescription="true"
6
enabledByDefault="true"
7
implementationClass="com.example.PmdP1IncrInspect ion"
8
groupName="Aladdin编码规范"
9
level="ERROR"
10
runForWholeFile="true"
11 />
12 </extensions>
● 注册好Inspection后,接下来实现我们的增量代码分析功能。当idea编辑器中⽂件发⽣变动或主动保存时候,都会触发inspection的扫描,⽽Inspection可能会有很多,每⼀个都会触发⼀次,因此实时检测对性能要求⽐较⾼。明确增量代码Inspection主要有以下⼏件事情要做:
1.插件启动的时候初始化好PMD规则,并按照类型分类到不同的Inspection中
2.只分析⽬录src/main/java下的有代码变动的Java⽂件,缩⼩扫描⽂件范围
3.调⽤PMD完成增量⽂件的扫描,获取代码存在的问题
4.根据增量代码⾏来控制代码问题的注册和编辑器中的问题标注显示
初始化规则并进⾏等级分类
⾼危问题Inspection
继承PmdBaseInspection重写filterByPmdRulePriority()⽅法,将所有⾼危问题纳⼊PmdP1IncrInspection中
接下来就是实现psiElementVisitor来完成增量代码的扫描和问题注册渲染功能了,这个在下⽂具体介绍
3.2 增量代码实时扫描
3.2.1 增量代码实时扫描原理图
功能说明:编写代码时,实时对增量/变动代码进⾏扫描,并对有问题的代码标红提示,并提供快速修复功能和问题解释说明
⽬的:在存量代码不变动的情况下,希望对增量的代码进⾏代码问题扫描,防⽌新增代码引⼊代码问题
● 原理图
3.2.2 增量代码实时扫描功能说明及效果图
● 插件可配置开启实时⾼危增量代码扫描,并提供实时修复建议。
● 插件代码实时扫描,实时提供问题提示及示例。如图:
3.2.3 实时增量代码扫描原理
现在⼤部分代码扫描⼯具都是对全量代码进⾏扫描,但在⼀些情况下,如⽼项⽬的存量代码不敢轻易优化,只希望对增量代码进⾏扫描,防⽌引⼊新的代码问题,对此我们增加了增量代码扫描的功能,考虑到不同的场景对获取增量代码⾏的性能和扫描范围的要求不同,我们进⾏了⼀些探索,最终采⽤了以下两种获取增量代码⾏的⽅式:
这⾥有以下关键点:
1.实时扫描是对当前⽂件的扫描,对实时性要求⾼,应最⼩成本的实现(采⽤读取idea已有的增量⾏数据)
2.主动扫描,扫描范围为整个git项⽬中增量⽂件和变更⽂件的增量代码⾏,需要我们⾃⼰实现(这⾥加⼊扫描缓存来降低扫描增量代码⾏成本)
获取当前⽂件代码增量⾏:
⾸先,我们观测到idea本身就帮助我们计算了增量⾏数据,编辑器⻚⾯就有体现,直接试⽤idea的api:
project.getLineStatusManager().getLineStatusTracker
获取使⽤即可,如下图所示:
核⼼代码:
1.idea提供了PsiElementVisitor抽象类扩展点visitFile()可完成代码扫描功能
2.我们实现⾃⼰的PsiElementVisitor ,来完成代码问题扫描、注册、渲染的逻辑
3.3 ⾼危组件实时扫描
3.3.1 ⾼危组件实时扫描原理图
功能说明:对新引⼊或者已修改组件进⾏依赖扫描(根据Aladdin已配置的违规组件),包括新引⼊组件的直接或者间接依赖组件。
⽬的:当前阶段,线上在跑带有⾼危组件的应⽤已全部完成治理,为了防⽌新的⾼危组件引⼊,增加了增量组件扫描功能。
● 原理图:
3.3.2 ⾼危组件实时扫描功能说明及效果图
● ⾼危组件实时扫描并提供修复建议,仅针对新添加或修改组件
● ⾼危组件配置与Aladdin持续集成系统保持⼀致,且可实时配置⽣效
3.3.3 增量组件扫描原理
实现增量组件扫描有以下关键点:
1.获取增量组件(git show⽐对pom⽂件变化)
2.获取增量组件和其依赖组件的依赖关系(idea已经帮我们分析好了,我们直接读取idea依赖树上的依赖关系)
3.将增量组件信息传给Aladdin持续化集成平台进⾏组件规范扫描并缓存扫描结果
计算增量组件
获取增量组件及其间接依赖 ⻛险分析 缓存分析结果
IDEA 已经将maven项⽬的maven依赖树解析完毕,通过上述过程获取到增量依赖后,可直接从maven依赖树中获取增量依赖包下边所有间接依赖。
实现⻛险组件结果⻚⾯渲染 Inspection
3.4 代码提交⾃动扫描
3.4.1 代码提交拦截扫描原理图
功能说明: 代码push时若增量⽂件存在Block等级问题将被拦截提醒,并提示编译/组件依赖/代码规约等问题数量,可查看详情
⽬的: 希望对增量代码进⾏编译问题/组件依赖问题/代码问题扫描拦截说明,防⽌⾼危问题遗漏
● 原理图:
3.4.2 代码提交拦截核⼼功能说明及效果图
● 代码提交前,插件会进⾏⼀次增量代码扫描,依据Aladdin中站点设置的开关进⾏提醒拦截,以代替体验较差、⽂案不清晰的Aladdin拦截
● 如果存在违规代码,插件会提示问题类型和个数,其中包括:语法错误问题,P3C⾼危问题,⾼⻛险组件问题,点击查看详情效果,可在问题列表中查看具体问题,对应类,代码⾏,以及修复建议
- 插件⽤户安装综合使⽤情况
⾃插件上线以来,研发中⼼整体有效⽤户安装量覆盖达到100%
代码问题拦截:Gitlab代码准⼊拦截向插件拦截转换情况如下
按周统计,随着插件⽤户使⽤⼈数增多,插件拦截问题数逐步增⻓,Gitlab代码准⼊拦截问题数逐步降低,这表明代码问题拦截逐步转移到代码开发阶段。
5. 总结&展望
Aladdin研发插件提供了⼀系列编码规范和最佳实践,能够⾃动检测代码中潜在问题并给出警告或错误提示。使⽤插件有以下好处 :
● 统⼀代码规范:基于Alibaba编码规范条款,和研发中⼼组件使⽤规约提供⼀套认可的编码规范。
● 前置发现潜在问题:插件可检测代码中潜在问题,有助于提⾼代码质量和稳定性,将质量问题拦截左移,降低拦截打回的成本。
● 规范编码习惯:插件提供很多实⽤的代码提示和建议,从⽽写出更健壮的代码。
● 通过扫描新引⼊依赖包:拦截⻛险组件,防⽌引⼊新的⻛险组件。
在未来的规划中,我们将继续对插件进⾏迭代升级
1.开发定制化代码规范,如定制化⽇志规范等,逐步优化完善出适合我们⾃⼰的⼀套规范
2.增加本地的增量单元测试覆盖率功能,实现增量代码覆盖率分析等
作者介绍
● swj,信也科技后端研发专家,主要负责基⽯
● zhx,信也科技后端研发专家,主要负责aladdin、rubik、tcm
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。