如何在 jscodeshift 中包装除导入之外的所有顶层语句和声明?

How to wrap all toplevel statements and declarations except imports in jscodeshift?

我有这个 AST 浏览器 snippet,它几乎可以让我做我想做的事,就是把这个:

function bar() {return 42;}
var baz = {}
import 'get-outta-here';

进入

import 'get-outta-here';

function wrap() {
  function bar() {return 42;}
  var baz = {}
}();

即包装除 import 之外的所有顶级语句和声明。但是,我的 jscodeshift 转换有问题,我无法理解。

我怀疑我的包装逻辑不对:root.get().value.program.body 听起来很老套。

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

  const wrapper = j(j.expressionStatement(
        j.callExpression(
          j.functionExpression(
            j.identifier('foo'), [],
            j.blockStatement(root.get().value.program.body)
          ), []), []));
  
  const nodes = root.find(j.ImportDeclaration).nodes();
  root.find(j.ImportDeclaration).remove();

  // wraps, but doesn't re-add the import at top-level
  return wrapper.toSource();
  
  // fails
  // return wrapper.find(j.Statement).at(0).insertBefore(nodes).toSource();
  
  // moves it to the beginning, but no wrap
  return root.find(j.Statement).at(0).insertBefore(nodes).toSource();
}

知道了。只需使用 j.program 将适当的“程序”AST 放入 wrapper.

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

  const wrapper = j(
    j.program([
      j.expressionStatement(
        j.callExpression(
          j.functionExpression(
            j.identifier("foo"),
            [],
            j.blockStatement(root.get().value.program.body)
          ),
          []
        ),
        []
      )
    ])
  );

  const imports = root.find(j.ImportDeclaration);
  const nodes = imports.nodes();
  imports.remove();
  return wrapper.find(j.Statement).at(0).insertBefore(nodes).toSource();
}