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:
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.
if(this.gridOptionsWrapper.isMaintainColumnOrder()){
...
}
New Code
To be replaced with calls to the following method:
public is(property: keyof GridOptions) : boolean {
return isTrue(this.gridOptions[property])
}
Called like this.
if(this.gridOptionsWrapper.is('maintainColumnOrder'){
...
}
The change will result in the following 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:
- Extract the property name after the
is
prefix in the original method call - Lowercase the first letter of the matched property name
- 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.
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.
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.
- 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
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.
Top comments (0)