Refactor/Rename and C++ #ifdefs
I am a long-time user of Visual Assist X who is now test driving Resharper C++. The test drive has gone reasonably well so far, but I have encountered one significant issue related to code where portions are inside #ifdefs.
I work with a very large code base that is built for many platforms/configurations. We have a bunch of code specific to certain configurations that can be found inside #ifdefs. Some of the features of Resharper aren't working in the way I'm expecting and am wondering if there are any configuration options that could help.
For example, if I write the following code:
int variable = 12;
variable += 4;
#if CONFIGURATION1
variable += 8;
#endif
the code inside the #if is correctly identified as disabled for my configuration. When I run “Find Usages” (Shift-F12), Resharper only identifies “variable += 4” in the main output. However, it does successfully identify “variable += 8" as “Found 1 possible usage in inactive code”. That part seems fine.
However, if I do Refactor/Rename (Ctrl-R R) to rename “variable” to “variable2”, it only renames the “variable += 4” reference. “variable += 8” would retain its original name. This would break any build flavor with CONFIGURATION1 enabled. Is there any configuration option that would allow Resharper to rename “inactive” references?
I've never had rename problems with Visual Assist. They offer a dialog that lets me select the set of references to rename, where known-good references and “inactive” ones are selected by default and some other “guesses” are unselected by default but can be selected. (BTW – This interactive selection mechanism in VAX turns out to be useful for stamping out new C++ classes using old ones as a starting point. I have some unit tests that use classes to stamp out a family of tests. When I build a new test family, I often start by cloning an old one to use some of it as boilerplate. To do this, I just copy the old test class to a new file and then interactively rename it to use the new class name. I select references in the new file and deselect references in the old one and I'm good to go.)
Thanks for any assistance here.
Please sign in to leave a comment.
Hi!
When you invoke refactoring, please try enabling "Search in comments and string literals" in the Rename window.
Then, ReSharper will show a list of possible usages to rename.
Elvira,
Thanks for the follow-up. How did you trigger that dialog? I can also see a dialog like that in the help information here:
https://www.jetbrains.com/help/resharper/Refactorings__Rename.html#invoking-the-refactoring-with-a-command
However, when I trigger the rename in Resharper C++ with the context menu, Ctrl-R / R, Extensions → Resharper → Refactor → Rename, or other means, all I get the “refactoring in place” feature described here:
https://www.jetbrains.com/help/resharper/Refactorings__Rename.html#performing-the-refactoring-in-place
where you simply type the new variable name on top of the selected name. That doesn't seem to provide a way for me to get to the dialog you reference – I tried the context menu while that's active and found nothing relevant. That was how I tested out the rename in my example above.
The dialog itself seems to provide functionality similar to what I'm used to with Visual Assist, though having inactive references counted as “comments and string literals” is a little odd. It might be more accurate to label that option as “inactive code, comments, and string literals”.
The in-place refactoring is usually suggested for simple cases in the local scope. Please try to invoke Rename in some global scope to enable mode with textual occurrences.
Thanks. Based on experiments, it looks like Resharper has a couple different “modes” for renaming. I'm including a stupid example below to illustrate:
The net seems to be that the dialog-based options in Resharper seem to do the right thing as far as I'm concerned, while the in-place method does not. I consider that to be a bug. I assume there is no easy option to *not* use the in-place method in cases like that?
The good thing here is that the main cases where I'm worried about this involve contexts that naturally involve a dialog (e.g. renaming methods, class members, or global variables). The broken support for renaming locals is a secondary issue, though I will probably hit that issue from time to time.
Thanks,
Pat
--
MAIN EXAMPLE:
class X
{
// m_member1 is a very pretty member.
int m_member1;
// no comment on this member name
int m_member2;
// don't mention this method name
void method2();
// method3() is a cool method name.
void method3();
};
void X::method2()
{
// value is a cool local variable name.
int value = 2 * 3;
value += 4;
#if DISABLED
value += 5;
#endif
m_member1 += value;
m_member2 += 3;
#if DISABLED
m_member1 += 1;
m_member2 += 4;
#endif
}
void X::method3()
{
int value = 2 * 2;
value += 1;
#if DISABLED
value += 1;
#endif
m_member1 += value;
m_member2 += 1;
#if DISABLED
m_member1 += 1;
m_member2 += 1;
#endif
}
--
EXAMPLE WITH #ifdef'ed method2():
#if !DISABLED
void X::method2()
{
// value is a cool local variable name.
int value = 2 * 3;
value += 4;
#if DISABLED
value += 5;
#endif
m_member1 += value;
m_member2 += 3;
#if DISABLED
m_member1 += 1;
m_member2 += 4;
#endif
}
#else
void X::method2() {}
#endif
Thanks a lot for the detailed examples and thorough analysis! We'll look into the limitations of the in-place renaming.
Sorry for the inconvenience.