1

我正在尝试编写一个小的 codemod 来重构一些代码。考虑一下我有这样的事情:

import { mod1, mod2, mod3 } from 'package1'
import localMod from 'package2'

我想将其更改为:

import { mod1, mod3 } from 'package1'
import * as mod2 from 'new-package'
import localMod from 'package2'

作为第一步,我试图mod2从我成功完成的第一行导入中删除,但我无法删除mod1.

到目前为止,我的代码片段如下所示:

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

  const reactApolloImports = root
    .find(j.ImportDeclaration)
    .filter(nodepath => nodepath.value.source.value === "package1")
    .find(j.Identifier)
    .forEach(nodepath => {
      if (nodepath.name === "imported" && nodepath.node.name === "mod2") {
        j(nodepath).remove();
      }
    });

  return root.toSource();
};

请帮忙。

4

2 回答 2

4

而不是搜索和删除j.Identifierinside ,而是通过表达式j.ImportDeclaration找到它们的父节点。j.ImportSpecifier如果你删除这些,你应该没问题。

如果您将import { mod1, mod2, mod3 } from 'package1'语句粘贴到AST Explorer中,则更容易理解。

在此处输入图像描述

代码:

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

  const reactApolloImports = root
    .find(j.ImportDeclaration)
    .filter(impDecNodePath => impDecNodePath.value.source.value === "package1")
    .forEach(impDecNodePathFiltered => {
      j(impDecNodePathFiltered)
        // find ImportSpecifier here instead of Identifier
        .find(j.ImportSpecifier)
        .forEach(impSpecNodePath => {
          if (impSpecNodePath.node.imported.name === "mod2") {
            j(impSpecNodePath).remove();
          }
        });
    });

  return root.toSource();
};

改变的输出:

import { mod1, mod3 } from 'package1';
import localMod from 'package2'

希望能帮助到你。

于 2019-09-03T10:27:40.540 回答
0

您可以为此目的使用putout代码转换器,它使事情变得更容易:

这是您需要的插件,它是Replacer

export const replace = () => ({
    'import {parse, compare, transform} from "putout"': `{
        import {parse, transform} from 'putout';
        import compare from '@putout/compare';
    }`,
}),

我们还将使用插件@putout/plugin-remove-nested-blocks来删除额外的块:

const replaceImports = {
    report: () => '',
    replace: () => ({
        'import {parse, compare, transform} from "putout"': `{
            import {parse, transform} from 'putout';
            import compare from '@putout/compare';
        }`,
    }),
};

const source = `
    import {parse, compare, transform} from 'putout';
`;

const {code} = putout(source, {
    plugins: [
        ['replaceImports', replaceImports],
        'remove-nested-blocks',
    ],
});

结果将是:

import {parse, transform} from 'putout';
import compare from '@putout/compare';

这是您的示例的外观(未remove-nested-blocks应用):

在此处输入图像描述

主要好处是封装工作,AST因此您可以更快、更简单地完成更多事情。

于 2021-08-11T15:45:13.007 回答