The third part of Android to create a proprietary Hook, the actual combat full code specification inspection

Series Article Directory

Android builds proprietary hooks to kill non-standard codes in the bud

The second part of Android creating proprietary hooks, the first step into the specification

In the last article, the environment has been set up, the initialization program has been completed, and the required configuration files have also been created. The next step is to write the business logic. Everyone, get ready and start! Before starting, I need to add again. Although it is a specification check on the Android side, the development language is Js . So, everyone, if you don’t understand it, take some time to take a look at the syntax related to Js. Let’s put it this way, it’s simple. After all, we are all people who have mastered high-level programming languages. It is really not that difficult to learn. It is still the same sentence. If you do not have time to learn, it is not a big problem. Follow my steps and execute step by step. , plus the understanding of relevant annotations, I believe that it is only a matter of time before I come up with my own company's specifications. Besides, I will basically realize most of the scenarios, and I will open source them to everyone in the end. You can use them at all Mine, or change based on mine.

The current standard inspection is divided into full file inspection and incremental file inspection, which are basically consistent with Git submission. In actual business, developers can dynamically modify the configuration file parameter gitIncrement to switch between incremental or full, and Quantity and full quantity have some things in common, which will be stated in the following code.

The final open source addresses of all codes are as follows:

https://github.com/AbnerMing888/AndroidGitHook

Today's key overview reads as follows:

1. Get a list of Git commit files

2. Determine the type of submitted file

3. Specification detection of various types of specifications

4. Supplementary instructions

1. Get a list of Git commit files

In the previous article, we defined four variables to temporarily store the parameters in the acquisition configuration file. Next, we can perform logical processing based on these parameters.

First, according to the mCommitOpen variable, it is judged whether the switch is turned on. If it is true, it proves that the Git specification check is required, otherwise it is not needed, and the green channel can be directly executed normally. After mCommitOpen is true, it is necessary to judge the mCommitIncrement variable to determine whether it is an incremental specification check or a full file check.

Whether it is an incremental check or a full check, for the name of the file, the name of the picture, etc., it is necessary to obtain the list of submitted files, and to obtain the list of submitted files, you need to execute a Git-related command. This command is:

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

By executing the above command, we can get the files that have been submitted and modified this time, and then we can traverse and check these files. The code is as follows. Due to the incremental and full checks, the output log information is different, and all The logic of judgment is also different and needs to be dealt with separately.

 //根据配置文件进行逻辑判断
        //如果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);
        }

2. Determine the type of submitted file

In the first step, we obtained the changed file through the Git command. In the above code, according to the full or incremental, different methods are defined, checkFile and checkDiffFile, in these two methods are for all Change the file for standard inspection. You can focus on these two methods. The log method is described in Chapter 2, which is used to output log information, which is a simple print.

In the current configuration file, there are 9 types of judgments listed. As mentioned in the previous article, let’s look at the parameter gitCheckType defined in the configuration file. This is defined by ourselves and needs to be exposed to users. So, old iron, Follow your company's standards.

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

By splitting the above 9 types, we can find that 4 to 9 are all judged by the class file, and 1 to 3 are judged by the file name. In the actual specification inspection, we can press Conditions are judged.

In the first item, we have obtained the list of files through the command, and also defined two methods, incremental and full, but the list of files we have obtained is a string. If we want to obtain each file, then We need to cut. Since the files are all one line, we can split them in the form of "\n". Of course, we need to remove the last newline symbol.

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

After getting every file submitted by Git, we have actually completed a big step. At least, the conditions required for the premise of the specification have been met. The next step is to check the specifications one by one for these submitted files. We have divided the 9 types, and the following is a brief overview of how to make judgments for the 9 types.

1. Class files

Class files only include java and Kotlin files for the time being. If you want to expand other file types, such as Flutter projects, you can define them yourself. After all, the program is made by yourself. What you want to do and how to do it are not up to you. Forget it, right, old iron! OK, for such a file, I use a relatively simple method. The kotlin file you submit must end with "kt". ​​Similarly, the java file you submit must also end with "java". Directly determine whether the current file name contains "kt" or "java" is not enough, haha, old irons, isn't it very simple, after the class file is judged, a series of specification checks can be written for the class file, such as class naming, class annotation , method naming, method annotations, variables, etc., we will explain them one by one later.

2. Image file

It is the same as the class file, and the end of the file is still used to judge. The formats of a picture must be fixed, such as png, jpg, gif, webp, etc. You only need to judge whether the file format that contains these endings is Can.

3. layout resource file

You need to pay attention to layout, not only to judge by the final ending xml, but also to judge whether the current directory is under the layout directory. Compared with drawable, there are also many xml resources. This requires everyone to pay attention.

4. string file Name

There is nothing to say, just judge whether the file name contains "string".

If you want to expand, here is a brief addition. Regarding whether the file naming is standardized, my purpose of judgment is whether the submitted file contains a certain feature, such as the above-mentioned class files and image files, and xml files, etc. , can be judged according to this logic, you can see the following code.

Full inspection code type judgment

/**
 * 整个文件进行检查,也就是全量文件检查
 * 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);
       
}

Incremental check code type judgment

/**
 * 增量文件检查
 * */
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);
}

Regardless of increment or full amount, the above code has a delay operation at the end of the program. The purpose of this delay is to wait for the execution of the above check program, because checking each specification is time-consuming, in order to avoid unchecked It ends when it is finished, so a delay operation is made. However, in actual development, you can check one by one, that is, check synchronously. After one check is completed, execute the other until the check is over, and then judge the progress. Follow what others say, let's see everyone's actual operation.

By the way, there is also an isCheck variable, which is a global variable defined, and we want to determine the final execution program based on this variable.

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

3. Specification detection of various types of specifications

Everyone, you need to pay attention. No matter what specification you check, you must have your own set of specification standards. All our programming is based on this set of standards, not fabricated out of thin air. I believe your company Basically, all we have to do is to check the company's standards into procedures.

According to the above 9 types, whether incremental or full, the file type is judged. Next, we will disassemble the different types one by one.

1. Check related specifications of kotlin files or java files

For the inspection of class files, as mentioned above, it includes class naming, method naming, class annotations, method annotations, variable naming, etc. Let’s look at the following code. Since the class file and String’s Name inspection share a method, here A type is used to distinguish. In order to ensure the execution order of the program, I simply performed delay operations one by one here. Of course, if you have a better way, you can modify it yourself.

/**
 * 检查类文件或者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) {
        // string
        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);
                    }
                }

            });
        }
    }
}

For the above code, I have defined different methods for the relevant specifications of the class. I will list them for simple inspection and share them as follows. Again, for these so-called specification inspections, you must have your own set of specification standards.

Is the class naming standard?

Class commands are nothing more than to check whether it is a big hump naming rule. Here I simply judge whether the first letter is capitalized or not, and whether there is an underscore. You can change it yourself.

/**
 * 检查类的名字是否规范
 * */
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);
        }
    }
}

Check whether the class annotation is standardized

Class annotation, our company defines three parameters that must be included, author, date, and desc. My judgment is whether these three parameters are included. Just go and execute.

/**
 * 类注释检查是否规范
 * */
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);
        }
    }
}

Are method annotations standardized?

Method annotation, this is a bit more logical, first, first, you have to find the method, second, judge whether there are "//", "*/", related annotation standards, third, some rewritten methods do not need to be added Note, and the method definitions of java and Kotlin are not the same. Kotlin is defined by "fun", and Java is even more irregular. At present, my judgment code is as follows, basically it can be realized, the problem is not big, haha ~

/**
 * 检查方法注释是否规范
 * */
function checkMethodNotes(className, data) {
    var eachOk = 0;
    var eachNo = 0;
    var caseNode = [];//不符合的方法
    if (className.indexOf("kt")) {
        //kotlin
        let 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);
    }
}

Is the method naming standard?

Compared with method annotations, this is much simpler. It is nothing more than obtaining the method name, and then judging whether the method name conforms to the specifications defined by the company. There is nothing to say, just look at the code.

/**
 * 检查方法命名是否规范
 * */
function checkMethodName(className, data) {
//遍历方法
    var eachOk = 0;
    var eachNo = 0;
    var caseNode = [];//不符合的方法

    //遍历所有的方法,判断是kt还是java
    if (className.indexOf("kt") !== 0) {
        //kotlin
        let 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);
    }
}

Is the variable naming standard?

The naming of variables is relatively responsible, because the variable formats defined by Kotlin and Java are different, and the naming of some constants has to be ignored. In Kotlin, I use val or var to intercept and divide, and get the variable name. What about Java? , is relatively limited, and can only be obtained in the common format of the public, and then divided. Specifically, you can directly look at the relevant code.

/**
 * 检查变量命名是否规范
 * */
function checkVariableName(className, data) {
    var eachOk = 0;
    var eachNo = 0;
    var caseNode = [];//不符合的方法

    //遍历所有的方法,判断是kt还是java
    if (className.indexOf("kt") !== -1) {
        //以等号分割
        let spD = data.split("=");
        spD.forEach(function (item, position) {
            //然后判断val 和 var
            let 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);
    }
}

Whether to add try catch

Try catch is a standard defined by our company. In business functions, try catch needs to be added to prevent crashes caused by empty and different types. The specific judgment is that after the method is obtained, the judgment method Whether it contains try catch or not.

/**
 * try  catch 是否添加
 * */
function checkTry(className, data) {
    //遍历所有的方法,判断是kt还是java
    var kj;
    if (className.indexOf("kt") !== -1) {
        //kotlin
        kj = data.split("fun");
    } else if (className.indexOf("java") !== -1) {
        //java
        kj = 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 file name naming convention check

string is relatively simple. First get the string file, then get the content in the file, then split the keywords, get all the keys of the name, and do a standard check on the key. Of course, in componentization In the development, there are some components that do not need to be checked. We can filter them. The following code is common to the class file check, and it is included in the related checks of Kotlin files or Java files.

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. Check the image file naming convention

Let me reiterate here, everyone, all the specifications must have their own set of specification standards, otherwise, our program will have no reference basis. Regarding the specification of pictures, according to the actual specification standards, I will give As an example, here is our company specification:

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

According to the above standards, the inspection I developed is as follows. Of course, the same sentence, the program is alive, and you can execute it according to your company's standards.

/**
 * 检查图片或者layout资源命名是否规范
 * */
function checkImageOrLayout(value) {
    //图片和layout  直接判断命名
    let moduleName = getModuleName(value);
    //过滤app和libBase
    if (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 check resource naming convention check

The layout's resource naming convention check is basically the same as the above image check, and can be reused. It should be noted that for component-based development projects, the component name may not be included for the app component and the middle layer component. Of course, depending on your actual business needs, you can filter without it.

Obtain the name of the module, that is, which component the currently submitted file belongs to. This inspection method is suitable for component-based development projects. Here I made a simple judgment, mainly because some components in our company have a module in their name. I deleted it here.

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

4. Supplementary instructions

In the above code, all the logic of the full code is included, but only the logic of the incremental code inspection is missing. Considering that there is a huge difference between the judgment of the incremental code and the full code, after all, the incremental specification inspection only checks what you have The part of the code submitted may be one line or several lines. The relevant logical judgment is still different from the full amount. So, everyone, as for how to implement the standard inspection of the incremental code, we will put it in the next article Go to the statement, well, everyone, this is the end of this article, welcome old irons who are interested, continue to pay attention, see you in the next article.

Guess you like

Origin blog.csdn.net/ming_147/article/details/126927698