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.

0
5 comments

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.


0

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”.

0

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.

0

Thanks.  Based on experiments, it looks like Resharper has a couple different “modes” for renaming.  I'm including a stupid example below to illustrate:

  • When I try to rename method2() to method4(), it pops up a dialog like you illustrate.  But with no references to method2() in the comments, it changes to my new name without any selection dialog.
  • If I change the implementation of method2() to use an #ifdef with two different implementations (second example below), the dialog lets me choose whether to rename the inactive reference.
  • When I try to rename method3() to method4(), I get the same dialog.  But after hitting enter after choosing “method4”, it lets me decide whether to rename my comment above the declaration of method3().
  • When I change the members m_member1 and m_member2 to m_member3, I get the same starting dialog to enter “m_member3” as the new name.  For m_member1, I have a list with checkboxes on renaming the comment above its declaration and the two #ifdef'ed out references.  For m_member2, the rename gives me an option of changing the two #ifdef'ed out references.
  • If I change either of the locals “value”, it will use the in-place method and not provide any support for renaming comments or inactive references.

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
 

0

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.

0

Please sign in to leave a comment.