自定义 Eslint 规则
如何定制化一个 Eslint,下面我将自定义一个检查 console.log()里面值是否为 99。
创建 EslintDemo 插件文件夹
文件夹来存放我们的规则
新建终端 输入 npm i 初始化项目
Eslint 官方提供了脚手架来简化新规则的开发。
/* 全局安装两个依赖包 */
npm i -g yo
npm i -g generator-eslint
再执行下面命令生成 Eslint 插件。
yo eslint:plugin
输入命令后会弹出交互式命令
? What is your name? // 插件名字
? What is the plugin ID? // 插件名 (eslint-plugin-xxx)
? Type a short description of this plugin: // 描述你的插件是什么的
? Does this plugin contain custom ESLint rules? Yes // 是否为自定义Eslint 校验规则
? Does this plugin contain one or more processors? No // 是否需要处理器
我是这样填的
这样我们就生成了插件目录结构
项目的 package.json 如下
{
"name": "eslint-plugin-con99",
"version": "0.0.0",
"description": "console.log value is 99",
"keywords": [
"eslint",
"eslintplugin",
"eslint-plugin"
],
"author": "eslint Demo",
"main": "./lib/index.js",
"exports": "./lib/index.js",
"scripts": {
"lint": "npm-run-all \"lint:*\"",
"lint:eslint-docs": "npm-run-all \"update:eslint-docs -- --check\"",
"lint:js": "eslint .",
"test": "mocha tests --recursive",
"update:eslint-docs": "eslint-doc-generator"
},
"dependencies": {
"requireindex": "^1.2.0"
},
"devDependencies": {
"eslint": "^8.19.0",
"eslint-doc-generator": "^1.0.0",
"eslint-plugin-eslint-plugin": "^5.0.0",
"eslint-plugin-node": "^11.1.0",
"mocha": "^10.0.0",
"npm-run-all": "^4.1.5"
},
"engines": {
"node": "^14.17.0 || ^16.0.0 || >= 18.0.0"
},
"peerDependencies": {
"eslint": ">=7"
},
"license": "ISC"
}
文件夹作用
创建规则文件
在创建规则文件前,我们先去官网看看示例
module.exports = {
meta: {
type: "problem",
// 这个type是规则的类型 据我了解有三种状态,problem就必须更改,suggestion是建议改
// 分别为problem,suggestion,layout
// problem: 这条规则识别的代码可能会导致错误或让人迷惑。应该优先解决这个问题
// suggestion: 这条规则识别的代码不会导致错误,但是建议用更好的方式
// layout: 表示这条规则主要关心像空格、分号等这种问题
// 对于自定义规则,docs字段是非必须的
docs: {
/* description描述你的规则 */
description: "Enforce that a variable named `foo` can only be assigned a value of 'bar'.",
},
/* fixable标识这条规则是否可以修复,假如没有这属性,即使你在下面那个create方法里实现了fix功能,eslint也不会帮你修复 */
fixable: "code",
// schema这里定义了这条规则需要的参数
schema: []
},
create(context) {
return {
// 这里就写规则判断的逻辑
};
}
};
有了前面铺垫我们在 lib 文件夹下 rules 里面创建 eslint-plugins-rule.js 文件
module.exports = {
meta: {
type: "problem",
docs: {
/* 描述 console.log的值不能是99*/
description: "error console.log have 99",
},
fixable: "code",
schema: [],
},
create: function (context) {
return {
/* 逻辑规则判断 */
ExpressionStatement: function (node) {
/* 存在相等则报错 */
if (node.expression.arguments[0].value === "99") {
context.report({
node: node,
message: "error console.log have 99",
});
}
},
};
},
};
编写逻辑规则判断
由于 ESlint 会通过 Estree 将代码解析一棵抽象语法树(AST),将不同类型的代码语句分成不同类型的节点,一份代码文件便形成了一个树状的结构,之后 ESlint 会依次遍历语法树上的节点。
我觉得应该是 Eslint 在检查代码时候会将代码转换为一颗树,通过变量这颗树节点来找出与规则不符合的节点,将代码转化为树要用到下面的工具。
astexplorer 工具
这里我用到了 astexplorer 工具将代码转化为树 ,点击跳转到工具
输入不合法代码 console.log(“99”),得到树结构
输入合法代码 console.log(“666”),得到树结构
这里我们看到了当这个 value 值不为 99,我们就可以将他视为不合法代码
//ExpressionStatement为树中的body的对象,这里要和代码对应,通过获取值来判断即可完成下面逻辑
ExpressionStatement: function (node) {
/* 存在相等则报错 */
if (node.expression.arguments[0].value === "99") {
context.report({
node: node,
message: "error console.log have 99",
});
}
},
到这里我们就完成了规则文件的代码编写
创建测试文件
在创建测试文件前,我们先去官网看看示例
// enforce-foo-bar.test.js
const {RuleTester} = require("eslint");
const fooBarRule = require("./enforce-foo-bar");/* 引入制定的规则 */
const ruleTester = new RuleTester({
parserOptions: { ecmaVersion: 2015 }/* emcaVersion用来指定你想要使用的 ECMAScript 版本 */
});
ruleTester.run(
"enforce-foo-bar", /* 规则名字 */
fooBarRule,
{
/*合法例子 */
valid: [{
code: "const foo = 'bar';",
}],
/* 非法例子 */
invalid: [{
code: "const foo = 'baz';",
output: 'const foo = "bar";',
errors: 1,
}],
}
);
console.log("All tests passed!");
接下来在 lib 文件夹下 rules 里面创建 eslint-plugins-test.js 文件
const rule = require("../../../lib/rules/eslint-plugins-rule");
const RuleTester = require("eslint").RuleTester;
const ruleTester = new RuleTester();
ruleTester.run("eslint-plugins-rule", rule, {
/* 有效场景 */
/* 当value值不为99就可以通过 */
valid: ['console.log("66");'],
/* 无效场景 */
/* 当value值等于99就会提示非法 */
invalid: [
{
code: "console.log('99');",
errors: [
{
message: "error console.log have 99",
type: "ExpressionStatement",
},
],
},
],
});
console.log("All tests passed!");
测试运行
/* 控制台输入 */
npm run test
测试结果
显示这样就完成了测试文件的编写
出错场景
在有效场景中将 code: "console.log(‘66’);"改为 code: "console.log(‘99’);"就相当于检查出来错误
到此我们完成完成了 Eslint 规则编写