eslint规则,兼容espree和babel-eslint的写法

Posted on 2024-05-17 09:44  生之不止,思之不息  阅读(55)  评论(0)    收藏  举报

在 JavaScript AST(抽象语法树)中,不同的解析器(如 espreebabel-parser)可能会使用不同的节点类型和属性表示相同的语法结构。以下是解释为什么在不同的地方使用了不同的大小写表示 import 语句的原因:

  1. CallExpression[callee.name="import"]:

    • 这个语法适用于 espree(ESLint 的默认解析器)和某些其他解析器,表示动态导入语句 import()
    • 在这种情况下,import 被解析为一个 CallExpression,其 callee 是一个 Identifier,名字是 import
  2. node.callee.type === 'Import':

    • 这个语法适用于 babel-parser,表示动态导入语句 import()
    • 在这种情况下,import 被解析为一个特殊的 Import 节点类型,而不是一个 Identifier

为了编写兼容多个解析器的 ESLint 规则,我们需要考虑这两种情况:

  • 使用 espree 时,动态导入语句的 calleeIdentifier 类型,名字是 import
  • 使用 babel-parser 时,动态导入语句的 calleeImport 类型。

兼容多个解析器的 ESLint 规则

以下是一个示例代码,展示了如何编写兼容多个解析器的 ESLint 规则,识别 import("@/components/BaseIcon")require("@/components/BaseIcon") 语句,并提取其中的路径:

module.exports = {
  meta: {
    type: "suggestion",
    docs: {
      description: "Extract import and require paths",
      category: "Best Practices",
      recommended: false,
    },
    schema: [], // no options
  },
  create(context) {
    function reportPath(node, importPath) {
      if (importPath.startsWith('@/')) {
        context.report({
          node,
          message: `Path detected: ${importPath}`,
        });
      }
    }

    return {
      ImportDeclaration(node) {
        const importPath = node.source.value;
        reportPath(node, importPath);
      },
      CallExpression(node) {
        // For `require("@/components/BaseIcon")`
        if (node.callee.name === 'require' && node.arguments[0] && (node.arguments[0].type === 'Literal' || node.arguments[0].type === 'StringLiteral')) {
          const importPath = node.arguments[0].value;
          reportPath(node, importPath);
        }
        // For dynamic `import("@/components/BaseIcon")` with different parsers
        if ((node.callee.type === 'Import' || (node.callee.type === 'Identifier' && node.callee.name === 'import')) && node.arguments[0] && (node.arguments[0].type === 'Literal' || node.arguments[0].type === 'StringLiteral')) {
          const importPath = node.arguments[0].value;
          reportPath(node, importPath);
        }
      },
    };
  },
};

解释

  1. ImportDeclaration:处理静态导入语句 import ... from ...
  2. CallExpression
    • 处理 require("@/components/BaseIcon"),其中 callee.namerequire,参数类型是 LiteralStringLiteral
    • 处理动态导入语句 import("@/components/BaseIcon"),其中 callee.typeImport(适用于 babel-parser),或 callee.typeIdentifiercallee.nameimport(适用于 espree),参数类型是 LiteralStringLiteral

通过这种方式,你可以编写兼容多个解析器的 ESLint 规则,确保能够正确识别和处理不同解析器生成的 AST 节点。

博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3