如何编写你的第一个ESLint插件(翻译)

翻译自 《How To Write Your First ESLint Plugin》
推荐理由:言简意骇,是我入门ESLint的启蒙文章👍

本文是ESLint插件(Plugins)的简单介绍指南,包括它们是如何工作的,如何配置、编写和如何使用一个插件的。

什么是ESLint插件

它是ESLint的一个外部拓展,强制执行一些规则(rules),不是写在ESLint核心(core)里的。举个例子,大家都比较熟悉的插件eslint-plugin-babel支持了ESLint核心中没有的实验性功能和linter(改进代码的工具)。🚩插件通常存储为单独的NPM模块,它导出rule对象,其中key是规则名称,value是另一个具有强制执行规则方法的对象:🚩

module.exports = {
    rules: {
        "rule-name": {
            create: function (context) {
                // rule implementation ...
            }
        }
    }
};

为什么你需要关心自己去写一个?

NPM已现存有非常多的插件,找到你需要的插件的概率会很高。但是在某些情况下,你可能需要针对你的代码库制定非常具体的规则。
最近,我们的开发团队决定强制执行关于异步函数的命名规范。这意味着,如果某个函数返回一个promise或有一个async声明前缀,那么这个函数命名必须有一个固定Async后缀:function someFunctionAsync()
让我们以此为例,编写一个可以警告函数命名错误的ESLint插件,

创建一个插件

在本教程中,我们将创建一个本地插件包并在简单的node应用中使用。项目结构如下所示:

plugin-tutorial 
│
└───my-eslint-rules
│   │   package.json
│   │   index.js
│   
└───node-app
    │   package.json
    │   index.js

首先创建主文件夹 mkdir plugin-tutorial && cd plugin-tutorial

配置插件包

每一个有效的插件都应该满足以下条件:

  • 单独的NPM包
  • 遵循eslint-plugin-<plugin-name>的命名格式
  • 导出rules对象
  1. 创建插件项目(plugin package): mkdir my-eslint-rules && cd my-eslint-rules && npm init --yes
  2. package.json中为其命名: { "name": "eslint-plugin-my-eslint-rules" }
  3. 创建index.js入口文件并导出自定义规则rules对象,暂命名为async-func-name
module.exports = {
  rules: {
    "async-func-name": {
      create: function (context) {
        return { /* ...rule methods */ }
      }
    }
  }
};

编写rule规则对象

为了构建和测试规则,我们将使用一个工具AST explorer
AST代表抽象语法树或者语法书,它是源代码的抽象语法结构的树状表现形式。 [注1]

将AST Explorer的解析器(parser)设置为eslint-babel和转换器(transformer)设置为ESLint v4

现在在资源管理器中可以看到四个窗口:

  • 左上角的窗口将用于编写源代码(source code)
  • 右上角的窗口是源代码的资源管理器。将鼠标悬停在表达式上时,你可以看到代码中突出显示的部分
  • 左下角就是我们要调试编辑的规则代码
  • 右下角是规则后的输出,与源代码同步更新运行
https://astexplorer.net/

规则函数会接受一个参数为context的对象,该对象包含了关于规则上下文相关的附加功能和信息。

主要方法是context.report()
你将使用的主要方法是 context.report(),它用来发布警告或错误(取决于你所使用的配置)。该方法只接收一个参数,是个对象,包含以下属性:message,node, loc, data, fix [注2]
最简单的示例是只使用 nodemessage

context.report({
    node: node,
    message: "Async function name must end in 'Async'"
});

该规则必须返回一个对象,其中包含ESLint再遍历源代码语法树时调用的visitor节点的方法。
在我们的示例中,有一个方法FunctionDeclaration,它接受一个node对象参数,该节点对象包含了函数信息,例如type(类型)、name(名称)、body(主体)、locations(每个值的位置)。

要检查函数名称是否具有Async后缀,我们需要访问名称,该名称位于FunctionDeclaration节点的id对象中:node.id.name

所以规则的主要逻辑应该是检查函数是否有async属性,如果不包含Async后缀,则调用context.report()方法。

应用规则后,AST explorer输出警告消息:

rule function

在资源管理器中编写规则并确保它捕获到正确的规则条件后,将逻辑代码复制到插件包的index.js中,即完成插件:

module.exports = {
  rules: {
    "async-func-name": {
      create: function (context) {
        return {
          FunctionDeclaration(node) {
            if (node.async && !/Async$/.test(node.id.name)) {
              context.report({
                node,
                message: "Async function name must end in 'Async'"
              });
            }
          }
        }
      }
    }
  }
};

将插件应用到项目中

首先,项目需要这样配置:

  • plugin-tutorial执行命令mkdir node-app && cd node-app && npm init --yes && touch index.js,并将AST explorer中的实例代码加入到index.js中:
async function myFunction() {
    return "";
}
  • 安装ESLint依赖npm i eslint --save-dev
  • 安装刚刚创建的插件:npm i ../my-eslint-rules --save-dev
  • 通过创建配置文件.eslintrc告诉应用程序需要使用到的ESLint规则与插件
{
  "parserOptions": {
    "ecmaVersion": 2018
  },
  "rules": {
    "my-eslint-rules/async-func-name": "warn"
  },
  "plugins": ["my-eslint-rules"]
}
  • 在项目应用程序文件夹中打开终端并运行ESLint命令:./node_modules/.bin/eslint index.js

差不多就是这样。如何您为异步函数设置了错误的名称,您应该在终端中运行它后看到ESLint警告。

在项目中使用插件的重要部分是.eslintrc配置文件。插件的命名规则应该遵循"<plugin-name>/<rule-name>": [warn/error]。插件名称应添加到数组plugins字段中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容