一个便捷操作的Android可视化规范检查

405 阅读7分钟

Hello啊各位铁子,今天带来一个自己开源的可视化规范检查工具,真正的懒人必备!让规范检查回归最简单,最便捷的操作流程,别说开发人员,就是一个小白也能针对项目进行熟练的规范检查操作,我先贴下地址,后面讲解实现过程。

项目开源地址:

github.com/AbnerMing88…

目前工具有九个功能,包含了,注释,类,方法,变量等基本的规范验证,如下图所示,当然也都是一些常见的规范功能检查,后续的话也会进行拓展,虽然此规范是按照我公司的标准去执行的,其实,Android嘛,大差不差,就那些规范,基本百变不离其宗,如果有不是很符合的,大家也可以在源码中进行更正为自己需要的就可以了。

项目运行效果图:

image.png

项目呢,没有选择打包进行发布,因为考虑到各个项目,各个公司的规范不一,打包的话不符合实际的开发需求,所以啊,各位铁子,大家可以down下项目,按照流程自己运行项目,然后查看实际的功能效果,当然了,你也可以针对自己公司规范,进行增加或修改已有的逻辑,使其符合本公司的规范流程措施。

规范这个东西,我相信大家的公司都会有,俗话说无规矩不成方圆,一个项目要是没有规范,每个人都按照自己的思路去编写,长此以往,大家可以想想,这样的项目会出现什么问题?这里我就不明说了,所以啊,规范是一个项目的基石,也是衡量一个项目,是否健壮,稳定,可维护的标准,可谓是相当重要的。

既然了有了这样的一套规范,那么在执行的时候,就需要去进行验证,毕竟协同开发的项目,每个人都有自己的一套开发标准,有时由于大意或疏忽,可能某一块就没有按照既定的规范去落实,那么就需要进行指正出来,然后进行修改,同样的新人接手项目,或是外包人员介入开发,就更应该进行规范的检查,从而让项目在一套标准的体系中运行。

其实市面上的规范检查工具颇多,像Lint,CheckStyle等等,要么需要一定的配置依赖,要么没有一个可以定制化的规范执行,大多数和实际的业务多多少少有些差距,基于此现状,这也是这个工具诞生的原因。工具的诞生,旨在简单便捷,提高我们的开发效率,节约我们的时间成本,使得项目稳定,可维护,基本上初衷便是如此,当然也是按照这样的准则去落实的。

Ok,侃了有点多了,说一说实现的思路吧,这个可视化的工具,是用electron进行开发的,和那个代码生成工具如出一辙,大家感兴趣的话,可以继续看,不感兴趣的话,就别看了,因为和Android知识关联性不大,[手动捂脸],直接去Github直接下载体验吧。

Electron我就不多说了,因为之前在介绍代码生成工具时,说了很多了,基本都是采用最基本的web语言去开发的,这里就不过多赘述了,简单的说几点实现思路。

一、 定位项目

定位项目,就是需要选择一个可以执行的Android项目,这是完成功能的第一步,没有项目,下面的所有功能基本无法开展。

选择项目,基本上是选择一次,在基础配置页面进行保存,然后,每个功能页面首先遍历出项目下所有存在的Module,进而针对不同Module做针对性检测。

打开一个目录使用到的是electron/ remote中的dialog模块,具体使用如下:


//引入

const dialog = require('@electron/remote').dialog;

 

//选择文件

        dialog.showOpenDialog({

            title: '请选择您的项目文件,尽量是Android项目哦~',

            properties: ['openDirectory']

        }).then(result => {

            const path = result.filePaths;

            if (path != null && path != "") {

                //选择后回显

                $(".config_file_input").val(path);

                //进行保存路径

                localStorage.setItem("select_path", path)

            }

 

        });

通过以上的代码,我们就可以针对选择的路径进行保存,目前呢,只是定位到了项目,上边说了,我们是需要定位到Module的,如何进行定位到Module,如下代码:

这里用到了fs模块,之前在讲述自动生成代码工具的时候也说过,就不多赘述了。

//引入fs模块

let fs = require('fs');

 

//取出存储的路径,不为空,进行遍历文件

if (selectPath !== "" && selectPath !== null) {

            //遍历文件

            fs.readdir(selectPath, function (err, files) {

                if (err) {

                    console.log(err);

                    return

                }

                //length 为0 证明,选择的文件路径下是空的,隐藏选择目录选项

                if (files.length === 0) {

                    isEmptyDir = true;

                    $(".data_select_file").css("display", "none");

                    return;

                }

                //不为空,就遍历当前路径下的所有的文件目录

                var isDir = false;

                files.forEach(function (item, position) {

                    let path = selectPath + "/" + item;

                    fs.stat(path, function (err, stats) {

                        if (err) {

                            return false;

                        }

                        if (stats.isDirectory()) {

                            isDir = true;

                        }

                        //最后一个判断

                        if (position === files.length - 1) {

                            //没有一个文件夹,隐藏

                            if (!isDir) {

                                isEmptyDir = true;

                                $(".data_select_file").css("display", "none");

                            }

                        }

                        //检测选择的是否是一个Android项目,通过是否包含app,gradle,settings.gradle,当然也可以判断其他

                        if (item === "app" || item === "gradle" || item === "settings.gradle") {

                            numAndroid++;

                        }

                        //判断是文件夹

                        if (stats.isDirectory()

                            && item != "build" && item != "gradle"

                            && item.indexOf(".") != 0) {

                            let nodeDiv = "<option value='" + item + "'>" + item + "</option>"

                            $(".data_file").append(nodeDiv);

                        }

                    });

                });

            });

        }

基本上,所有的功能,都是基于以上逻辑的。

二、 定位文件

可以发现目前实现的功能中,像layout,图片命名,类名检查,就属于文件类型的,针对这种文件性质的,我们就需要找到其文件,然后获取文件名字,就可以简单的判断是否符合相关规范了,比如类是否满足大驼峰,layout是否满足,小写,下划线,是否带Module前缀等等规则验证就可以实现相关功能了,图片基本上和layout类似,简单吧,其实一点技术含量没有[手动捂脸]。

layout的路径是固定的,src/main/res/layout,直接加上前边的项目路径加上Module路径就可以进行遍历了,代码就不沾了,就是一个遍历。

类文件的话,就需要循环遍历了,也就是Module下可能会有N个包,那么就需要不断的遍历出来,然后得到一个一个的文件,再进行简单的规则验证,后续的话,关于Activity,Fragment,ViewModel等一些特殊性质的,可以加上包名进行判断。

三、 代码内容截取

代码内容截取,相对稍微复杂一些,因为,得到文件之后,需要对文件中的内容进行判断,比如,类注释,方法注释,方法命名,变量检查,try catch检测等等,这一类的规范检查,都得要获取到文件内容,然后才能执行下一步的操作。

类注释就比较简单了,得到文件内容之后,无论是Java文件还是Kotlin文件,大括号肯定都是存在的,那么就截取呗,以“{ “进行截取,获取第0个,然后判断相关关键字是否存在,比如author,desc,date等,或者其他关键性的参数,不存在就意味着类注释不存在,就可以把不存在的类进行返回到页面上,让开发者做针对性修改即可。

方法注释,需要判断是Java文件还是Kotlin文件,如果是Kotlin文件,我们直接可以以“fun“关键字进行截取,如果是Java,那么就需要找每个方法的相似之处,我这边采用的是“) {”,当然了也有更好的方案,大家可以针对源码进行优化。

其他的,像方法命名,变量检查,try catch检测,基本上也是类似的寻找关键字,截取方式进行实现的,这里也不多过多赘述了,大家参考源码实现就可以了。

源码中相对来说比较乱,有些代码还没来得及优化,毕竟咱也不是专门搞Web开发了,哈哈,凑合着看吧,有问题,大家一起沟通,一起修正,毕竟这种东西的存在,多多少少的能够在规范检查上,节约我们一部分的时间。

还有啊,那个可视化的脚手架,自己也在整理,会不定期更新出来,其实也没啥技术含量,大家看前几章,估计也能搞出来,后面工作不忙了,会接着更[手动捂脸]。

疫情期间,大家多注意防护。