javascript 自定义ESLint规则修复程序:如果辅助函数尚未导入,则添加导入声明

nue99wik  于 2023-05-12  发布在  Java
关注(0)|答案(2)|浏览(130)

我有一个用例,我想替换一个变量函数调用,特别是像foo.value.toString()这样的函数,使用一个助手函数getStringValue(foo)。如果我找到了CallExpression节点上的文本,我可以使用fixer替换它,所以我的规则fixer当前看起来像这样:

fixer => fixer.replaceText(node, `getStringValue(${identifierNode.getText()})`);

以这种方式自动修复此错误的问题是,getStringValue可能已经导入到文件中,也可能尚未导入到文件中。我希望此修复程序具有以下行为:
1.如果函数已经导入到文件中,则不执行其他操作。
1.如果函数未被导入,但其包含的文件模块被导入,则将此函数添加到该模块的导入中。
1.如果函数及其包含的文件模块均未导入,则将模块与此函数沿着导入。
据我从文档中所知,没有简单的方法可以使用fixercontext对象访问根ESTree节点。最接近的是SourceCode.getText(),这意味着我必须解析源文本才能解析导入--我更愿意直接与整个AST交互。执行此自动导入过程的最佳方法是什么?

c9qzyr3d

c9qzyr3d1#

如果你想在这里稍微不安全,你可以假设用户没有在他们的文件中本地重新定义getStringValue函数(如果你拥有这个规则所针对的代码库,通常是一个安全的假设)。
在这种情况下,最好的方法是使用选择器来检查导入,例如:

module.exports = {
  create(context) {
    let hasImport = false;
    let lastImport = null;
    return {
      ImportDeclaration(node) {
        lastImport = node;
        if (isImportICareAbout(node)) {
          hasImport = true;
        }
      },
      "My Selector For Other Linting Logic"(node) {
        // ...
        context.report({
          messageId: "myReport",
          fix(fixer) {
            const fixes = [
              fixer.replaceText(node, `getStringValue(${identifierNode.name})`),
            ];
            if (!hasImport) {
              const newImport = 'import { getStringValue } from "module";';
              if (lastImport) {
                // insert after the last import decl
                fixes.push(fixer.insertTextBefore(lastImport, newImport));
              } else {
                // insert at the start of the file
                fixes.push(fixer.insertTextAfterRange([0, 0], newImport));
              }
            }
            return fixes;
          },
        });
      },
    };
  },
};
o2g1uqev

o2g1uqev2#

原来有一种简单的方法可以从context对象中提取AST根节点。它位于context.getSourceCode().ast。我用下面的逻辑重写了我的fixer:

fixer => {
  fixer.replaceText(node, `getStringValue(${identifierNode.getText()})`);
  const body = context.getSourceCode().ast;
  const importDeclarations = body.filter(statement => statement.type === AST_NODE_TYPES.ImportDeclaration);
  ... // Check if the declaration has the import and add the appropriate imports if necessary
}

相关问题