在 JavaScript AST(抽象语法树)中,不同的解析器(如 espree 和 babel-parser)可能会使用不同的节点类型和属性表示相同的语法结构。以下是解释为什么在不同的地方使用了不同的大小写表示 import 语句的原因:
-
CallExpression[callee.name="import"]:- 这个语法适用于
espree(ESLint 的默认解析器)和某些其他解析器,表示动态导入语句import()。 - 在这种情况下,
import被解析为一个CallExpression,其callee是一个Identifier,名字是import。
- 这个语法适用于
-
node.callee.type === 'Import':- 这个语法适用于
babel-parser,表示动态导入语句import()。 - 在这种情况下,
import被解析为一个特殊的Import节点类型,而不是一个Identifier。
- 这个语法适用于
为了编写兼容多个解析器的 ESLint 规则,我们需要考虑这两种情况:
- 使用
espree时,动态导入语句的callee是Identifier类型,名字是import。 - 使用
babel-parser时,动态导入语句的callee是Import类型。
兼容多个解析器的 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);
}
},
};
},
};
解释
- ImportDeclaration:处理静态导入语句
import ... from ...。 - CallExpression:
- 处理
require("@/components/BaseIcon"),其中callee.name是require,参数类型是Literal或StringLiteral。 - 处理动态导入语句
import("@/components/BaseIcon"),其中callee.type是Import(适用于babel-parser),或callee.type是Identifier且callee.name是import(适用于espree),参数类型是Literal或StringLiteral。
- 处理
通过这种方式,你可以编写兼容多个解析器的 ESLint 规则,确保能够正确识别和处理不同解析器生成的 AST 节点。
浙公网安备 33010602011771号