如何编写你的第一个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-的命名格式
  • 导出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配置文件。插件的命名规则应该遵循"/": [warn/error]。插件名称应添加到数组plugins字段中。

你可能感兴趣的:(如何编写你的第一个ESLint插件(翻译))