Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to convert to a NodePath? #64

Closed
TheSavior opened this issue Oct 28, 2015 · 5 comments
Closed

How to convert to a NodePath? #64

TheSavior opened this issue Oct 28, 2015 · 5 comments
Labels

Comments

@TheSavior
Copy link
Member

I'm trying to create a transformer that will go from:

React.createElement(Foo, null);
React.createElement(Foo, { bar: "baz", onClick: this.divClicked });

React.createElement(
    Foo,
    { bar: "baz", onClick: this.divClicked },
    React.createElement("div", { foo: "bar" })
  );

to

<Foo></Foo>;
<Foo bar="baz" onClick={this.divClicked}></Foo>;

<Foo bar="baz" onClick={this.divClicked}>
    <div foo="bar">
    </div>
</Foo>

I've gotten the first two examples, but I'm confused on recursively handling the children.

My interactive codemod is here: http://felix-kling.de/esprima_ast_explorer/#/hb6iLO9hTe/4

If I change convertNodeToJSX to:

function convertNodeToJSX(node) { 
    if (!node) {
      return;
    }

    console.log(node);

   // other code

   const children = convertNodeToJSX(args[2]);

then I get printed out

NodePath {value: Object, parentPath: NodePath, name: "expression", __childCache: Object}
NodePath {value: Object, parentPath: NodePath, name: "expression", __childCache: Object}
NodePath {value: Object, parentPath: NodePath, name: "expression", __childCache: Object}
Object {type: "CallExpression", start: 175, end: 217, loc: i, callee: Object…}

So how can I convert the CallExpression to a NodePath? Wrapping the element with j() gives me:

e {_parent: undefined, __paths: Array[1], _types: Array[5]}

Or perhaps as a higher level question, is this even the right approach?

@fkling
Copy link
Contributor

fkling commented Oct 28, 2015

Recast (ast-types actually) provides two APIs: One lets you access the underlying "raw" AST node, with .value or .node, as you already know. The other gives you a NodePath instead of the raw AST node value.

Examples:

var args = path.value.arguments; // array of AST nodes
var args = path.get('arguments'); // NodePath representing the array of AST nodes

.get takes multiple arguments. To get the NodePath to the first AST node in arguments, you can do:

var pathToFirstArg = path.get('arguments', 0); // or args.get(0) from above

See also https://github.com/benjamn/ast-types#nodepath .

Wrapping the element with j() gives me ...

j will always return a collection of NodePaths.

@TheSavior
Copy link
Member Author

Perfect. Thanks, that helped me get there.

Do you have any thoughts as to where I should put this codemod transform? I'm either going to start a repo myself or open a PR to a pre-existing collection of transforms. Do you have any opinions on where it should go?

I imagine there is a lot of value for people who start without Babel/JSX and want to convert their codebase later to use JSX.

@cpojer
Copy link
Contributor

cpojer commented Oct 29, 2015

Feel free to create your own repo or send a PR to https://github.com/cpojer/js-codemod which I have used as a collection of useful codemods that I ran at FB.

@fkling
Copy link
Contributor

fkling commented Oct 29, 2015

@cpojer: What about https://github.com/reactjs/react-codemod ? Is that more for API changes between versions?

@cpojer
Copy link
Contributor

cpojer commented Oct 29, 2015

Oh yeah, react-codemod is fine for React specific codemods.

@fkling fkling closed this as completed Oct 29, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants