Discussion on how to integrate with Babel's ability to use recast #168

Open
hzoo opened this Issue Nov 8, 2016 · 2 comments

Projects

None yet

3 participants

@hzoo
Contributor
hzoo commented Nov 8, 2016 edited

So after babel/babel#3561 allows babel to use recast as the parser/generator and the other prs fixed the babel 6 ast nodes for ast-types/recast we should be able to use babel as the transformer for jscodeshift.

Is there anything we want to do to the api to make it easier or should users just add it in themselves? babel-core/recast are already dependencies, but yeah it's not necessary (Ah I see babel-core is v5 for the babel 5 parser). Maybe it's just a docs change.

module.exports = function(fileInfo, api) {
  return api.jscodeshift(fileInfo.source)
    .findVariableDeclarators('foo')
    .renameTo('bar')
    .toSource();
}
const transform = require('babel-core').transform;
const recast = require('recast');
const plugin = require('./plugin');

module.exports = function(fileInfo, api, options) {
  return transform(fileInfo.source, {
    parserOpts: {
      parser: recast.parse
    },
    generatorOpts: {
      generator: recast.print
    },
    plugins: [plugin]
  }).code;
};

// ./plugin.js
module.exports = {
  visitor: {
    VariableDeclarator({ node }) {
      if (node.id.name === "foo") {
        node.id.name = "bar";
      }
    }
  }
};

Also interesting sidenote would be using the jscodeshift type api in babel

cc @fkling, @cpojer, @drewml

@benjamn
Member
benjamn commented Nov 8, 2016

My two cents:

The Visitor-based transformation API used by Babel tends to be better for complicated transforms, and transforms that need to be run by other people who don't fully understand what's happening behind the scenes, which means handling more edge cases automatically, and not giving up in cases when it's easier to edit the code by hand.

The Collection-based API is much better for hand-supervised codemods, and for transforms where it's ok if you don't handle every edge case, because you know that certain patterns of syntax are rare in your specific codebase.

These may not be the only possible options in the API landscape, but they've proven effective in their respective niches. I don't think it necessarily makes sense to unify them into one API, but I'm totally in favor of making both kinds of transforms easier to write, if possible.

@fkling
Member
fkling commented Nov 9, 2016

Is there anything we want to do to the api to make it easier or should users just add it in themselves?

While I understand that having everything shipped with jscodeshift could be more convenient, I'm also a bit afraid of overloading it with too many features and thus making it more confusing.

I think it would be more valuable over all if we make it easier to "load" transforms from locally or globally installed packages, rather than reading a file. That would make it easier to distribute codemods with dependencies, such as in your example or what is proposed in #162 (assuming this becomes its own package).

We should also have more examples of transforms with dependencies.

Maybe we could have a separate babel-jscodeshift package that simply wires recast and babel together, so you only have to load that one? Something like:

const transform = require('babel-jscodeshift');

module.exports = function(fileInfo, api, options) {
  return transform({
    visitor: {
      VariableDeclarator({ node }) {
        if (node.id.name === "foo") {
          node.id.name = "bar";
        }
      }
    }
  });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment