定制阿里代码检查,实现你自己的代码规范检查

2023-05-16

几个月前,阿里开源了p3c,我也接到了老大交给我的技术改造。是这样的,app是老项目了,半年前接入了ARouter,由于Activity繁多,就没有去全局支持ARouter,这不,技术改造来了,就是定义一个规则,全局的在项目里面搜一遍,所有Activity如果没有@Route()注解,就把它揪出来。那么来吧。

于是到同性恋交友网站(github)上面,把阿里代码检查(这里附上链接https://github.com/alibaba/p3c)下下来之后就傻眼了,用Kotlin写的,我尼玛。。。好吧骚年,撸起袖子加油干。学点Kotlin,总还是好的。

我们现在打开idea-plugin这个项目,代码主要是在p3c-common这个包里面,我们先来看一下包结构吧
这里写图片描述
这里画圈两个包比较重要,inspection是所有的检查逻辑,idea-sandbox是插件输出的位置。
那是哪里调用inspection的呢?

class AliLocalInspectionToolProvider : InspectionToolProvider {
    ...
    companion object {
            val ruleInfoMap: MutableMap<String, RuleInfo> = Maps.newHashMap<String, RuleInfo>()
            private val LOGGER = Logger.getInstance(AliLocalInspectionToolProvider::class.java)
            val ruleNames: MutableList<String> = Lists.newArrayList<String>()!!
            private val CLASS_LIST = Lists.newArrayList<Class<*>>()
            private val nativeInspectionToolClass = arrayListOf<Class<out LocalInspectionTool>>(
                    AliMissingOverrideAnnotationInspection::class.java,
                    TuoMissingAcitvityRouteInspection::class.java,
                    AliAccessStaticViaInstanceInspection::class.java,
                    AliDeprecationInspection::class.java,
                    MapOrSetKeyShouldOverrideHashCodeEqualsInspection::class.java,
                    AliArrayNamingShouldHaveBracketInspection::class.java,
                    AliControlFlowStatementWithoutBracesInspection::class.java,
                    AliEqualsAvoidNullInspection::class.java,
                    AliLongLiteralsEndingWithLowercaseLInspection::class.java,
                    AliWrapperTypeEqualityInspection::class.java
            )
            ...
    }
    ...
}

我们看到这个数组常量nativeInspectionToolClass,这里装的就是你点击检查时候检查的所有规则的类。

private fun initNativeInspection() {
            val pool = ClassPool.getDefault()
            pool.insertClassPath(ClassClassPath(DelegateLocalInspectionTool::class.java))
            nativeInspectionToolClass.forEach {
                pool.insertClassPath(ClassClassPath(it))
                val cc = pool.get(DelegateLocalInspectionTool::class.java.name)
                cc.name = "Delegate${it.simpleName}"
                val ctField = cc.getField("forJavassist")
                cc.removeField(ctField)
                val itClass = pool.get(it.name)
                val toolClass = pool.get(LocalInspectionTool::class.java.name)
                val newField = CtField(toolClass, "forJavassist", cc)
                cc.addField(newField, CtField.Initializer.byNew(itClass))
                CLASS_LIST.add(cc.toClass())
            }
        }

就是在initNativeInspection这个初始化本地检查的方法里面遍历的。ok。再往上代码我们就不看啦,因为我们只要模仿着写一个Inspection类,然后手动添加到那个List,然后编译插件就ok了。

接下来就是该写写检查的规则类了,这里我以我自己需求出发来分析,然后你们只要举一反三就好了。

/*
* 这边要继承BaseInspection,AliBaseInspection
* BaseInspection是IDEA源码里面的基础类
* AliBaseInspection是阿里提供的基础类
* 这两个类是一定要实现的
* */
class TuoMissingAcitvityRouteInspection : BaseInspection, AliBaseInspection {

    private val messageKey = "com.alibaba.p3c.idea.inspection.tuotuo.TuoMissingAcitvityRouteInspection"

    constructor()

    /**
     * For Javassist
     */
    constructor(any: Any?) : this()

    //规程的标题
    override fun ruleName(): String {
        return "MissingAcitvityRouteRule"
    }

    //错误信息
    override fun buildErrorString(vararg infos: Any): String = P3cBundle.getMessage("$messageKey.errMsg")

    //错误提示标题
    override fun getDisplayName(): String = "Your activity should add route"

    //错误提示内容体
    override fun getStaticDescription(): String? = "Your activity should add route !!!"

    //错误的等级
    override fun getDefaultLevel(): HighlightDisplayLevel = HighlightDisplayLevels.CRITICAL

    //规则的短标题
    override fun getShortName(): String = "TuoMissingAcitvityRoute"

    //是否默认开启
    override fun isEnabledByDefault(): Boolean = true

    //回调一个遍历的类,这个类是由IDEA自己去控制的
    override fun buildVisitor(): BaseInspectionVisitor {
        return MissingActivityRouteVisitor()
    }

    /*
    * 这里是规则的具体写法,比较灵活,自己的业务可以看一下别的规则的实现来推导自己的实现
    * 我这里只要是如果这个类名字里面包含了Activity,就去拿它的注解,
    * 如果注解为空,或者说注解列表里面不包含"com.alibaba.android.arouter.facade.annotation.Route"
    * 即表示没有添加过路由,就会通过registerClassError(aClass)输出错误信息
    * */
    class MissingActivityRouteVisitor : BaseInspectionVisitor() {
        override fun visitClass(aClass: PsiClass?) {
            super.visitClass(aClass)
            if (aClass == null) return

            if (TextUtils.isEmpty(aClass.name) || !aClass.name!!.contains("Activity")) {
                return
            }

            if (hasRouteOverrideAnnotation(aClass)) {
                return
            }
            registerClassError(aClass)
        }

        private fun hasRouteOverrideAnnotation(
                element: PsiModifierListOwner): Boolean {
            val modifierList = element.modifierList ?: return false
            val annotation = modifierList.findAnnotation("com.alibaba.android.arouter.facade.annotation.Route")
            return annotation != null
        }
    }

}

其实代码检查还提供一个快速修复的fix功能,比如官方提供的实现里面有这样一个场景,找到所有需要加@override但是没有加上@override的方法,然后检查出来之后,会通过

@Override
  public JComponent createOptionsPanel() {
    final MultipleCheckboxOptionsPanel panel =
      new MultipleCheckboxOptionsPanel(this);
    panel.addCheckbox(InspectionGadgetsBundle.message(
      "ignore.equals.hashcode.and.tostring"), "ignoreObjectMethods");
    panel.addCheckbox(InspectionGadgetsBundle.message(
      "ignore.methods.in.anonymous.classes"),
                      "ignoreAnonymousClassMethods");
    return panel;
  }

提供一个操作界面,点击后会调用

@Override
  protected InspectionGadgetsFix buildFix(Object... infos) {
    return new MissingOverrideAnnotationFix();
  }

  private static class MissingOverrideAnnotationFix
    extends InspectionGadgetsFix {

    @Override
    @NotNull
    public String getName() {
      return InspectionGadgetsBundle.message(
        "missing.override.annotation.add.quickfix");
    }
    @Override
    @NotNull
    public String getFamilyName() {
      return getName();
    }

    @Override
    public void doFix(Project project, ProblemDescriptor descriptor)
      throws IncorrectOperationException {
      final PsiElement identifier = descriptor.getPsiElement();
      final PsiElement parent = identifier.getParent();
      if (!(parent instanceof PsiModifierListOwner)) {
        return;
      }
      final PsiModifierListOwner modifierListOwner =
        (PsiModifierListOwner)parent;
      final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
      final PsiElementFactory factory = psiFacade.getElementFactory();
      final PsiAnnotation annotation =
        factory.createAnnotationFromText("@java.lang.Override",
                                         modifierListOwner);
      final PsiModifierList modifierList =
        modifierListOwner.getModifierList();
      if (modifierList == null) {
        return;
      }
      modifierList.addAfter(annotation, null);
    }
  }

dofix就是快速修复代码,这两个都是通过BaseInspection实现的。由于我这边的需求不需要智能修复,就没去写fix啦。

然后写完了代码就是打包插件了,我这里花了很多时间,给张截图给老铁们,蟹蟹捧场关注了
这里写图片描述
buildPlugin就可以啦,输出文件就在刚才讲的p3c-idea/idea-sandbox下面啦。然后你就自己玩去吧。自己定义自己的代码检查。哎呦,还蛮酷的哦!

给出本人定制的代码规范的github地址(https://github.com/mengxin1995/p3c),可以看看提交记录学习。

参考文章 :AndroidStudio 插件开发(Hello World 篇)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

定制阿里代码检查,实现你自己的代码规范检查 的相关文章

  • 年度回忆录(2013.01----2013.12)

    看了一下上次的年度总结是从 2013 年 2 月份开始的 xff0c 按照以往的习惯 xff0c 年度回忆录是半年一写的 xff0c 这次居然破例了 xff01 由于工作的原因吧 xff08 这是找借口的节奏么 xff09 xff0c 没有
  • 使用JMF实现音乐播放(java多媒体编程)

    JMF实际上是Java的一个类包 JMF 2 1 1技术提供了先进的媒体处理能力 xff0c 从而扩展了 Java平台 的功能 这些功能包括 xff1a 媒体捕获 压缩 流转 回放 xff0c 以及对各种主要媒体形式和编码的支 持 xff0
  • Pygame下载和安装

    Pygame 的下载非常简单 xff0c 可分为两种方式 xff1a 一是通过 Python 的包管理器 pip 来安装 xff1b 二是下载二进制安装包进行安装 其中使用 pip 包管理器安装是最简单 最轻量级的方法 xff0c 下面以
  • 物联网毕业设计 stm32四轴飞行器设计与实现

    1 简介 Hi xff0c 大家好 xff0c 今天向大家介绍一个学长做的单片机项目 基于stm32的四轴飞行器设计 大家可用于 课程设计 或 毕业设计 这次尝试制作一个四旋翼飞控的过程 这个飞控是基于STM32 xff0c 整合了MPU6
  • 机器学习(周志华)学习笔记八:集成学习(上)

    一 AdaBoost思想 三个臭皮匠 xff0c 顶个诸葛亮 xff0c 这也正是集成学习的目的 为了达到上述目的 xff0c AdaBoost算法有两个核心思想 1 更加关注之前基学习器做错的样本 xff1b 2 降低错误率较高的基学习器
  • opencv在编译报错的汇总

    Q1 xuy 64 xuy 桌面 opencv test make usr bin cmake home xuy anaconda2 lib libcurl so 4 no version information available req
  • 至简设计系列_闹钟

    作者 xff1a 小黑同学 本文为明德扬原创及录用文章 xff0c 转载请注明出处 xff01 1 1 1 概述 数字时钟是采用数字电路技术实现时 分 秒计时显示的装置 xff0c 可以用数字同时显示时 xff0c 分 xff0c 秒的精确
  • 遥控器对码与飞控解锁

    今天开始DIY 四旋翼 xff0c 购买了 mwc 飞控和天地飞六代遥控器 xff0c 装好电机电调后 xff0c 想试一下遥控控制电机 首先是遥控发射器与接收器的对码 将电调连上电机后 xff0c 单独把电调的杜邦线插口查到接收器油门插槽
  • Git保存论文

    多图预警 多图预警 多图预警 多图预警 操作步骤 下载git for windows客户端安装TortoiseGit使用Git删除文件夹再试一遍 下载git for windows客户端 下载地址 http msysgit github i
  • Git小乌龟分支操作

    分支的创建 选择创建分支 这里填上分支名字 切换到新分支可点可不点 选中的话直接就切换到新分支 不点的话进行下一步选择切换 检出 选择要切换的分支 分支就创建完成 接下来是分支的合并 分支的合并 首先 确认当前的分支为发起合并方 个人理解
  • 零星PCB打板|开源广场|每月2张|等你来撸|保姆级教程:嘉立创免费PCB打样获取攻略

    目录 缘由 软件 xff1a 嘉立创EDA专业版 xff08 视情况下载 xff0c 非必需 xff09 软件 xff1a 嘉立创PC端下单助手 xff08 领优惠券 xff09 优惠券在这里 xff1a 嘉立创PCB免费打样新规则解读 6
  • Linux下利用GDB调试快速找到Bug

    调试程序最让人头疼的就是层出不断的Bug xff0c 而且有些Bug不容易定位 xff0c 下面介绍一种很强大的调试工具 xff1a GDB 虽然之前听过GDB调试 xff0c 但是自己调试时一直没使用过 今天在调试highmac程序时 x
  • 无状态会话bean(1)---定义

    无状态会话bean 用于完成在单个方法的生命周期内的操作 无状态bean 可以实现许多业务操作 xff0c 但是每个方法都不能假定任何其他的方法会在它之前调用 后半句的意思是现在的你可能不是刚才的你 xff0c 明天的你可也能不是今天的你
  • 树莓派(Raspberry Pi),如何在命令行下配置查看WIFI无线网络

    通常 xff0c 我们的wifi路由器都是开启了DHCP自动分配 ip地址的功能的 xff0c 本文是以这个为前提 xff0c 如果你的WIFI路由器没有开启DHCP xff0c 则在本文的基础上 xff0c 还需要给WLAN0口配置静态I
  • ubuntu虚拟机网络配置同时连接WIFI上外网和连接以太网与ARM开发板通信

    在学习ARM嵌入式开发过程中 xff0c 需要在ubuntu虚拟机下进行程序开发和编译 xff0c 一般需要使用网线直连ARM开发板 xff0c 或挂载NFS网络文件系统 xff0c 或 通过SSH TFTP等网络协议传输在PC端编译完的二
  • Systemd 服务管理教程

    Systemd 概述 Systemd 简介 Systemd 是一系列工具的集合 xff0c 其作用也远远不仅是启动操作系统 xff0c 它还接管了后台服务 结束 状态查询 xff0c 以及日志归档 设备管理 电源管理 定时任务等许多职责 x
  • 高版本Matlab运行时//在当前文件夹或MATLAB路径中未找到文件//函数或变量 ‘xx‘ 无法识别//解决方法

    当你用2019以上版本Matlab时 xff0c 可能会发现这样一个问题 xff1a 当你默默选择 更改文件夹 或者 添加到路径 后 xff0c Matlab又会输出 函数或变量 xx 无法识别 类似这样 xff1a 总之不会乖乖出现运行结
  • 美团技术十年:让我们感动的那些人那些事

    时光荏苒 xff0c 美团十岁了 xff0c 美团技术团队也走过了十个春秋 2010年3月4日美团网上线的时候 xff0c 整个公司总共十来人 xff0c 在一套三居室的民房里起步 其中技术团队只有5个人 xff0c 现在有4位还在美团 今
  • 如何在Windows上轻松安全的将数据从HDD迁移到SSD?

    当你打算升级硬盘时 xff0c 如何将数据从HDD迁移到SSD xff1f 你可以使用一款免费的软件将所有数据从一个硬盘克隆到另一个硬盘 为什么要将数据从HDD迁移到SSD xff1f HDD xff08 机械硬盘 xff09 和SSD x
  • Ubuntu 16.04安装Python3.8

    bin sh install software properties common sudo apt install software properties common install PPA sudo add apt repositor

随机推荐

  • error LNK2038: 检测到“_ITERATOR_DEBUG_LEVEL”的不匹配项: 值“0”不匹配值“2” 解决方法

    错误原因 xff0c Debug工程引用了Release版本的库文件 解决方法
  • 关于wince OS开发面试问题的总结系列之Bootloader

    参考资料 xff1a 1 Windows CE 工程事件完全解析 by xff1a 李大为 2 Windos CE 实用开发技术 by xff1a 张冬泉 等 3 Windows Embedded CE 6 0 Fundamentals 4
  • Jacobian矩阵和Hessian矩阵

    1 Jacobian 转载自 xff1a http jacoxu com p 61 146 在向量分析中 雅可比矩阵是一阶偏导数以一定方式排列成的矩阵 其行列式称为雅可比行列式 还有 在代数几何中 代数曲线的雅可比量表示雅可比簇 xff1a
  • 打工与乘公交

    去一个公司打工就如同上了一辆公交车 在上车之前 xff0c 你应该清楚自己打算去哪里 xff0c 打算在哪里下车 有的公交车很豪华 xff0c 有的很破烂 xff0c 但是这并不是重点 xff0c 所有能开到目的地的车都是好车 上了车之后
  • 卡尔曼滤波器(从vchelp的算法论坛上看到的)

    卡尔曼滤波器 Kalman Filter 1 xff0e 什么是卡尔曼滤波器 xff08 What is the Kalman Filter xff09 在学习卡尔曼滤波器之前 xff0c 首先看看为什么叫 卡尔曼 跟其他著名的理论 xff
  • 第4篇 FreeRTOS是如何工作的---基本原理3(上下文切换)

    上下文切换Context Switching 任务执行时 xff0c 它使用处理器 微控制器的寄存器并访问RAM和ROM xff0c 就像任何其他程序一样 这些资源 处理器寄存器 堆栈等 组成了任务执行上下文 任务是一段连续的代码 xff0
  • MissionPlanner-开发历程-1

    1 Mission Planner 简介 Mission Planner是使用C 开发的开源飞控地面站软件 xff0c 使用MavLink通信协议 xff0c 浏览官方网站 Mission Planner是ArduPilot开源自动驾驶项目
  • 关于SpringSecurity配置中的一些问题解决(登录页面不跳转,报错302)

    1 为何在自定义的登录页面中登录完页面不跳转 xff1f 主要是SpringSecurity在校验csrf跨域时候 xff0c 会传一个csrf相关的随机token值 xff01 在SpringSecurity 4 之后 xff0c 其cs
  • DAY2. jetson nx gpio

    更新 扩展接口说明 xff0c 官方说明文档 xff1a Jetson Xavier NX DevKit Carrier Board Specification v1 0 pdf 分割线 参照这个文档 xff1a https www jet
  • 使用kinect2进行目标跟踪-ROS平台

    之前闲得无聊 xff0c 在ROS平台上调用Kinect摄像头进行目标跟踪检测 首先 xff0c 要在ubuntu下安装好Kinect2和ROS的接口 xff0c 参考http www mamicode com info detail 15
  • 在ROS中使用opencv-灰度处理

    没什么好说的 xff0c 直接看代码理解吧 xff1a include lt ros ros h gt ros标准库头文件 include lt iostream gt C 43 43 标准输入输出库 cv bridge中包含CvBridg
  • GCC的编译流程分为了四个步骤:

    GCC的编译流程分为了四个步骤 1 预处理 xff0c 生成预编译文件 xff08 文件 xff09 xff1a Gcc E hello c o hello i 2 编译 xff0c 生成汇编代码 xff08 s文件 xff09 xff1a
  • Android自定义控件基础

    采用自定义控件解决重复编写代码的问题 总共分三步 1 写好一个自定义模板布局 title XML span class hljs pi lt xml version 61 34 1 0 34 encoding 61 34 utf 8 34
  • String,StringBuffer,StringBuilder的区别(优缺点)

    最近学习到StringBuffer xff0c 心中有好些疑问 xff0c 搜索了一些关于String xff0c StringBuffer xff0c StringBuilder的东西 xff0c 现在整理一下 关于这三个类在字符串处理中
  • nginx+tomcat重复请求

    好久不写技术文章了 xff0c 越发的觉得单纯的讲技术没啥意思 怪不得知乎越来越火 xff0c 因为大家都喜欢看故事 xff0c 不喜欢硬生生的技术文章 笔者今天就来就给大家讲故事 最近网站压力突然增大 xff0c 把带宽都占满了 xff0
  • Android真机获得root权限修改文件权限

    好久没有更新博客了 xff0c 最近因为重装了系统导致所有的配置都不存在了 xff0c 当要修改Android权限去查看数据库文件的时候 xff0c 发现又忘记了怎么去获得修改权限 xff08 其实第一次弄这个内容的时候就费了很大的劲 xf
  • Android完全自定义控件并且实现监听事件

    本篇文章带来Android的完全自定义控件 载体是自定义一个开关的控件 xff0c 并且能够响应事件 xff0c 首先我们先创一个项目 xff0c 名字就叫ToggleView xff0c 修改MainActivity span class
  • 2016年总结,辛勤劳作的一年

    直到刚才听到门外的爆竹声 才意识到这一年 xff0c 快结束了 今天是11月26号 xff0c 其实离2017年还有一段距离 xff0c 趁着今天有空 xff0c 给自己写一篇文章 其实 xff0c 我是很不想说 xff0c 你好 xff0
  • Android屏幕适配实战

    说一下在项目里面遇到的一个问题 xff0c 和解决思路 需求来源于运营小姐姐 xff0c 她们希望在App的搜索关键字前面加上图片醒目效果图如下 布局很简单左边一个SimpleDraweeView xff0c 右边一个TextView xf
  • 定制阿里代码检查,实现你自己的代码规范检查

    几个月前 xff0c 阿里开源了p3c xff0c 我也接到了老大交给我的技术改造 是这样的 xff0c app是老项目了 xff0c 半年前接入了ARouter xff0c 由于Activity繁多 xff0c 就没有去全局支持ARout