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

cor*_*vid 2 javascript jscodeshift codemod

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

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

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

我想将那个导入成员更改waitwaitFor. 我可以在 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()
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

这可以用 jscodeshift 实现吗?

小智 6

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

\n

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

\n
const isWaitExpression = (node) =>\n    node.callee && node.callee.name === "wait";\n\n// I\'ve used "root" where you used "source"\nroot\n    .find(j.CallExpression, isWaitExpression)\n
Run Code Online (Sandbox Code Playgroud)\n

然后您可以将这些节点替换为replaceWith()

\n
const replaceExpression = (path, j) =>\n    j.callExpression(j.identifier("waitFor"), path.node.arguments);\n\nroot\n   .find(j.CallExpression, isWaitExpression)\n   .replaceWith((path) => replaceExpression(path, j));\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

总之,将“wait”从 RTL 重命名为“waitFor”\xe2\x80\x94 的变压器,命名的导入声明和文件 \xe2\x80\x94 中调用它的每个实例都可以像这样完成:

\n
const isWaitExpression = (node) => node.callee && node.callee.name === "wait";\n\nconst replaceExpression = (path, j) =>\n  j.callExpression(j.identifier("waitFor"), path.node.arguments);\n\nexport default function transformer(file, api) {\n  const j = api.jscodeshift;\n  const root = j(file.source);\n\n  root\n    .find(j.ImportDeclaration)\n    .filter((path) => path.node.source.value === "@testing-library/react")\n    .find(j.ImportSpecifier)\n    .filter((path) => path.node.imported.name === "wait")\n    .replaceWith(j.importSpecifier(j.identifier("waitFor")));\n\n  root\n    .find(j.CallExpression, isWaitExpression)\n    .replaceWith((path) => replaceExpression(path, j));\n\n  return root.toSource();\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这是AST 浏览器上的链接

\n