如何在Jscodeshift中正确导出const

时间:2019-08-12 16:01:15

标签: javascript jscodeshift

我正在使用Jscodeshift编写我的第一个codemod。 我当前的目标是导出分配了特定标识符的const。

因此,如果我定位每个名为stuff的变量,则在脚本运行后将对其进行命名-导出。

IN:

const stuff = 4;

OUT:

export const stuff = 4;

这是我所拥有的精简版本。它可以正常工作,但看起来很脆,并且有很多缺点。

const constName = "stuff";

module.exports = (fileInfo, api) => {
  const j = api.jscodeshift;
  const root = j(fileInfo.source);

  const declaration = root.find(j.VariableDeclaration, {
    declarations: [
      {
        id: {
          type: "Identifier",
          name: constName
        }
      }
    ]
  });

  declaration.forEach(n => {
    n.insertBefore("export");
  });

  return root.toSource();
};

AST

这将导致(注意不需要的新行)

export
const stuff = 4;

如果将此源提供给脚本,这也将严重失败。

IN:

// hey
const stuff = 4;

OUT:

export
// hey
const stuff = 4;

我非常确信n.insertBefore("export");确实是这里的罪魁祸首,我想使用jscodeshift构建器自己构建命名的导出文件,但实际上无法使其工作。

这里有什么建议吗?

1 个答案:

答案 0 :(得分:1)

.insertBefore不是正确的使用方法。这是为了在另一个节点之前插入整个新节点。

如何用VariableDeclaration 替换 ExportNamedDeclaration。如果查看export const stuff = 4;的AST,您会发现它具有属性declaration,其值为VariableDeclaration节点。这使我们的转换变得容易了:找到VariableDeclaration,创建一个新的ExportNamedDeclaration,将其declaration属性设置为找到的节点,然后用新节点替换找到的节点。

要了解如何构建节点,我们可以查看ast-type's ast definitions

const constName = "stuff";

module.exports = (fileInfo, api) => {
  const j = api.jscodeshift;

  return j(fileInfo.source)
    .find(j.VariableDeclaration, {
      declarations: [
        {
          id: {
            type: "Identifier",
            name: constName
          }
        }
      ]
    })
    .replaceWith(p => j.exportDeclaration(false, p.node))
    .toSource();
};

astexplorer