# CodeMod Tutorial - Part 2 - How?

In [part 1 of this series](./create-a-codemod-part-1-why-ckd7v6qw500opses112kz6sl4) we did a lot of talking about what Codemods are and why you should (or shouldn't) write them. This time we're going to get our hands dirty and write one.

There's quite a bit to get through in this part: we're going to examine an AST and construct a complete - albeit simple - codemod, little-by-little.

# Our Codemod

To keep this particular article at a reasonable length,
we'll develop a _very_ simple codemod. It'll simply rename
a method in all JavaScript classes it sees.  Specifically, it'll
rename `componentWillUpdate` to `UNSAFE_componentWillUpdate`.
(This change forms [part of a Codemod for React](https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles) but you don't need to know
anything about React to follow this tutorial.)

# Writing a Codemod

I've found this set of steps handy when developing codemods. If you don't do these things you can *easily* develop a codemod that changes the wrong code or changes the right code in the wrong way.  The TL;DR is "think before you code, and have some tests".

1.  Figure out what we want to change
    -   Ensure you understand precisely what structures you want the codemod to change, and precisely what you want it to change those things into.
2.  Figure out what we _don't_ want to change
    -   Do you _always_ want to make the change, or only when you're extending a particular class?
    -   Do you _always_ want to make the change, or only when there aren't any parameters?
    -   Find structures similar to what you think you want to target and decide if you want those to change too
3.  Construct a 'test bed'
    -   Develop one or more 'test' files containing examples of positive (things you do want to change) and negative (things you don't want to change) sample code
4.  Build a target profile
    -   Identify the AST structures you want to change and construct
5.  Fire tracer bullets
    -   Write codemod code that targets the structure you're hoping to reach, and makes a tiny change there. Don't attempt to make the full final change straight away. Focus initially on targeting.
    -   You may need to evolve your testbed as you do this
6.  Apply changes
    -   Now that you're targeting the correct nodes, write codemod code that makes the desired changes
7.  Use the codemod
    -   And be sure to check the output for unexpected changes!
8.  Evaluate
    -   Was it easier/quicker/better than making the changes by hand?

Let's work through those steps for our codemod:

## 1. Figure out what we want to change

That's easy. We want to find all class methods called `componentWillUpdate` and rename them
to `UNSAFE_componentWillUpdate`. We don't need to change structure; we're just changing the
name of an identifier.

## 2. Figure out what we don't want to change

Let's think about things _similar_ to what we want to change, to identify related things we
_don't_ want to change.

A convenient way to do this is to take the thing we want to target and create variants of
it, changing one thing at a time:

-   Our start point is that we want to change methods called `componentWillUpdate`.
-   We don't want to change methods that _aren't_ called `componentWillUpdate`.
-   We don't want to change _all_ functions that are called `componentWillUpdate`; only class methods.
-   We don't want to change `static` class functions that are called `componentWillUpdate`; only instance methods.
-   We only want to change the *name* of the `componentWillUpdate` method. None of its contents should change.
-   Do we _always_ want to change methods called `componentWillUpdate`?  If we were sharing
    this codemod publicly and therefore wanted to be super-careful, we should probably only change that method
    if it's on a class extending React's `Component` class, but let's just assume for the sake
    of this tutorial that we don't need to worry about that because we happen to know there are no uses
    of `componentWillUpdate` outside of our React components.

## 3. Construct a testbed

We now write some sample code to illustrate all the above positive and negative matches:

```js
class Class1 {
  // This should be renamed
  componentWillUpdate() {
    // This code should not be lost
    return false;
  }

  // This should not be renamed
  notComponentWillUpdate() {
  }
}

// This should not be renamed
function componentWillUpdate() {
}

class Class2 {
  // This should not be renamed
  static componentWillUpdate() {
  }
}
```

As we develop our codemod we'll run it against the above code to gain confidence that it's changing the correct pieces of code.

## 4. Build a target profile

We need to identify the AST pattern we want to target.  A particularly easy
way to do this is to use the excellent [AST Explorer](https://astexplorer.net/)
web site to explore the AST.

JSCodeShift uses the `recast` library, so make sure that's the selected option.

Here is a link to AST Explorer with
the above code already entered, and the
correct options selected: <https://astexplorer.net/#/gist/4ba8eac986f73baf39c5c9683af03b93/10917053e0e1b9b41cc3dd9b806f0cec69d9ac00>

Go take a look at that. I'll wait.  Make sure you click around the sample
code (on the left) and examine the appropriate parts of the syntax tree (on the right).  Look to see what sorts of AST nodes we're going to be interested in.

After a little clicking around we can see that we're interested in `MethodDefinition` nodes whose `key` is an `Identifier` with a `name` of `componentWillUpdate`.

_Aside_

One area of difficulty when working with these ASTs is that different parsers produce slightly different AST structures. The `esprima` parser generates `MethodDefinition` nodes whereas the `babylon7` parser calls them `ClassMethod`s.

For this reason, it's vital to ensure you're using the exact same parser configuration in AST Explorer that you'll be using when running your codemod.

Note in particular that `recast` is merely a layer on top of a real parser, so when we use `recast` in AST Explorer, it's important to choose the appropriate parser from the recast settings.

## 5. Fire tracer bullets

This is where things get interesting.

At this point, we're actually going to create and run a real codemod.  The neat thing is that we can do it _directly inside AST Explorer_.

Click the 'Transform' button in AST Explorer and select 'JSCodeShift'.  The two-window display will change into a four-window display.  The two new panes at the bottom are the codemod source (bottom-left) and the resulting output (bottom-right).

AST Explorer gives us a sample codemod that reverses all of the identifiers in the source.
That sample is a little more complex than we need, so replace the codemod code with this simpler skeleton:

```js
1. export default function transformer(file, api) {
2.   const j = api.jscodeshift;
3. 
4.   return j(file.source)
5.     .find(j.Identifier)
6.     .forEach(path => path.node.name = 'Foo')
7.     .toSource();
8. }
```

It's only 8 lines long but it is a complete codemod! Let's walk through it, line-by-line:

-   1: The codemod consists of a single exported function called with the current file and the JSCodeShift API.
-   2: We extract the `jscodeshift` helper from the API and call it `j` as we will be using it a lot.
-   4: Here we begin a multi-line chained operation passing objects from one function to another: we start by parsing the current file. JSCodeShift will return a wrapper around the file that allows us to perform sophisticated search and replace operations.
-   5: We search for anything of type `Identifier`. Note the uppercase `I` in `j.Identifier`: this references the _type_ Identifier.
-   6: We tweak each (Identifier) node, changing its `name` to `Foo`.  We'll cover the `path` business in detail in the next article, so for now, just focus on the fact that we can write `path.node` to get the node in question.
-   7: We regenerate the output code from our modified tree by calling `.toSource()`.

If you look at the output pane you'll see that our code has been heavily transformed to:

```js
class Foo {
  // This should be renamed
  Foo() {
    // This code should not be lost
    return false;
  }

  // This should not be renamed
  Foo() {
  }
}

// This should not be renamed
function Foo() {
}

class Foo {
  // This should not be renamed
  static Foo() {
  }
}
```

Every `Identifier` - every mention of `x`, `somefunc`, `Array` and `NotArray` - has been changed into `Foo`, as we said it should in the code.

That's not (of course) what we want from our final codemod, but it serves to show how powerful codemods are, and it
provides a good basis for developing our codemod.
It'll require remarkably few changes to turn that into our final codemod!

## Target the correct thing

Firstly, we don't want to target *all* `Identifier`s.
From our AST investigations earlier, we know we want to start by finding all the `MethodDefinition`s.
Our tracer bullet will simply be to set the name of the method to `Foo`.  That's achieved by setting the `.name` property of
the method's `.key` property.

i.e.

```
1. export default function transformer(file, api) {
2.   const j = api.jscodeshift;
3. 
4.   return j(file.source)
5.     .find(j.MethodDefinition)
6.     .forEach(path => path.node.key.name = 'Foo')
7.     .toSource();
8. }
```

The output:

```js
class Class1 {
  // This should be renamed
  Foo() {
    // This code should not be lost
    return false;
  }

  // This should not be renamed
  Foo() {
  }
}

// This should not be renamed
function componentWillUpdate() {
}

class Class2 {
  // This should not be renamed
  static Foo() {
  }
}
```

We're now renaming all methods on classes, and we're not renaming the classes or functions.

But we're still hitting methods we don't want: we're renaming methods whose name is not `componentWillUpdate` and we're renaming `static` methods.

Happily, the `.find()` method takes a second parameter that supports property-based filtering.

We _only_ want to target:

-   methods named `componentWillUpdate`. We're looking for methods whose `key` property is an object with a `name` property equal to `componentWillUpdate`.
-   methods which are not `static`. We're looking for methods whose `static` property is false.

We adjust our `.find()` call as follows:

```js
 1. export default function transformer(file, api) {
 2.   const j = api.jscodeshift;
 3. 
 4.   return j(file.source)
 5.     .find(j.MethodDefinition, {
 6.       key: { name: 'componentWillUpdate' },
 7.       static: false
 8.     })
 9.     .forEach(path => (path.node.key.name = "Foo"))
10.    .toSource();
11. }
```

which produces the transformed output:

```js
class Class1 {
  // This should be renamed
  Foo() {
    // This code should not be lost
    return false;
  }

  // This should not be renamed
  notComponentWillUpdate() {
  }
}

// This should not be renamed
function componentWillUpdate() {
}

class Class2 {
  // This should not be renamed
  static componentWillUpdate() {
  }
}
```

That's perfect. We're now targeting exactly the one method we want
to, and leaving everything else alone.

# 6. Apply changes

For this codemod, this bit's easy. We don't need any information
from the existing node. We just want to set its name to `UNSAFE_componentWillUpdate`, which merely requires us to change
from setting `Foo` to `UNSAFE_componentWillUpdate`:

```js
 1. export default function transformer(file, api) {
 2.  const j = api.jscodeshift;
 3.
 4.  return j(file.source)
 5.    .find(j.MethodDefinition, {
 6.      key: { name: 'componentWillUpdate' },
 7.      static: false
 8.    })
 9.    .forEach(path => (path.node.key.name = "UNSAFE_componentWillUpdate"))
10.    .toSource();
11. }
```

So the output is now:

```js
class Class1 {
  // This should be renamed
  UNSAFE_componentWillUpdate() {
    // This code should not be lost
    return false;
  }

  // This should not be renamed
  notComponentWillUpdate() {
  }
}

// This should not be renamed
function componentWillUpdate() {
}

class Class2 {
  // This should not be renamed
  static componentWillUpdate() {
  }
}
```

That looks perfect!

# 7. Use the codemod

At this point, we'd run it across our codebase and carefully check
the output. We've done some due diligence so we're hoping it'll work
well, but there are often more edge cases that we've missed.

# 8. Evaluate

This isn't a fabulous codemod. It only replaces one method name,
and it doesn't rename existing _references_ to that method.
And to be honest, with what it _actually_ does, we could probably have
achieved the same thing with a regular-expression-based search
and replace.

If this was a codemod we'd be sharing with others, it would be
worth turning our sample code into a repeatable unit test, but we won't
cover that here.

Of course, our main objective here was to illustrate how to create
a simple codemod, and it hopefully served that purpose.  Let me know?

# Summary

We've covered how to use JSCodeShift to create a simple codemod
from scratch, but, as importantly, we've covered a
process for developing more reliable codemods.

Have fun developing some codemods, and let me know how you get on!

In [part 3](codemod-tutorial-part-3-paths-moving-nodes-ckd7ussl800metbs10pkzf7yh), we'll cover a more advanced codemod which involves moving
existing code around.
