我们一起Eslint 探索之 Plugin

开发 前端
在schema中定义的,主要用于传入的,例如上面的例子,要想指定某些字段在注释中禁用,这些自定义禁用的字段需要传入到context中。

关于Eslint-plugin的研究,今天主要谈两点:

实现一个简单的plugin插件。

eslint如何处理plugin插件。

接着上一篇《Eslint源码探索》,今天探索一下plugin。今天是研究课。

实现一个简单的plugin插件

关于Plugin官方文档说的比较详细,但是内容太多,这里罗列了几条关键的步骤:

  • 生成plugin模版
  • 生成rule规则
  • rule规则对象配置属性说明
  • 单元测试

这里以生成一个单行注释不允许出现的字段为例。展开对plugin的探索。

官方提供了模版生成的工具Yeoman。这里一样:

// 下载
pnpm install -g yo generator-eslint

// 生产模版
yo eslint:plugin

// 生成rule
yo eslint:rule

模版的结构也比较简单,提供了三个功能,这三个功能都可以通过yo eslint:rule自动生成。

  • docs文档说明。每一个rule都有各自的md。
  • lib核心库,包含每一个rule。
  • tests测试用例。每一个rule都是单独的用例。

依赖第三方包如下:eslint相关和测试相关的。

requireindex这个包,会把lib下的所有rules打包成一个对象。比较实用,以后在其他项目中也会用到。

// requireIndex 把多文件包装成对象
const requireIndex = require("requireindex");
module.exports.rules = requireIndex(__dirname + "/rules");

// 打印一下,包装的rules
{
// ...
'notes-keys': {
meta: {
type: 'suggestion',
docs: [Object],
fixable: 'code',
schema: [Array]
},
create: [Function: create]
}
}

mocha主要用于测试。

接下来进入rules,了解一下rules详细的配置:

在meta中,type较为关键,表示此规则的必要性:

  • problem,表示此代码会导致错误和异常行为,是优先要处理的。
  • suggestion,表示此代码只是建议,可以有更好的方式来完成。
  • layout,表示代码的美观性,比如空格、逗号、封号等。
  meta: {
type: 'suggestion', // `problem`, `suggestion`, or `layout`
docs: {
description: "校验注释中是否包含指定关键词",
category: "Stylistic Issues", // 规则分类
recommended: true, // 配置文件中的 "extends":"eslint:recommended"属性是否启用该规则,当创建的规则push到eslint核心规则才生效
url: null, // URL to the documentation page for this rule
},
fixable: 'code', // Or `code` or `whitespace`
// 如fixable主要用于fix功能,如果不设置fixable,eslint将默认此规则不可修复
schema: [
{
"keyWords": {
"type": "array",
"items": {
"type": "string"
}
}
}
], // Add a schema if the rule has options
},

fixable主要用于修复规则,在eslint-plugin包中此处为必填,官方推荐此处必须配置。与之相对应的在create中context.report中fix函数相对应,修复函数的回调。

在schema中定义的字段,主要用于传入的配置,例如上面的例子,要想指定某些字段在注释中禁用,这些自定义禁用的字段需要传入到context中。此处用于限定传入字段的属性。当我使用此rule的时候,可以这样处理:

rules: {
// foo表示在注释中禁用的字段
"foo/notes-keys": [2, { keyWords: ['foo'] }]
}

create返回一个对象,包含eslint在遍历语法树时,用来访问节点的方法。这些访问节点的方法很多。这也是生成插件比较难的地方,因为走到这里你需要了解AST的节点类型相关的知识。

上图是针对AST节点类型的一些简单的总结,在eslint源码中定义的访问NodeType的如下图。除了源码中定义的,还有第三方定义,比如在react中就有JSXAttribute和JSXElement等自定义AST节点。

这里先把create的代码放在这里,图中的Program就是AST节点访问的方法。

接下来,开始讲讲context,context顾名思义,在这里几乎是无所不能的,它主要能帮我们做的事情,有以下几点:

  • 获取配置中的信息,如settings、parser相关的属性。
  • 获取遍历节点的数组,比如声明的变量、参数的变量、函数的变量、说明符的变量等。
  • 获取与源文件关联的文件名。
  • 获取源码。
  • 获取作用域中所有的变量和引用。
  • 报告有问题的代码。

create中的逻辑比较简单,获取到单行注释,然后判断是否有配置中的字段,如果有就report。此插件已发布到npm上,供大家学习参考。在npm上直接搜eslint-plugin-foo,只有一个rule。也可点击文章底部原文链接查看github上源码。

使用也简单,

// .eslintrc.js
plugins: ['foo'],
rules: {
"foo/notes-keys": [2, { keyWords: ['foo'] }]
}

在发布之前,我们还得写一下单元测试,这个也简单,eslint提供了RuleTester方法,我们只需写几个简单的实例就行。

const rule = require("../../../lib/rules/notes-keys"),
RuleTester = require("eslint").RuleTester;

const ruleTester = new RuleTester();
const errMsg = (msg) => `注释中含有不被允许的字符${msg}`;
ruleTester.run("notes-keys", rule, {
valid: ['// sssss', '// attr'], //生效的, 失效的

invalid: [
{
code: `// xxx:测试内容`,
errors: [{ message: errMsg('xxx') }],
options: [{ // 通过options 配置自定义参数
keyWords: ['xxx']
}],
// 添加fix修复必须添加output,output输出的内容要和rule中fix返回的结果一致
output: `// :测试内容`,
},
{
code: `// str11: const s='测试内容'`,
errors: [{ message: errMsg('str') }],
options: [{ // 通过options 配置自定义参数
keyWords: ['str']
}],
// 添加fix修复必须添加output,output输出的内容要和rule中fix返回的结果一致
output: `// 11: const s='测试内容'`,
}
],
});

运行一下

eslint如何加载plugin插件

关于plugin的处理没在eslint库里,而是引用了另一个库@eslint/eslintrc中,这里需要注意一点node在v14版本之后就支持了ES模块的书写,简而言之,我们可以在node文件中使用import/export。然后通过命令行执行node命令即可。

接着上一篇,我们聊到关于plugin、extends和parser的处理在ConfigArrayFactory中。

这里的探索过程也简单,下载@eslint/eslintrc的源码,npm install就绪之后,我们创建一个demo.js的文件。顺便下载我们发布的插件eslint-plugin-foo,在配置文件中加入。

demo中的代码如下,我们固定一个path来让它向下流转,通过node命令执行,方便我们查看它执行的步骤。

plugin的大致加载流程,和在源码中的位置,如下:

在loadInDirectory中,我们可查看当前的配置文件对象,也就是我们配置foo的地方。这个时候,还没有加载plugin。

在_loadPlugin中,能获取到foo配置的数据。

最后在configArray中收集生效的规则。

最后在demo.js中打印config。已经把foo插件变成一个对象,把rule也放在了rules中。

关于plugin的了解,先到这里。


责任编辑:武晓燕 来源: 惊天码盗
相关推荐

2024-06-07 14:54:55

2021-05-18 14:02:01

前端PDF中文

2023-11-03 12:54:00

KAFKA探索中间件

2021-08-27 07:06:10

IOJava抽象

2022-01-17 06:59:40

Grep指令linux

2021-12-29 08:27:05

ByteBuffer磁盘服务器

2024-02-20 21:34:16

循环GolangGo

2021-07-28 07:53:20

Github ActiDotnet 应用

2022-03-08 17:52:58

TCP格式IP

2022-03-31 18:59:43

数据库InnoDBMySQL

2021-08-27 07:06:09

DubboDocker技术

2022-10-18 07:33:57

Maven构建工具

2023-08-04 08:20:56

DockerfileDocker工具

2023-09-10 21:42:31

2021-01-12 05:08:49

DHCP协议模型

2023-08-10 08:28:46

网络编程通信

2022-05-24 08:21:16

数据安全API

2023-06-30 08:18:51

敏捷开发模式

2021-11-29 07:24:08

ACID事务大数据

2024-07-29 08:24:43

点赞
收藏

51CTO技术栈公众号