javascript - 通过 jscodeshift 替换特定导入的所有实例

标签 javascript jscodeshift codemod

好的,我的代码如下所示:

import { wait } from "@testing-library/react";

describe("MyTest", () => {
  it("should wait", async () => {
    await wait(() => {
      console.log("Done");
    });
  });
});

我想将导入成员 wait 更改为 waitFor。我可以像这样在 AST 中更改它:

    source
      .find(j.ImportDeclaration)
      .filter((path) => path.node.source.value === "@testing-library/react")
      .find(j.ImportSpecifier)
      .filter((path) => path.node.imported.name === "wait")
      .replaceWith(j.importSpecifier(j.identifier("waitFor")))
      .toSource()

但是,输出的代码将如下所示:

import { waitFor } from "@testing-library/react";

describe("MyTest", () => {
  it("should wait", async () => {
    await wait(() => {
      console.log("Done");
    });
  });
});

我正在寻找一种方法来更改该导入的所有后续用法以匹配新名称

这可以用 jscodeshift 实现吗?

最佳答案

您可以通过访问所有 CallExpression 节点、过滤具有您所定位的名称(“wait”)的节点并将它们替换为新节点来完成此操作。

要查找相关节点,您可以循环遍历 jscodeshift 的 find() 方法返回的集合并在其中添加逻辑,或者您可以给 find()第二个论点。这应该是用于过滤的谓词:

const isWaitExpression = (node) =>
    node.callee && node.callee.name === "wait";

// I've used "root" where you used "source"
root
    .find(j.CallExpression, isWaitExpression)

然后您可以使用 replaceWith() 替换这些节点:

const replaceExpression = (path, j) =>
    j.callExpression(j.identifier("waitFor"), path.node.arguments);

root
   .find(j.CallExpression, isWaitExpression)
   .replaceWith((path) => replaceExpression(path, j));

它可能看起来有点令人困惑,但要创建 CallExpression 节点,您可以从 api 调用 callExpression() 方法。注意那里的驼色外壳。

总而言之,将“wait”从 RTL 重命名为“waitFor”的转换器(命名的导入声明和文件中调用它的每个实例)可以像这样完成:

const isWaitExpression = (node) => node.callee && node.callee.name === "wait";

const replaceExpression = (path, j) =>
  j.callExpression(j.identifier("waitFor"), path.node.arguments);

export default function transformer(file, api) {
  const j = api.jscodeshift;
  const root = j(file.source);

  root
    .find(j.ImportDeclaration)
    .filter((path) => path.node.source.value === "@testing-library/react")
    .find(j.ImportSpecifier)
    .filter((path) => path.node.imported.name === "wait")
    .replaceWith(j.importSpecifier(j.identifier("waitFor")));

  root
    .find(j.CallExpression, isWaitExpression)
    .replaceWith((path) => replaceExpression(path, j));

  return root.toSource();
}

这是一个 link to it on AST explorer

关于javascript - 通过 jscodeshift 替换特定导入的所有实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72280795/

相关文章:

jscodeshift - 如何在检查模式下启动 jscodeshift?

javascript - 在 AngularJS 中使用单例模式是一种不好的做法吗?

属性和方法具有相同名称的 JavaScript 类

javascript - npm:从 src 文件夹外部导入

javascript - 扩展javascript函数继承数组

javascript - 创建一个 codemod 以将新元素添加到数组

javascript - jscodeshift 更改对象文字值