lint 是什么? 维基百科中是这样说的
在计算机科学中,lint是一种工具程序的名称,它用来标记源代码中,某些可疑的、不具结构性的段落。它是一种静态程序分析工具,最早适用于C语言,在UNIX平台上开发出来。后来它成为通用术语,可用于描述在任何一种计算机程序语言中,用来标记源代码中有疑义段落的工具。

lint 其实是 c 语言中的一个工具,在 1979 年由贝尔实验室发布的。它是通过静态分析代码来检查错误的工具。后来各领域的类似工具都叫做 xx lint。比如前端领域的 eslint、stylelint 等。

lint 通过静态分析源码,对 AST 进行检查,发现其中的一些代码结构的错误,或者代码格式的错误。
代码结构的错误包括两种情况: 代码有逻辑或者语法错误,代码没错误但是不符合代码规范;
代码格式的错误则是:代码结构是对的,但是空格、换行等格式不对。
这些都需要进行 lint。
静态分析:动态指的是代码运行的时候,而静态则不会运行代码。静态是通过编译的方式来分析源代码。它的目的不是为了生成目标代码,而是为了提取一些想要的信息,这是和编译的不同之处。
parse 成 AST,对 AST 进行检查,这个事情用 babel 也可以做,这节我们就用 babel 写一个 lint 插件。
# 检查出错误的代码
代码的错误写法可能很多,就像 eslint 有一系列的 rule,我们只挑两个来实现。
# 错误的 for direction
for (var i = 0; i < 10; i--) {
}
for (var i = 10; i >= 0; i++) {
}
上面两种代码遍历方向是错误的,会导致死循环。而开发者写代码的时候一个不注意就有可能写错了,我们希望静态分析出这种错误代码,并进行编译时报错。
# 思路分析
for 语句的 AST 是 ForStatement,我们在 astexplorer.net 中来查看一下它的结构


init 部分是一个变量声明语句 VariableDeclaration。
test 部分是一个二元表达式 BinaryExpression,operator 属性为 <。
update 部分是一个一元表达式 UpdateExpression,operator 属性为 --。
body 部分是块语句 BlockStatement。
我们的目标是检查出遍历方向是否和终止条件的判断一致,也就是说当 update 为 ++ 时,test 应为为 <、<=;当 update 为 – 时,test 应为 >、>=。如果不一致就报错。
# 代码实现
首先,对 ForStatement 的 update 和 test 做检查,如果不一致就报错。
visitor: {
ForStatement(path, state) {
const testOperator = path.node.test.operator
const udpateOperator = path.node.update.operator;
let sholdUpdateOperator;
if (['<', '<='].includes(testOperator)) {
sholdUpdateOperator = '++';
} else if (['>', '>='].includes(testOperator)) {
sholdUpdateOperator = '--';
}
if (sholdUpdateOperator !== udpateOperator) {
// 报错:遍历方向错误
}
}