• Android打造专有Hook第四篇,实战增量代码规范检查


    系列文章目录

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

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

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

    Hello啊各位老铁,上篇的文章,我们把全量代码规范检查做了一个整体的实现,唯独缺少了关于增量代码的检查,今天,这篇我们就重点把增量这块,做一个简单的分析。

    在全量文件检查中,我们只需要得到Git提交的文件,然后逐一针对文件内容,获取,做相关的逻辑检查即可,但是增量就不能这样搞了,我们都知道,每次增量的提交,是没有规律可言的,也许增量中只有一行,也许有百行,而且增量的代码位置,有可能是在方法中,有可能是在资源中,所以针对增量代码的检查,是必须要做出取舍的,因为,通过一行,或者几行,很难达到一定的规范标准,OK,废话不多说,我们开搞!

    今天的内容大概如下

    1、增量代码简单说明

    2、增量中如何获得代码

    3、增量代码规范检查

    4、补充说明

    一、增量代码简单说明

    前边说过,增量代码相对于全量代码有着巨大的差异,在增量代码中,所提交的更改代码,有可能是没有包含我们所制定的规范的,比如下面的这段提交的增量代码:

    1. + val strings: List<String> = token.split(".")
    2. + if (strings.size != 3) {
    3. + LogUtil.d("Incorrect token, strings size = ${strings.size}")
    4. + return default
    5. + }
    6. +

    从上边的增量代码中,你能判断什么?方法命名规范?方法注释规范,变量命名规范?还是其他的规范,根据我们的规范标准,其实啥也判断不了,所以,在增量代码的提交中,我们需要着重和我们的规范标准进行相匹配,既然匹配,那么我们就不得不做出一些取舍,也就是说,有些能规范检查的,我们进行检查,不能做检查的,我们只能舍弃。

    二、增量中如何获得代码

    增量代码检查的前提,必须得到当前所提交的增量代码,如何获取到增量代码呢?Git中给我们提供了相关命令,如下,通过下述的命令,我们就可以得到当前commit的所有提交文件的增量代码,并生成我们指定的对应文件。

    git diff >> androidCommit.diff

    需要注意的是,增量代码的生成,是生成到一个文件下,而且必须是在命令行的情况下才会生效,所以啊,各位老铁,使用增量代码检查时,一定要注意这个,并且在暴露给开发者的时候,在配置文件里也一定要标注。

    当命令执行后,所生成的增量内容大致如下(检查的代码都是用于测试的,大家只关注增量提交的信息即可):

    1. diff --git a/app/src/HomeActivity.kt b/app/src/HomeActivity.kt
    2. index 29ef3c5..0cdc619 100644
    3. --- a/app/src/HomeActivity.kt
    4. +++ b/app/src/HomeActivity.kt
    5. @@ -701,7 +701,8 @@ class HomeActivity : DataBindingBaseActivity<ActivityHomeBinding, HomeViewModel>
    6. }
    7. - override fun onResume() {
    8. +
    9. +override fun onResume() {
    10. super.onResume()
    11. mActivityStatus = ACTIVITY_ON_RESUME
    12. }
    13. @@ -727,7 +728,9 @@ class HomeActivity : DataBindingBaseActivity<ActivityHomeBinding, HomeViewModel>
    14. }
    15. - fun on_sHttp(){
    16. +
    17. +
    18. + fun on_sHttp(){
    19. }
    20. diff --git a/app/src/HomeViewModel.kt b/app/src/HomeViewModel.kt
    21. index 477da32..c43897e 100644
    22. --- a/app/src/HomeViewModel.kt
    23. +++ b/app/src/HomeViewModel.kt
    24. @@ -59,6 +59,7 @@ import org.json.JSONObject
    25. class HomeViewModel(app: Application) : AppBarBaseViewModel<PickupMessageRepository, IAppBarProcessor>(app) {
    26. val mText: MutableLiveData<String> = MutableLiveData()
    27. +
    28. var badgeByTypeBean = MutableLiveData<List<BadgeByType>>()
    29. init {
    30. @@ -147,6 +148,12 @@ class HomeViewModel(app: Application) : AppBarBaseViewModel<PickupMessageReposit
    31. return default
    32. }
    33. + val strings: List<String> = token.split(".")
    34. + if (strings.size != 3) {
    35. + LogUtil.d("Incorrect token, strings size = ${strings.size}")
    36. + return default
    37. + }
    38. +
    39. return try {
    40. val decoded = String(Base64.decode(strings[1], Base64.DEFAULT), charset("UTF-8"))
    41. val jsonObject = JSONObject(decoded)
    42. diff --git a/gitExec.js b/gitExec.js
    43. index dd9288b..21d452d 100644
    44. --- a/gitExec.js
    45. +++ b/gitExec.js
    46. @@ -95,8 +95,6 @@ let lint = function (cb) {
    47. }
    48. cb(1);
    49. }
    50. -
    51. -
    52. };
    53. let taskList = [lint];

    各位老铁看后,感觉怎么样,如何从这些增量内容中,检查相关代码是否符合规范呢?是不是很乱,是不是毫无头绪?其实我刚一看到后,也是一脸懵逼,类命名规范,方法命名规范,注释检查等,从何搞起呢?静下心来慢慢分析后,其实也就那么回事。

    从增量提交的内容来看,凡是进行过更改的文件,前缀都有一个”+++ b“,大家可以实际的观察下,既然每个更改的文件都有这样的一个标识,我们是不是可以通过它,来截取到所提交的文件,这种方式是可行的,当然了,除了这种方式之外,大家也可以按照全量代码检查中的,文件列表获取,来判断相关的文件命名是否规范。

    文件的命名规范,比如类,layout,图片等,可以按照上述所说的规则,那么针对string的Name是否规范呢?其实也简单,通过”+++ b“分割后,遍历判断每一个元素是否包含string.xml,如果包含,直接遍历每一行的内容,下面的逻辑判断和全量中的基本上类似了。

    增量中,还有一个需要解决的是,方法命名规范和变量命名规范如何实现,同样的,也是需要在增量代码中进行寻找规则,以”+++ b“分割后,通过遍历,找到有相关内容,并且是类的提交规则,比如是否包含了”@@“和”+ “,然后再进行文件名子的截取,是否包含”kt“和”java“之后,就可以进行这两个功能的判断了。

    三、增量代码规范检查

    关于增量代码检查,我这里分为了两步,一步是和全量一样,拿到提交的文件,针对提交上来的文件做命名规范检查,另一步则是针对增量内容进行拆解,检查string的Name和类中的方法名和变量是否规范。

    比如图片和layout 规范检查、类的名字是否规范检查,这个在上篇文章全量检查中已经分析过了,这里就不重复了,关于这两块,其实就是截取,然后进行规则判断,大家看上一篇即可。

    1. /**
    2. * 增量文件检查
    3. * */
    4. function checkDiffFile(cb, stdout, dirname) {
    5. //通过切割换行,拿到文件列表
    6. let array = stdout.split('\n');
    7. // 去掉最后一个换行符号
    8. array.pop();
    9. log('【针对以上提交文件检查结果如下:】\n', 1);
    10. //遍历文件,检查相关规范是否符合
    11. array.forEach(function (value) {
    12. if (((value.indexOf("png") !== -1
    13. || value.indexOf("jpg") !== -1
    14. || value.indexOf("gif") !== -1
    15. || value.indexOf("webp") !== -1) ||
    16. (value.indexOf("layout") !== -1 &&
    17. value.indexOf("xml") !== -1)) && (
    18. mCommitType.indexOf("0") !== -1 ||
    19. mCommitType.indexOf("2") !== -1 ||
    20. mCommitType.indexOf("3") !== -1
    21. )) {
    22. //图片或者layout 规范检查
    23. checkImageOrLayout(value);
    24. } else if (value.indexOf("kt") !== -1 || value.indexOf("java") !== -1) {
    25. //Kotlin或者Java,规范检查
    26. let lastPosition = value.lastIndexOf("/");
    27. let className = value.substring(lastPosition + 1, value.length);
    28. //检查类的名字是否规范
    29. checkClassName(className, value);
    30. }
    31. });
    32. //生成增量文件,并使用命令,写入增量代码
    33. fs.writeFile(dirname + "/androidCommit.diff", "", function (err) {
    34. if (err) {
    35. log('增量检查中断', 0);
    36. return;
    37. }
    38. exec('git diff >> androidCommit.diff', function (error, stdout, stderr) {
    39. //增量代码写入后,进行读取diff文件
    40. checkDiff(cb, dirname);
    41. });
    42. });
    43. setTimeout(function () {
    44. console.log("\n");
    45. if (isCheck) {
    46. cb(1);
    47. } else {
    48. log("增量检查完毕,暂未发现问题,真棒!!!\n", 2);
    49. cb(0);
    50. }
    51. }, 1500);
    52. }

    string文件Name是否符合规范,以及类文件中的方法命名和方法注释是否规范,这几种规范检查是通过增量内容进行判断的,具体的判断如下:

    1、执行增量文件生成命令

    增量检查和全量最大不同就是,增量需要执行命令,生成增量文件,所以在暴露给开发者的时候,配置文件中,这一项如果打开,那么就需要选择命令行方式进行检查,这个在实际的研发中已经验证,工具的方式无法生成增量文件。

    1. exec('git diff >> androidCommit.diff', function (error, stdout, stderr) {
    2. //增量代码写入后,进行读取diff文件
    3. checkDiff(cb, dirname);
    4. });

    2、string的Name规范检查

    string的Name检查,在增量中并不复杂,首先通过”+++ b“进行分割,在遍历的时候,针对每个元素进行判断,看是否包含”string.xml“和”“关键字。

    1. //读取增量文件代码
    2. let data = fs.readFileSync(dirname + "/androidCommit.diff", 'utf-8');
    3. if (data === "" || data == null) {
    4. log("\n【增量代码无法检查】,这种情况下请您Github上Issues反馈\n", 0);
    5. return;
    6. }
    7. log('\n增量代码文件生成中\n', 1);
    8. //获取到所有的问题内容后
    9. let diffArray = data.split("+++ b");
    10. if (mCommitType.indexOf("0") !== 0 ||
    11. mCommitType.indexOf("1") !== 0) {
    12. diffArray.forEach(function (value) {
    13. //判断string
    14. if (value.indexOf("function") === -1 &&
    15. value.indexOf("string.xml") !== -1
    16. && value.indexOf("") !== -1) {
    17. //string文件
    18. var mName;
    19. value.split(/\r?\n/).forEach((line, position) => {
    20. if (position === 0) {
    21. let moduleName = line.trim().substring(1, line.length);
    22. let moduleIndex = moduleName.indexOf("/");
    23. mName = moduleName.substring(0, moduleIndex);
    24. }
    25. if (line.indexOf("") !== -1) {
    26. //判断string name
    27. if (mName.indexOf("app") === -1 && mName.indexOf("libBase") === -1) {
    28. let stringArr = line.split("name=\"");
    29. stringArr.forEach(function (item, position) {
    30. let i = item.indexOf("\"");
    31. let endString = item.substring(0, i);
    32. if (endString !== "" && !endString.startsWith(mName)) {
    33. //开头不是
    34. isCheck = true;
    35. log("【" + mName + "模块中string文件,name为" + endString + "】,命名不规范", 0);
    36. }
    37. });
    38. }
    39. }
    40. });
    41. }
    42. });
    43. }

    3、方法命名规范和变量命名规范检查

    方法的检查,我是通过是否包含“@@”和“+ ”后,在遍历每一行的信息,kotlin判断是否包含“fun”,java的话是通过“) {”来截取判断,当然了,目前的判断中还是有瑕疵的,但匹配度完全可以。变量的话,针对Kotlin的var和val变量来采取判断,大家可以看下面的逻辑判断。

    1. /**
    2. * 增量代码进行检查是否规范
    3. * */
    4. function checkDiff(cb, dirname) {
    5. //判断类
    6. setTimeout(function () {
    7. diffArray.forEach(function (value) {
    8. if (value.indexOf("@@") !== -1 && value.indexOf("+ ") !== -1) {
    9. var mFileName = "";
    10. value.split(/\r?\n/).forEach((line, position) => {
    11. if (position === 0 && line.startsWith("/")) {
    12. //文件名
    13. mFileName = line.trim();
    14. }
    15. //java和kt
    16. if (mFileName.indexOf("kt") !== -1 || mFileName.indexOf("java") !== -1) {
    17. //增量代码就得另类考虑和判断了
    18. //1 先判断方法名字
    19. if (line.indexOf("fun") !== -1 && (
    20. mCommitType.indexOf("0") !== -1 ||
    21. mCommitType.indexOf("7") !== -1
    22. )) {
    23. //kotlin方法
    24. let funIndex = line.indexOf("fun");
    25. let funString = line.substring(funIndex + 3, line.length).trim();
    26. let funEnd = funString.split("(")[0];
    27. //判断方法名字
    28. if (checkCase(funEnd.substring(0, 1)) || funEnd.indexOf("_") !== -1) {
    29. isCheck = true;
    30. log("【" + mFileName + "】中的方法" + funEnd + ",不符合规范,请您整改", 0);
    31. }
    32. }
    33. if ((line.indexOf(") {") !== -1 || line.indexOf("Exception {") !== -1) && (
    34. mCommitType.indexOf("0") !== -1 ||
    35. mCommitType.indexOf("7") !== -1
    36. )) {
    37. //java方法
    38. let javaIndex = line.indexOf("(");
    39. let javaMethods = line.substring(0, javaIndex);
    40. let javaMArray = javaMethods.split(" ");
    41. let methodName = javaMArray[javaMArray.length - 1];
    42. if ((checkCase(methodName.substring(0, 1)) || methodName.indexOf("_") !== -1)
    43. && methodName !== "") {
    44. isCheck = true;
    45. log("【" + mFileName + "】中的方法" + methodName + ",不符合规范,请您整改", 0);
    46. }
    47. }
    48. //2判断变量
    49. if ((line.indexOf("var") !== -1 || line.indexOf("val") !== -1) &&
    50. line.indexOf("+") !== -1
    51. ) {
    52. // kotlin变量
    53. //1、包含= 2包含 :
    54. var kotlinArr = [];
    55. if (line.indexOf(":") !== -1) {
    56. kotlinArr = line.split(":");
    57. } else {
    58. kotlinArr = line.split("=");
    59. }
    60. let varA = kotlinArr[0].trim();
    61. let varEndArr = varA.split(" ");
    62. let varEnd = varEndArr[varEndArr.length - 1];
    63. //判断变量的名字
    64. if ((checkCase(varEnd.substring(0, 1))
    65. || varEnd.indexOf("_") !== -1)) {
    66. const p = /^[A-Z_]*$/g;
    67. if (!p.test(varEnd)) {
    68. isCheck = true;
    69. log("【" + mFileName + "】中的变量" + varEnd + ",不符合规范,请您整改", 0)
    70. }
    71. }
    72. }
    73. }
    74. });
    75. }
    76. });
    77. }, 300);
    78. }

    四、补充说明

    增量代码检查,目前可实现的功能没有全量的多,而且在相关的判断中,很多暂时无法百分百的进行检查,毕竟脱离了Android的环境,不能准确的获取到相关类,相关资源,相关方法,只能通过共性,来实现我们的规范检查,话又说回来,虽然不能百分百,但通过类似的比较之后,也能够满足大部分的检查需求。

    好了老铁们,关于Android端的GitHook规范检查,我们基本上阐述完毕了,如果大家只是使用的话,看第1篇即可,如果想亲手搞一个的话,可以看2至4篇,有些代码写的不够清晰,也比较繁琐,毕竟咱也不是专职搞Web的,大家多包涵点看,待我后续工作不忙后,再仔细的优化一下,也可以直接去Github上下载后,直接改即可,上篇已经贴了地址,这里在贴一下:

    https://github.com/AbnerMing888/AndroidGitHook

    代码有了,功能也有了,如何打包让别人使用呢?这个总结到下篇文章吧,其实就是把目前的代码上传到npm官网,让别人可以通过命令安装,具体的效果大家可以看第1篇文章。

  • 相关阅读:
    深入探讨Spring Boot:实现一个完整的RESTful应用程序
    unity【动画】操作_角色动画控制器 c#
    如何使用 Node.js 发送电子邮件全解和相关工具推荐
    C嘎嘎 - 函数与指针
    大二学生web期末大作业 在线电影网站 HTML+CSS+JS
    二叉树的性质
    2022 杭电多校 第一场
    Flutter Cocoon 已达到 SLSA 2 级标准的要求
    【C语言】用冒泡排序实现my_qsort
    网络文件传输程序设计(上)
  • 原文地址:https://blog.csdn.net/ming_147/article/details/127091868