Eslint 插件

235 阅读5分钟

- 插件的意义

  • eslint 定义规则:插件允许你自定义规则,通过插件加入到 eslint ,确保团队成员遵守统一的代码约定,提高代码质量和可维护性
  • 支持特定技术栈:插件可以提供针对特定技术栈的规则和配置选项。eslint-plugin-vue 提供了用于 Vue.js 开发的规则
  • 处理特定语言特性:插件可以添加针对特定语言特性的检查规则。slint-plugin-import 可以处理模块导入/导出相关的问题
  • 提供辅助功能:插件可以为规则提供辅助功能,例如自动修复或给出更详细的错误消息。
  • eslint插件中文文档 eslint.nodejs.cn/docs/latest…

- 举例

  • 实现一个给每一个函数添加注释(注释模版 === 开发者名称,开发时间,函数描述)
// 使用eslint 规则修复和添加这个注释
/**
* 
* @constructor
* @param {string} title - 名称
* @param {string} author - 作者
*
*/
function name(params) {
  console.log(111)
}

- 初始化插件的开发环境

pnpm i -g yo
pnpm i -g generator-eslint

// 生成项目框架
yo eslint:plugin
  • 填写一些基本信息,如下
yo eslint:rule
What is your name? 随便写个你的名字
What is the plugin ID? 你的插件的id,推荐(eslint-plugin-xxx)的命名方式
Type a short description of this plugin: 描述你的插件是干啥的
Does this plugin contain custom ESLint rules? Yes
Does this plugin contain one or more processors? No (这里我们用不到处理器,就直接选No)
  • 创建一条规则
npx yo eslint:rule

image.png

├── README.md 这是你的插件的描述文档,包括如何安装使用等
├── docs
│   └── rules 这是你的自定义规则的描述文档
│       └── my-custom-rules1.md
├── lib 源码目录
│   ├── index.js 插件的入口
│   └── rules 这里放你的每一条自定义规则
│       └── my-custom-rules1.js
├── package.json
├── pnpm-lock.yaml
└── tests 测试目录
    └── lib
        └── rules
            └── my-custom-rules1.js

- rule的格式

module.exports = {
    // meta里面的元数据,对于我们自定义规则,其实只关心schema就行了
    meta: {
        // 规则的类型problem|suggestion|layout
        // problem: 这条规则识别的代码可能会导致错误或让人迷惑。应该优先解决这个问题
        // suggestion: 这条规则识别的代码不会导致错误,但是建议用更好的方式
        // layout: 表示这条规则主要关心像空格、分号等这种问题
        type: "suggestion",
        // 对于自定义规则,docs字段是非必须的
        docs: {
            description: "描述你的规则是干啥的",
            // 规则的分类,假如你把这条规则提交到eslint核心规则里,那eslint官网规则的首页会按照这个字段进行分类展示
            category: "Possible Errors",
            // 假如你把规则提交到eslint核心规则里
            // 且像这样extends: ['eslint:recommended']继承规则的时候,这个属性是true,就会启用这条规则
            recommended: true,
            // 你的规则使用文档的url
            url: "https://eslint.org/docs/rules/no-extra-semi"
        },
        // 标识这条规则是否可以修复,假如没有这属性,即使你在下面那个create方法里实现了fix功能,eslint也不会帮你修复
        fixable: "code",
        // 这里定义了这条规则需要的参数
        // 比如我们是这样使用带参数的rule的时候,rules: { myRule: ['error', param1, param2....]}
        // error后面的就是参数,而参数就是在这里定义的
        schema: [],
        // 信息模版
        messages: {
      noDescMessage: '请添加注释解析 方法名称为 {{ type }}',
    }
    },
    create: function(context) {
        // 这是最重要的方法,我们对代码的校验就是在这里做的
        return {
            // callback functions
        };
    }
};

- create

  1. create 方法接受一个 context 参数,用于提供规则执行所需的上下文信息。通过 context 对象,你可以访问到当前解析的代码的 AST(抽象语法树)、配置选项等。
  2. 说下eslint 校验文件的流程 image.png
  3. 具体如何解析ast 语法书请看 astexplorer.net/
  4. create方法的入参context
  • parserOptions-编译器选项,就是我们.eslintrc.js里的那个
  • id-规则id
  • options-通过这个可以拿到规则传进来的参数
  • getFilename()-返回源文件文件名
  • getScope()- 返回当前遍历节点的作用域
  • getSourceCode()- 返回SourceCode对象,就是源码对象,很有用
  • report()- 当校验不通过的时候,通过这个方法输出错误信息

- 注意这里你们可以自己在 vscode 上自己用 JavaScript Debug Terminal 调试代码

image.png

- 开始写我们上面eslint 插件

  • 我写的这个插件是给每一个函数都想有一个注释解析,方便减轻后期维护人员的维护成本
  1. 判断每一个函数是不是都有注释
  2. 没有注释给一个提示 每一个函数都应该有自己的注释解析
  3. 可以提示修复(加上注释 功能描述作者参数名称返回值说明)如下所示
/**
 * 函数功能描述
 * @desc { title } 作者
 * @param {type} 参数名 参数说明
 * @return {type} 返回值说明
 */
function name(params) {
}

- 具体插件实现

/**
 * @fileoverview 添加注释
 * @author eslint-plugin-desc
 */
"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
  meta: {
    type: 'suggestion', // `problem`, `suggestion`, or `layout`
    docs: {
      description: "添加注释",
      recommended: false,
      url: null, // URL to the documentation page for this rule
    },
    fixable: 'code', // Or `code` or `whitespace`
    schema: [], // Add a schema if the rule has options
    messages: {
      noDescMessage: '请添加注释解析 方法名称为 {{ type }}',
    }
  },

  // eslint-disable-next-line no-unused-vars
  /**
   * 第一步获取 当前代码的前一步代码
   * 第二部判断 代码有没有注释 没有注释加入注释 有注释判断下符合格式不
   *
   * @param {*} context
   * @return {*} 
   */
  create(context) {
    const sourceCode = context.getSourceCode();
    function getFunctionParamsLoc(node) {
      return {
        start: node.loc.start,
      };
    }
    return {
      /**
       *判断当前节点有没有 有 就进一步判断当前节点是不是type:Block
       *
       * @param {*} node
       * @return {*} 
       */
      FunctionDeclaration(node) {
        let FunctionDeclarationDesc = []
        FunctionDeclarationDesc = sourceCode.getCommentsBefore(node)
        if (!FunctionDeclarationDesc[0]) {
          context.report({
            node,
            loc: getFunctionParamsLoc(node),
            data: {
              type: node.id.name
            },
            messageId: 'noDescMessage',
            fix(fixer) {
              return fixer.insertTextBefore(node, `/**
 * 函数功能描述
 * @desc { title } 作者
 * @param {type} 参数名 参数说明
 * @return {type} 返回值说明
 */
`)
            }
          })
        }
      },
    };
  },
};

image.png

- pnpm 构建本地测试环境

  1. 在刚写好的eslint插件同级目录下新建一个文件 eslint_test
  2. 安装eslint
pnpm init
pnpm i eslint -D // 安装eslint
pnpm create @eslint/config //初始化eslint配置文件

pnpm i eslint-plugin-desc@workspace -W // 这里可以回报错 说没有什么根文件
  1. 新建 pnpm-workspace.yaml 建好过后运行 在 eslint_test 文件下安装pnpm i eslint-plugin-desc@workspace -W

image.png

image.png 4. 在eslint_test文件下的 .eslintrc.js 引入刚才写好的规则

module.exports = {
  "env": {
    "browser": true,
    "es2021": true
  },
  // "extends": "eslint:recommended",
  "overrides": [
    {
      "env": {
        "node": true
      },
      "files": [
        ".eslintrc.{js,cjs}"
      ],
      "parserOptions": {
        "sourceType": module
      }
    }
  ],
  "parserOptions": {
    "ecmaVersion": "latest"
  },
  // 用到的规则
  "rules": {
    'desc/eslint-plugin-desc': ['error']
  },
  // 插件名称
  plugins: ['desc'],
}
  1. 新建index.js测试文件 image.png image.png

注意如果引入不生效就把vscode 退了重新进入就可以看下提示了

- 代码地址 需要自取gitee.com/little1/esl…