
Write Code to Rewrite Your Code: jscodeshift - PaulHoule
http://www.datasciencecentral.com/profiles/blogs/write-code-to-rewrite-your-code-jscodeshift?utm_content=buffer598df&utm_medium=social&utm_source=linkedin.com&utm_campaign=buffer
======
GeZe
You can similarly search/replace JS code, but using pattern matching and CSS
style selectors instead of writing code, with Grasp. It's usable from the
command line like sed.

[http://www.graspjs.com/](http://www.graspjs.com/)

For instance changing all calls to "calc" from taking two arguments to taking
one object literal instead (eg. `calc(1, 2)` to `calc({from: 1, to: 2})`, is
as easy as:

    
    
        $ grasp -r -e 'calc($a, $b)' -R 'calc({from: {{a}}, to: {{b}}})' file.js
    

(Where the two arguments to "calc" could be any arbitrary nested expressions,
which could not be safely handled by a regular expression)

~~~
fkling
(Disclaimer: I'm maintaining jscodeshift)

Yes, this is great! I'd love to be able to integrate graspjs with jscodeshift
somehow. Ideally there would be multiple possible ways to _find_ the nodes you
want to change (pattern matching, tree traversal, etc), and multiple ways to
specify how to _replace_ them (e.g. a template like in your example vs a
function where you can do anything you want).

Simple transforms should definitely be possible with little "code" like in
your example and we certainly have to improve jscodeshift in this regard.

------
pag
This seems similar to Cocinelle [1], which can perform complex refactorings
and bug finding for C code (e.g. the Linux kernel).

[1] [http://coccinelle.lip6.fr/sp.php](http://coccinelle.lip6.fr/sp.php)

------
nthitz
Original article here [https://www.toptal.com/javascript/write-code-to-
rewrite-your...](https://www.toptal.com/javascript/write-code-to-rewrite-your-
code) (linked at the bottom) has proper code snippets, but a super annoying
fullpage interstitial.

------
alxlu
Is anyone else seeing the code samples getting cut off? Seems to happen to me
in Chrome on both OS X and Ubuntu. The page shows:

    
    
        export const sum = (a, b) => { re
    

And when I copy and paste the line the rest of it is copied to the clipboard.

~~~
throwanem
I think everybody is; it looks like whatever CMS they're using eats newlines
out of content pasted into <pre>s, because there aren't any in the source.

Maybe it's a cavil, but I'm not overjoyed at the thought of doing global
search and destroy on my codebases with a tool I heard about on a website that
messes up something that basic.

On the other hand, apparently jscodeshift itself comes from Facebook [1], and
they tend to do good work (on a technical level, at least); perhaps it'd be
worthwhile to change the HN link to point to that repo, not least because the
code samples aren't munged to unintelligibility there.

[1]
[https://github.com/facebook/jscodeshift](https://github.com/facebook/jscodeshift)

~~~
15155
> I'm not overjoyed at the thought of doing global search and destroy on my
> codebases with a tool I heard about on a website that messes up something
> that basic.

When I am writing jscodeshift scripts, it's a constant cycle of git checkout
-> run codemod -> git checkout.

Nobody is saying you need to commit the changes: review them by hand if you
will. I've never had a problem with jscodeshift itself. Publicly available
transform scripts though are quite hit or miss.

~~~
throwawaysocks
Could you share links to buggy ones? I'm interested in seeing how they go
wrong.

~~~
15155
I can't name any specific situations, but it will generally come down to the
fact that your project is different from whatever the script writer was
anticipating.

For instance: import statements vs. require expressions - these need to be
handled with different AST matchers. Import statements themselves have 3
different varieties of specifiers (default, named, "all") which must be
accounted for. A require expression may or may not involve destructuring, it
may or may not use const or let over var (each of which need to be handled
explicitly, etc.)

As far as failure mode: scripts generally just won't match or work, or they
might replace all of your consts with vars, etc - they can be very codebase
specific depending on the complexity of the script.

------
mofle
We use jscodeshift [0] in the AVA project to enable our users to run one
command to migrate breaking changes in their tests automatically. This really
is the future of breaking changes!

[0]: [https://github.com/avajs/ava-codemods](https://github.com/avajs/ava-
codemods)

------
skrebbel
Jscodeshift is remarkably easy to write scripts for. It is why I'm very
comfortable using all kinds of experimental babel plugins: If somehow the
proposed standard changes or just never makes it and I want the code to be es6
compliant (or, say, move it over to a different compiler), then I know that
for most cases I can easily write a codemod that makes the changes in our
codebase.

Nice examples are stuff like decorators or the :: bind operator.

------
rjbwork
That this sort of thing is necessary is crazy. I couldn't live without my
automatic refactoring tools in other languages.

~~~
2muchcoffeeman
In other languages you don't _need_ refactoring tools so much. I use the Idea
refactoring a lot, but really I can change a method signature, or rip out some
code into another method and watch it fail to compile and fix the problems one
by one.

~~~
rjbwork
Well, yeah, but the fact that that is also possible lets you have those
automatic refactoring tools because it's easy to understand what's going on
with the code in static analyzers and compilers, etc.

------
jcoffland
How do you avoid the problems of reformatting the output code? For example, I
want long lines broken up in a consistent manner. Doing this correctly in a
language like JavaScript is hard. Also, how can I configure the tool to follow
a formatting style other than the default?

~~~
fkling
jscodeshift is primarily a wrapper around recast. Recast takes care of all the
printing. It's smart enough to reuse the original source code for AST nodes
that haven't been changed.

As for formatting, there are some options to influence the pretty printer, but
not a lot [1]. It will infer things like indentation from the existing source
code. I'm not sure right now how it handles long lines.

Whenever we run into issues with the printer, we just create a PR to fix it.
Getting automatic code formatting right is apparently quite hard. There are
dedicated tools for this, such as
[https://github.com/millermedeiros/esformatter](https://github.com/millermedeiros/esformatter)
.

[1]:
[https://github.com/benjamn/recast/blob/master/lib/options.js](https://github.com/benjamn/recast/blob/master/lib/options.js)

------
fiatjaf
Nice, now I can use that to write the code that will rewrite the code of the
software I'm developing that will help others code better, so they can launch
startups that assist developers in coding new development tools for startups.

~~~
fiatjaf
Yes, I didn't read this thing, they're using a very bad CMS. I bet it's
Wordpress.

~~~
fiatjaf
I was wrong, it is not.

------
smrq
Does anyone know of something similar for TypeScript?

