Abstract: Fixing function names with Understand’s Rename Refactor tool, and some recent improvements to it.
Part of our company programming policy is if you’re touching a file anyway, you might as well fix stylistic bugs. Failure to do this results in an email informing you of all the CodeCheck violations you could have fixed but didn’t (learn how to set up email notifications for CodeCheck violations in this article). It’s slightly better than the email notification that you’ve added new CodeCheck violations, but no email is best.
One of our style conventions is naming. Functions should be named with lowerCamelCase. How to fix badly named functions? The brute force method is the general Replace in Files, but there is a better, more targeted option. Refactor->Rename is entity-specific and available from the right-click menu of the function! It’s even had some smartness added to it in the past few years so that renaming a C++ class also renames constructors and destructors, and renaming an overridden method gives you the option of renaming that method for the entire inheritance tree.
Refactor rename accuracy depends on parse accuracy, so make sure your project is set up accurately. If it does go wrong, you can undo it from the right-click menu (an undo option will be available in the same place as the rename option).
In my experience, with an up-to-date parse, I don’t have problems with Refactor Rename. But, like another engineer on our team, I sometimes get impatient and try to do a series of renames all in a row without parsing between each one. This is especially true when working with a class where every method needs to be renamed.
Let’s see what we can do to solve that. In this case, it would be helpful to know where the Refactor Rename failed. Things like: the call reference on line X of file Y wasn’t renamed.
There are two possible questions related to these failures: 1) why does the rename sometimes fail and 2) why weren’t the failures reported?
The answer to the first question, Refactor Rename errors on the side of caution. Consider this function call:
indent(file,indent);
To rename the indent function and avoid renaming the indent parameter, the search for the word “indent” is targeted to the column where “indent” is expected to be. The search is a little fuzzy, but the editor contents have to be close enough to the original contents that the text can be unambiguously mapped back to the function “indent.”
So, occasional failures make sense on files where the parse is out of date. Why didn’t Understand report these failures?
The problem has been false positives. Rename is actually pretty simple conceptually: grab all the references for an entity and search each reference’s line at the given column for the entity’s name. If the name is found and belongs to the starting entity, replace it with the new name. The false positives come from that “all” references. Many references aren’t expected to have the entity’s name. For instance, in the reference “functionA() calls functionB()”, the name “functionA” won’t appear on the same line as the call to FunctionB even though it is one of functionA‘s references.
void functionA()
{
// functionA calls functionB on the next line, but functionA’s name is not on the line.
functionB();
}
There are a lot of different languages and references in Understand, so determining which references are expected to have the entity’s name isn’t trivial. But working with the senior engineer for each language, we’ve determined a master list for renaming. Now (build 1092) if the entity’s name isn’t found, Understand will report it in the search results window.
If you haven’t checked out the search results window yet, you should try it now. It unifies Find in Files and Instant Search results (and now also features the failure results from Rename) and supports dismissing individual results with a stylish hover x icon.
Showing rename failures means you have been empowered to recklessly rename many entities in a row, just like I do.