Code Refactoring with Regex Find and Replace
Tags: tutorial, productivity
Published: 2022-10-14 13:39:17

When faced with a major refactoring task across your codebase don't forget you can use Regexes to do the heavy lifting for you, potentially saving you hours of work!

Let me show how I used a Regex to update over 1000 method calls across hundreds of files in about 5 minutes instead of a day's work!

## My Refactoring Task

In one section of code, I had many duplicated methods that could be replaced with a single generic getter. All the methods did was coerce a value from a configuration object and return this to the rest of the codebase without exposing the underlying object.

But how do you go about updating hundreds of these method calls when there are many different properties names and call locations? 

Fortunately, all the methods follow a naming convention so we can take advantage of this and automate the update via Regex find and replace. 

### Old Code

We had many methods of this format:

```ts
public isMaintainColumnOrder() {
    return isTrue(this.gridOptions.maintainColumnOrder);
}
public isSuppressRowTransform() {
    return isTrue(this.gridOptions.suppressRowTransform);
}
public isSuppressColumnStateEvents() {
    return isTrue(this.gridOptions.suppressColumnEvents);
}
```

Which were then called like this.

```ts
if(this.gridOptionsWrapper.isMaintainColumnOrder()){
    ...
}
```

### New Code

To be replaced with calls to the following method:

```ts
public is(property: keyof GridOptions) : boolean {
  return isTrue(this.gridOptions[property])
}
```

Called like this.
```ts
if(this.gridOptionsWrapper.is('maintainColumnOrder'){
    ...
}
```

The change will result in the following diff:

```diff
- if(this.gridOptionsWrapper.isMaintainColumnOrder()){
+ if(this.gridOptionsWrapper.is('maintainColumnOrder'){
```

## Breaking Down the Changes Required

Thanks to the naming convention the changes follow this pattern:
 
 1. Extract the property name after the `is` prefix in the original method call
 2. Lowercase the first letter of the matched property name
 3. Place the updated match into single quotes and parenthesis 


## Required Regexes

When doing a find and replace in VS Code we require two regexes. The first is used to find the code to update and extract the required information. The second regex is used to format the information, via a transformation, to be the new code.

### Find Regex

This is the regex we use to match all our method calls.

```ts
gridOptionsWrapper.is(\w*)\(\)
```
Let's break this down.

 - `gridOptionsWrapper.is`: first find this string
 - `(\w+)`: now match one or more word characters for the method name and extract this into the regex group result
 - `\(\)`: match the parenthesis `()`. `\` is an escape character so we can match a parenthesis. 

When the Regex sees the following code we will get a full match and also the extracted group match.

```ts
if(this.gridOptionsWrapper.isMaintainColumnOrder()){
```
- Full Match: `gridOptionsWrapper.isMaintainColumnOrder()`
- Group: `MaintainColumnOrder`

This is enough information for us to make the transformation.

### Replacer

This is the regex we use to construct the new method call.

```
gridOptionsWrapper.is('\l$1')
```

This replaces the code in the following way:
 - `gridOptionsWrapper.is` remains unchanged
 - `('` open parenthesis and single quote
 -  `\l` lowercase the first letter of the next section
 - `$1` provide the matched group
 - `')` close quote and parenthesis

This gives us the required diff for every single one of our `is` lookup methods no matter what the property name is.

```diff
- if(this.gridOptionsWrapper.isMaintainColumnOrder()){
+ if(this.gridOptionsWrapper.is('maintainColumnOrder'){

- if(this.gridOptionsWrapper.isSuppressRowTransform()){
+ if(this.gridOptionsWrapper.is('suppressRowTransform'){
```

Then it is a matter of running through the changes or just hitting that "Replace All" button and committing! :P

![VS Code Regex Find and Replace](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p47w6t96ygaiztfcs2h8.png)

## Conclusion

Don't forget about all the tools built into your IDE that can save you time and effort. Using Regexes for Find / Replace is just one example of the tools at your disposal.