系列文章目录

Android打造专有hook,让不规范的代码扼杀在萌芽之中

Android打造专有hook第二篇,走进规范第一步

上篇文章,环境已经搭建,初始化程序已经完成,所需要的配置文件也均已创建,后面就是着手业务逻辑编写了,各位老铁,准备,开干!开干前,需要再次补充一下,虽是Android端的规范检查,但开发语言是Js,所以啊,各位铁子,不了解的话,抽个时间,看一看Js相关的语法,这么说吧,简单,毕竟我们都是掌握过高级编程语言的人,学起来,真的,没那么难,还是那句话,得得确确没时间学的话,也问题不大,跟着我的脚步,一步步执行,加上相关注释的理解,我相信,搞出来属于自己公司的规范,也只是时间的问题,况且,大部分的场景,我也基本上都会实现,最后也会开源给大家,大家完全可是使用我的,或者在我的基础之上更改即可。

目前的规范检查,我分为了全量文件检查和增量文件检查,基本上和Git提交保持一致,在实际的业务中,开发者可以动态修改配置文件参数gitIncrement,来切换是增量还是全量,增量和全量有一些是共通的地方,接下来的代码中会陈述。

最终的所有代码开源地址如下:

https://github.com/AbnerMing888/AndroidGitHook

今天的主要概述内容如下:

1、获取Git提交文件列表

2、判断提交文件类型

3、各中规范类型规范检测

4、补充说明

一、获取Git提交文件列表

在上篇中,我们定义了四个变量,临时存储了获取配置文件中的参数,下面我们就可以根据这些参数,来进行逻辑的处理。

首先根据mCommitOpen变量,判断开关是否打开,如果为true,证明需要进行Git规范检查,否则就是不需要,直接绿色通道,正常执行即可。在mCommitOpen为true之后,紧接着需要判断mCommitIncrement变量,判断是增量规范检查还是全量文件检查。

无论是增量检查还是全量检查,针对文件的名字,图片的名字等,都是要获取提交的文件列表的,而获取提交的文件列表,需要执行Git相关命令,这个命令是:

git diff HEAD --name-only --diff-filter=ACMR

通过执行上述的命令,我们就可以拿到本次提交修改过的文件,进而就可以针对这些文件进行遍历检查了,代码如下,由于增量和全量检查,所输出的日志信息不一样,以及所判断的逻辑也是不一样的,需要进行分别处理。

 //根据配置文件进行逻辑判断//如果mCommitOpen为true,意味着git开关打开,需要执行检查if (mCommitOpen.indexOf("true") !== -1) {//mCommitIncrement是否为true,true:增量检查(仅仅适用于命令行操作),false:整个文件的检索if (mCommitIncrement.indexOf("true") !== -1) {console.log("");log('增量检查中,铁子,开始了哦~', 1);} else {//进行整个文件的检查,全量检查console.log("\n");log('铁子,我要开始检查你的代码了!', 1);}// 通过node子进程执行git命令,查看提交的文件列表exec('git diff HEAD --name-only --diff-filter=ACMR', function (error, stdout, stderr) {if (stdout) {//先检查文件名字是否符合规范log("这次你commit文件列表如下:\n", 1);console.log(stdout + "\n");if (mCommitIncrement.indexOf("true") !== -1) {//执行增量文件检查//获取当前项目根路径let path = require('path');let dirname = path.join(__dirname);checkDiffFile(cb, stdout, dirname);} else {//整个文件开始逐一排查checkFile(stdout, cb);}return;}//没有文件,直接放行log("铁子,你的代码暂时没得问题,放行!\n", 1);cb(0);});} else {//如果mCommitOpen为false,意味着不检查,直接绿色通道,通过cb(0);}

二、判断提交文件类型

在第一步中,我们通过Git命令拿到了所更改的文件,在上面的代码中,根据全量还是增量,分别定义了不同的方法,checkFile和checkDiffFile,在这两个方法里就是针对所有的更改文件进行规范的检查,大家重点关注这两个方法即可,log方法第二章中有过讲述,就是用来输出日志信息的,就是一个简单的打印。

目前配置文件中,列出了9种类型的判断,上篇文章说过,我们再来看下配置文件定义的参数gitCheckType,这个是自己定义的,需要暴露给使用者的,所以啊,老铁,根据自己公司的规范标准来。

#git检测类型,0:全部,1:string文件Name,2:图片命名,3:layout,4:类命名,
#5:类注释,6:方法注释,7:方法命名,8:变量命名,9:try catch
gitCheckType=0

以上的9种类型,通过拆分,我们可以发现,4到9,都是通过类文件进行判断的,而1到3是根据文件名字进行判断的,在实际的规范检查中,我们就可以按条件进行判断。

在第一项中,我们通过命令已经拿到了文件的列表,而且还定义了两个方法,增量和全量,但是,我们拿到的文件列表是一个字符串,如果要获得每一个文件,那么我们就需要进行切割,由于文件都是一行一个,我们就可以以“\n”的方式进行分割,当然了,对于最后一个换行符号我们是要进行去掉的。

 let path = require('path');let dirname = path.join(__dirname);let array = files.split('\n');//通过切割换行,拿到文件列表array.pop();// 去掉最后一个换行符号log('【针对以上提交文件检查结果如下:】\n', 1);array.forEach(function (value) {//value 就是每一个文件});

拿到Git所提交的每一个文件,其实我们已经完成了一大步了,起码说,规范的前提所需要的条件,均已具备,后面就是针对这些提交的文件,进行逐个的规范检查了,9种类型,我们已经划分,下面针对9种类型如何做判断做一个简单的概述。

1、类文件

类文件暂时只包含java和Kotlin文件,如果大家想要拓展其他的文件类型,比如Flutter的项目等,大家可以自己定义,毕竟程序是自己搞的,想搞成什么,如何搞,还不是自己说的算,是吧,老铁!OK,针对这样的文件,我用的方法比较简单,你提交的kotlin文件,肯定以”kt“结尾,同样,提交的java文件,也肯定以”java“结尾,直接判断当前的文件名字是否包含”kt“或者”java“这不就搞定了,哈哈,老铁们,是不是特简单,类文件判断之后,就可以针对类文件,进行一系列的规范检查编写,如,类命名,类注释,方法命名,方法注释,变量等等,后面我们会一一阐述。

2、图片文件

和类文件一样的道理,还是用文件的结尾进行判断,一个图片有哪几种格式,肯定是固定的,比如png,jpg,gif,webp等等,只需要判断是否包含这些结尾的文件格式即可。

3、layout资源文件

layout需要注意,不仅要以最后的结尾xml来判断,还要判断当前的目录是不是在layout目录下,比较drawable下也有很多的xml资源,这个需要大家注意一下。

4、string文件Name

没什么好说的,直接判断文件名字是否包含”string“即可。

如果大家想要拓展,这里简单补充一下,关于文件命名是否规范,我的判断宗旨是,提交上来的文件,是否包含某一个特性,比如上述所说的类文件和图片文件,以及xml文件等等,都可以按照这样的逻辑进行判断,大家可以看下面的代码。

全量检查代码类型判断

/*** 整个文件进行检查,也就是全量文件检查* files:当前commit的文件列表* cb:进程,1,终止,0,执行* */
function checkFile(files, cb) {let path = require('path');let dirname = path.join(__dirname);let array = files.split('\n');//通过切割换行,拿到文件列表array.pop();// 去掉最后一个换行符号log('【针对以上提交文件检查结果如下:】\n', 1);array.forEach(function (value) {//判断文件是什么类型if (value.indexOf("kt") !== -1 || value.indexOf("java") !== -1) {//kotlin文件或者java文件checkClassOrString(dirname + "/" + value, value, 0);} else if (value.indexOf("string") !== -1 && (mCommitType.indexOf("0") !== -1 ||mCommitType.indexOf("1") !== -1)) {//string文件name命名规范检查checkClassOrString(dirname + "/" + value, value, 1);} else if ((value.indexOf("png") !== -1|| value.indexOf("jpg") !== -1|| value.indexOf("gif") !== -1|| value.indexOf("webp") !== -1) &&(mCommitType.indexOf("0") !== -1 ||mCommitType.indexOf("2") !== -1)) {//图片文件命名规范检查checkImageOrLayout(value);} else if ((value.indexOf("layout") !== -1 &&value.indexOf("xml") !== -1) && (mCommitType.indexOf("0") !== -1 ||mCommitType.indexOf("3") !== -1)) {//layout 检查资源命名规范检查checkImageOrLayout(value);}});setTimeout(function () {console.log("\n");if (isCheck) {cb(1);} else {log("所有文件均检查完毕,暂未发现问题,真棒!!!\n", 2);cb(0);}}, 1500);}

增量检查代码类型判断

/*** 增量文件检查* */
function checkDiffFile(cb, stdout, dirname) {//通过切割换行,拿到文件列表let array = stdout.split('\n');// 去掉最后一个换行符号array.pop();log('【针对以上提交文件检查结果如下:】\n', 1);//遍历文件,检查相关规范是否符合array.forEach(function (value) {if (((value.indexOf("png") !== -1|| value.indexOf("jpg") !== -1|| value.indexOf("gif") !== -1|| value.indexOf("webp") !== -1) ||(value.indexOf("layout") !== -1 &&value.indexOf("xml") !== -1)) && (mCommitType.indexOf("0") !== -1 ||mCommitType.indexOf("2") !== -1 ||mCommitType.indexOf("3") !== -1)) {//图片或者layout 规范检查checkImageOrLayout(value);} else if (value.indexOf("kt") !== -1 || value.indexOf("java") !== -1) {//Kotlin或者Java,规范检查let lastPosition = value.lastIndexOf("/");let className = value.substring(lastPosition + 1, value.length);//检查类的名字是否规范checkClassName(className, value);}});//生成增量文件,并使用命令,写入增量代码fs.writeFile(dirname + "/androidCommit.diff", "", function (err) {if (err) {log('增量检查中断', 0);return;}exec('git diff >> androidCommit.diff', function (error, stdout, stderr) {//增量代码写入后,进行读取diff文件checkDiff(cb, dirname);});});setTimeout(function () {console.log("\n");if (isCheck) {cb(1);} else {log("增量检查完毕,暂未发现问题,真棒!!!\n", 2);cb(0);}}, 1500);
}

无论增量还是全量,上面的代码在程序结束的时候,都做了一个延时操作,此延时的目的在于等待上述检查的程序执行,因为检查各个规范是耗时的,为了避免还未检查完毕就结束,所以做了一个延时操作,不过大家在实际的开发中,可以采用逐个检查,也就是同步检查,一个检查完毕再执行另一个,直至检查结束,再进行进程判断也可以的,人云亦云,看大家实际的操作了。

对了,还有一个isCheck变量,它是定义的一个全局变量,我们是要根据这个变量来决定最终的执行程序。

//这个比较重要的,要用这个变量定义最终的执行程序  false符合,通过,不提示,true不符合,不符合就要终止执行,给出提示
var isCheck = false;

三、各中规范类型规范检测

各位老铁,需要注意是的,无论检查什么规范,前提一定得有自己的一套规范标准,我们所有的程序编写都是根据这套标准而来的,而不是凭空的捏造,我相信大家公司基本上都有,我们要做的就是,把公司的标准做成程序的检查。

根据上述的9中类型,无论增量还是全量,都进行了文件类型的判断,下面,我们针对不同的类型进行一一的拆解。

1、kotlin文件或者java文件相关规范检查

针对类文件的检查,上述已经说过,包含了,类命名,方法命名,类注释,方法注释,变量命名等,我们看下面的代码,由于类文件和String的Name检查公用了一个方法,这里用了一个type做了区分,为了保证程序的执行顺序,我这里简单的一一做了延时操作,当然了,大家如果有更好的方式,可以自行修改。

/*** 检查类文件或者String文件* type:0,kotlin文件或者java文件,1,string文件name命名规范检查* */
function checkClassOrString(path, value, type) {let moduleName = getModuleName(value);//模块名字let data = fs.readFileSync(path, 'utf-8');// 拿到文件内容if (type === 0) {//java和kotlin文件//首先检查命名,然后在类注释,方法,变量等let lastPosition = value.lastIndexOf("/");let className = value.substring(lastPosition + 1, value.length);//首先检查类命名是否规范checkClassName(className, value);setTimeout(function () {//检查类注释是否规范if (mCommitType.indexOf("0") !== -1 || mCommitType.indexOf("5") !== -1) {checkClassNotes(className, data);}}, 200);setTimeout(function () {//检查方法注释是否规范if (mCommitType.indexOf("0") !== -1 || mCommitType.indexOf("6") !== -1) {checkMethodNotes(className, data);}}, 400);setTimeout(function () {//检查方法命名是否规范if (mCommitType.indexOf("0") !== -1 || mCommitType.indexOf("7") !== -1) {checkMethodName(className, data);}}, 600);setTimeout(function () {//检查变量命名是否规范if (mCommitType.indexOf("0") !== -1 || mCommitType.indexOf("8") !== -1) {checkVariableName(className, data);}}, 800);setTimeout(function () {//检查try catch 是否添加if (mCommitType.indexOf("0") !== -1 || mCommitType.indexOf("9") !== -1) {checkTry(className, data);}}, 1000);} else if (type === 1) {// stringif (moduleName.indexOf("app") === -1 && moduleName.indexOf("libBase") === -1) {let stringArr = data.split("name=\"");stringArr.forEach(function (item, position) {if (item.indexOf("encoding") === -1) {let i = item.indexOf("\"");let endString = item.substring(0, i);if (endString !== "" && !endString.startsWith(moduleName)) {//开头不是isCheck = true;log("【" + value + "中,name为" + endString + "】,命名不规范", 0);}}});}}
}

针对上述代码,我把关于类的相关规范都定义了不同的方法,简单检查罗列一下,分享如下,还是那句话,这些所谓的规范检查,你必须有一套属于自己的规范标准。

类命名是否规范

类命令,无非就是,检查下是否是大驼峰命名规则,我这里简单的以首字母是否是大写,还有是否有下划线进行判断了,大家可以自行更改。

/*** 检查类的名字是否规范* */
function checkClassName(className, value) {if (mCommitType.indexOf("0") !== -1|| mCommitType.indexOf("4") !== -1) {if (!checkCase(className.substring(0, 1)) ||className.indexOf("_") !== -1) {//不符合isCheck = true;log("【" + value + "】,类命名不规范", 0);}}
}

检查类注释是否规范

类注释,我们公司定义的是必须包含,author,date,desc这个三个参数,我的判断就是是否包含了这三个参数,没包含就提示不规范,当然了,大家可以按照自己公司的标准去执行即可。

/*** 类注释检查是否规范* */
function checkClassNotes(className, data) {if (data.indexOf("{") !== -1) {let dd = data.split("{")[0];if (dd.indexOf("author") === -1|| dd.indexOf("date") === -1|| dd.indexOf("desc") === -1) {//不符合isCheck = true;log("【" + className + "】,类注释不规范", 0);}}
}

方法注释是否规范

方法注释,这个稍微逻辑复杂些,第一,首先,得找到方法,第二,判断是否有”//“,”*/“,相关注释标准,第三,一些重写的方法就没必要添加注释了,还有就是,java和Kotlin的方法定义还不太一样,kotlin是”fun“来定义,Java就更不规则了,目前我的判断代码如下,基本上可以实现,问题不大,哈哈~

/*** 检查方法注释是否规范* */
function checkMethodNotes(className, data) {var eachOk = 0;var eachNo = 0;var caseNode = [];//不符合的方法if (className.indexOf("kt")) {//kotlinlet kotlin = data.split("fun");kotlin.forEach(function (item, position) {let endItem = item.trim();let override = endItem.substring(endItem.length - 20, endItem.length);//判断是否包含if (position !== kotlin.length - 1) {if (override.indexOf("override") === -1) {let endM = kotlin[position + 1];//有注释的也要另行添加let kE = endItem.lastIndexOf("}");let endK = endItem.substring(kE, endItem.length);if (endK.indexOf("//") !== -1 || endK.indexOf("*/") !== -1) {//带有注释eachOk++;} else {//没有注释//不符合的方法let tr = endM;if (tr != null) {let positionCase = tr.indexOf("(");let endCase = tr.substring(0, positionCase);//去掉构造函数if (endCase.length < 30 && className.indexOf(endCase) === -1) {eachNo++;caseNode.push(endCase);}}}}}});} else {//java//遍历方法let java = data.split(") {");java.forEach(function (item, position) {if (item.indexOf("public") !== -1|| item.indexOf("protected") !== -1|| item.indexOf("private") !== -1) {//判断是否包含}if (item.indexOf("}") !== -1) {let lastDesc = item.lastIndexOf("}");let endDesc = item.substring(lastDesc, item.length);if (endDesc.indexOf("Override") === -1) {if (endDesc.indexOf("//") !== -1 || endDesc.indexOf("/*") !== -1) {//包含eachOk++;} else {if (item.indexOf("while") === -1&& item.indexOf("if") === -1&& item.indexOf("for") === -1) {//添加方法let lastK = item.lastIndexOf("(");let lasetContent = item.substring(0, lastK);let endContent = lasetContent.split(" ");//取最后一个let javaMethod = endContent[endContent.length - 1];if (className.indexOf(javaMethod) === -1) {//不符合的方法eachNo++;caseNode.push(javaMethod);}}}}} else {let lastPrivate = item.lastIndexOf("private");let lastPublic = item.lastIndexOf("public");let lastProtected = item.lastIndexOf("protected");var endLast = lastPrivate;if (lastPublic > endLast) {endLast = lastPublic;}if (lastProtected > endLast) {endLast = lastPublic;//获取最后一个}let endString = item.substring(endLast - 50, endLast);if (endString.indexOf("Override") === -1) {if (endString.indexOf("//") !== -1 || endString.indexOf("*/") !== -1) {//包含eachOk++;} else {//添加方法let lastK = item.lastIndexOf("(");let lasetContent = item.substring(0, lastK);let endContent = lasetContent.split(" ");//取最后一个let javaMethod = endContent[endContent.length - 1];if (className.indexOf(javaMethod) === -1) {//不符合的方法eachNo++;caseNode.push(javaMethod);}}}}}});}if (eachNo !== 0) {isCheck = true;log("\n【" + className + "】,未添加注释的方法如下:\n", 1);log(caseNode, 0);}
}

方法命名是否规范

这个相对于方法注释,就简单了许多了,无非就是获取方法名字,然后这对方法名字判断是否符合公司定义的规范即可,没啥好说的,看代码即可。

/*** 检查方法命名是否规范* */
function checkMethodName(className, data) {
//遍历方法var eachOk = 0;var eachNo = 0;var caseNode = [];//不符合的方法//遍历所有的方法,判断是kt还是javaif (className.indexOf("kt") !== 0) {//kotlinlet kotlin = data.split("fun");kotlin.forEach(function (item, position) {if (position !== 0) {//判断开头是大写还是小写let tr = item.trim();let indexCase = tr.substring(0, 1);let positionCase = tr.indexOf("(");let endCase = tr.substring(0, positionCase);if (endCase.indexOf("<") === -1&& endCase !== "" && className.indexOf(endCase) === -1) {if ((checkCase(indexCase)|| endCase.indexOf("_") !== -1)) {//不符合eachNo++;//添加方法caseNode.push(endCase);} else {//符合eachOk++;}}}});} else {//java//遍历方法let java = data.split(") {");java.forEach(function (item, position) {if (item.indexOf("public") !== -1|| item.indexOf("protected") !== -1|| item.indexOf("private") !== -1) {//获取最后一个括号let lastK = item.lastIndexOf("(");let lasetContent = item.substring(0, lastK);let endContent = lasetContent.split(" ");//取最后一个let endMethod = endContent[endContent.length - 1];if (endMethod.indexOf("<") === -1&& endMethod !== "" &&className.indexOf(endMethod) === -1&& endMethod.indexOf("(") === -1) {if (checkCase(endMethod.substring(0, 1)) || endMethod.indexOf("_") !== -1) {//不符合eachNo++;//添加方法caseNode.push(endMethod);} else {//符合eachOk++;}}}});}if (eachNo !== 0) {//不符合isCheck = true;log("\n【" + className + "】,方法命名不规范的如下:\n", 1);log(caseNode, 0);}
}

变量命名是否规范

变量的命名相对比较负责,因为Kotlin和Java所定义的变量格式是不一样的,还有就是得忽略一些常量的命名,Kotlin我是以val或者var来进行截取分割,拿到变量名,Java呢,相对就比较局限,只能以大众的常见格式进行获取,然后再进行分割,具体的,大家直接看相关代码。

/*** 检查变量命名是否规范* */
function checkVariableName(className, data) {var eachOk = 0;var eachNo = 0;var caseNode = [];//不符合的方法//遍历所有的方法,判断是kt还是javaif (className.indexOf("kt") !== -1) {//以等号分割let spD = data.split("=");spD.forEach(function (item, position) {//然后判断val 和 varlet lastVal = item.lastIndexOf("val");let lastVar = item.lastIndexOf("var");var endLast = lastVal;if (lastVar > lastVal) {endLast = lastVar;}let lastContent = item.substring(endLast, item.length);if (lastContent.indexOf("val") !== -1|| lastContent.indexOf("var") !== -1) {if (lastContent.indexOf("fun") === -1) {let endK = lastContent.split(" ")[1];//判断变量是否符合要求if (endK.indexOf("R") === -1&& endK.indexOf("!") === -1&& endK.indexOf(")") === -1&& endK.indexOf("{") === -1&& endK.indexOf("}") === -1) {if (endK.indexOf("<") === -1 && endK !== "") {//这里进行判断大小写const p = /^[A-Z_]*$/g;if (p.test(endK)) {//符合eachOk++;} else {if ((checkCase(endK.substring(0, 1))|| endK.indexOf("_") !== -1)) {//不符合eachNo++;//添加方法caseNode.push(endK);} else {//符合eachOk++;}}}}}}});} else {//java//判断let spF = data.split(";");spF.forEach(function (item, position) {let lastPrivate = item.lastIndexOf("private");let lastPublic = item.lastIndexOf("public");let lastProtected = item.lastIndexOf("protected");var endLast = lastPrivate;if (lastPublic > endLast) {endLast = lastPublic;}if (lastProtected > endLast) {endLast = lastPublic;//获取最后一个}let lastContent = item.substring(endLast, item.length);if (lastContent.indexOf("public") !== -1|| lastContent.indexOf("protected") !== -1|| lastContent.indexOf("private") !== -1) {//是否包含等号if (lastContent.indexOf("=") !== -1) {let a = lastContent.trim().split("=");let b = a[0].trim().split(" ");let endC = b[b.length - 1];if (endC.indexOf("R") === -1&& endC.indexOf("!") === -1&& endC.indexOf(")") === -1&& endC.indexOf("(") === -1&& endC.indexOf("{") === -1&& endC.indexOf("}") === -1) {//判断变量是否符合要求const p = /^[A-Z_]*$/g;if (p.test(endC)) {eachOk++;} else {if (endC.indexOf("<") === -1 && endC !== "") {if ((checkCase(endC.substring(0, 1))|| endC.indexOf("_") !== -1)) {//不符合eachNo++;//添加方法caseNode.push(endC);} else {//符合eachOk++;}}}}} else {//普通的成员变量let endItem = lastContent.trim().split(" ");let endContent = endItem[endItem.length - 1];//最后的内容if (endContent.indexOf("R") === -1&& endContent.indexOf("!") === -1&& endContent.indexOf(")") === -1&& endContent.indexOf("(") === -1&& endContent.indexOf("{") === -1&& endContent.indexOf("}") === -1) {//判断变量是否符合要求if (endContent.indexOf("<") === -1 && endContent !== "") {const p = /^[A-Z_]*$/g;if (p.test(endContent)) {eachOk++;} else {if ((checkCase(endContent.substring(0, 1))|| endContent.indexOf("_") !== -1)) {//不符合eachNo++;//添加方法caseNode.push(endContent);} else {//符合eachOk++;}}}}}}});}if (eachNo !== 0) {//不符合isCheck = true;log("\n【" + className + "】,变量命名不规范的如下:\n", 1);log(caseNode, 0);}
}

try catch 是否添加

try catch是我们公司自己定义的一项标准,就是在业务函数中,需要增加try catch,以防止由于空,类型不一等情况造成的崩溃,具体的判断就是,在获取到方法后,判断方法里是否包含try catch即可。

/*** try  catch 是否添加* */
function checkTry(className, data) {//遍历所有的方法,判断是kt还是javavar kj;if (className.indexOf("kt") !== -1) {//kotlinkj = data.split("fun");} else if (className.indexOf("java") !== -1) {//javakj = data.split("void");} else {kj = [];}//遍历方法var eachOk = 0;var eachNo = 0;kj.forEach(function (item, position) {if (position !== 0) {if (item.indexOf("try") !== -1 && item.indexOf("catch") !== -1) {//符合的方法eachOk++;} else {//不符合的方法eachNo++;}}});if (eachNo !== 0) {//不符合isCheck = true;log("【" + className + "】,检测到有未添加try catch的方法", 0);}
}

2、string文件name命名规范检查

string相对来说还是比较简单的,首先拿到string文件,然后获取文件里面的内容,接着进行关键字分割,拿到所有的name的Key,针对Key做规范检查即可,当然了,在组件化的开发中,有一些组件是不需要检查的,我们进行过滤即可,下面的代码是和类文件检查公用的,在Kotlin文件或Java文件相关检查中有。

if (moduleName.indexOf("app") === -1 && moduleName.indexOf("libBase") === -1) {let stringArr = data.split("name=\"");stringArr.forEach(function (item, position) {if (item.indexOf("encoding") === -1) {let i = item.indexOf("\"");let endString = item.substring(0, i);if (endString !== "" && !endString.startsWith(moduleName)) {//开头不是isCheck = true;log("【" + value + "中,name为" + endString + "】,命名不规范", 0);}}});}

3、图片文件命名规范检查

这里再重述一下啊各位老铁,所有的规范,前提必须得有自己的一套规范标准啊,不然,我们的程序就没有参照依据了,关于图片的规范,根据实际的规范标准,我举一个例子,下面是我们公司的规范:

图片命名规则:组件名称_(背景用bg,图片用ic,按钮用btn,分隔线用divider)_**
例如:
①、community模块下
community_ic_publish
②、common模块下
common_bg_publish
common_ic_publish

根据上述的标准,我所开发的检查如下,当然了,还是那句话,程序是活的,大家可以根据自己公司的规范标准去执行即可。

/*** 检查图片或者layout资源命名是否规范* */
function checkImageOrLayout(value) {//图片和layout  直接判断命名let moduleName = getModuleName(value);//过滤app和libBaseif (moduleName.indexOf("app") === -1 && moduleName.indexOf("libBase") === -1) {let lastPosition = value.lastIndexOf("/");let xmlName = value.substring(lastPosition, value.length);if (!xmlName.startsWith(moduleName)) {isCheck = true;log("【" + xmlName + "】,命名不规范", 0);}}
}

4、layout 检查资源命名规范检查

layout的资源命名规范检查,和上述的图片检查基本是一致的,可以进行复用。需要注意的是,组件化开发的项目,可能对于app组件以及中间层组件,组件名是可以不带的,当然了,看大家实际的业务需求,不带就进行过滤即可。

获取模块的名字,也就是当前提交的文件是属于哪个组件,这种检查方式适用于组件化开发的项目,这里我进行了一个简单的判断,主要是我们公司有的组件名字带了一个module,我这里给删除了。

/*** 获取模块的名字* */
function getModuleName(value) {let imagePosition = value.indexOf("/");var moduleName = value.substring(0, imagePosition);//模块名字//去除moduleif (moduleName.indexOf("module_") !== -1) {//包含moduleName = moduleName.replace("module_", "");}return moduleName;
}

四、补充说明

在上述中代码中,包含了所有的全量代码逻辑,但是唯独缺少了增量代码检查的逻辑,考虑到增量代码的判断和全量有着巨大的差异,毕竟增量规范检查,只检查你所提交的那部分代码,也许是一行,也许是几行,相关的逻辑判断,还是和全量有所区别的,所以啊,各位老铁,至于增量代码如何实现规范检查,我们放到下篇文章去陈述,好了,各位铁子,这篇就到这里,欢迎感兴趣的老铁,持续关注,我们下篇见。

Android打造专有Hook第三篇,实战全量代码规范检查相关推荐

  1. 一篇走心的iOS代码规范!

    前言 关于代码规范的重要性这里不做过多解释,能看到这篇文章说明你已经开始重视代码规范了(代码规范看起来是在限制你的自由和发挥,其实它是在间接的帮助你变得更优秀.). 适当的代码规范和标准绝不是消灭代码 ...

  2. zhangrelay博客置顶三篇点击量分析

    230515只有三篇置顶,如下: 分别为: 20.03.13 :  9015 22.01.12 :13729 23.04.15 :18836 熟悉zhangrelay博客风格的AI都清楚,他的博客内容 ...

  3. android emulator虚拟设备分析第三篇之pipe上的qemud service

    一.概述 本篇和第二篇是强相关的,需要结合第二篇一起看. 以boot-properties为例,注意不需要看ANDROID-QEMUD.TXT,这个是和guest os中的qemud进行相关的,已废弃 ...

  4. Android中HTTPS之一(三)具体操作(代码实现)

    一.背景 前两篇对Http和Https的原理进行了介绍,接下来是在Android代码中如何具体配置:同时再强调说明一下如果使用权威ca机构申请(购买)的证书客户端也要进行验证. 二.涉及的点 2.1 ...

  5. JAVA登录界面学生和老师_学生信息管理系统之第三篇登录界面java代码

    class DLFrame extends JFrame implements ActionListener, ItemListener {// 登录界面 JPanel p1 = null; JPan ...

  6. Android 腾讯Bugly使用(异常上报,全量升级,热更新)

    1.0.1腾讯Bugly使用(异常上报,全量升级,热更新) 说明 Bugly全量升级,热更新以及异常上报是一起集成的,还包括运营统计,本文档着重演示热更新功能. 接入步骤 1.在Project的bui ...

  7. android远程打电话,Android打电话功能 Android实战教程第三篇之简单实现拨打电话功能...

    想了解Android实战教程第三篇之简单实现拨打电话功能的相关内容吗,杨道龙在本文为您仔细讲解Android打电话功能的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Android拨打电话 ...

  8. Android Studio 插件开发详解三:翻译插件实战

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78113868 本文出自[赵彦军的博客] 系列目录 Android Gradle使用 ...

  9. [深度][PyTorch] DDP系列第三篇:实战与技巧

    [深度][PyTorch] DDP系列第三篇:实战与技巧 转自:https://zhuanlan.zhihu.com/p/250471767 零. 概览 想要让你的PyTorch神经网络在多卡环境上跑 ...

最新文章

  1. 小学生python-如何看待小学生开始学Python?
  2. Java-二叉树算法
  3. 初建FreeMarker工程
  4. Effective C# 原则48:了解更多的工具和资源(译)
  5. oracle 批量杀死 死锁进程
  6. 任正非:将来华为岗位分三类 职员类岗位不涉及末位淘汰
  7. Android Camera之SurfaceView学习
  8. 2012.4.17内存相关(二)
  9. 线性代数【六】:解线性方程组
  10. 关于工作和人生观(转)
  11. macbook 终端命令怎么使用_Mac终端怎么打开?带你全面了解在macOS中使用终端命令行...
  12. 《Javascript高级程序设计(第四版)》学习笔记(一)第1、2章
  13. 18650锂电池保护板接线图_12v锂电池保护板电路图 - 全文
  14. 通信网实验_Kruskal算法_Mininet_Ryu
  15. 【异常】Reason: Executor heartbeat timed out after 140927 ms
  16. Failed to decode response: zlib_decode(): data error Retrying with degraded mode, check https://getc
  17. 解放生产力 - Xcode 与 Simulator 技巧整理(持续更新中)
  18. 「星火计划沙龙视频」云原生数据湖专场
  19. Linux TWI开发指南
  20. amh升级php版本,AMH4.2升级PHP版本后续之组件安装

热门文章

  1. C++中的memset函数
  2. 【微信小程序】真机调试引用的外部字体不生效问题
  3. 通过云计算、大数据、人工智能等技术解决城市问题
  4. react:css样式穿透
  5. C/C++锁以及安全锁
  6. Kotlin为什么会火起来,有什么特点,跟Java区别
  7. Excel·VBA数组行列转换函数
  8. 7月火影忍者服务器维护,火影忍者OL7月23日区服停机更新公告介绍
  9. 给字符数组赋值java_给字符数组赋值的方法
  10. 英语习语集锦::recommended::