Hello, my name is Raman Sharma, and I am a Program Manager on the VC++ team. Through this blog post, I wish to highlight some changes we have made to an important feature in the C++ IDE, called “Find all References”. As most of you would know, this feature is used to search for references to any element of your code (classes, class members, functions etc.), inside the entire solution. In Visual Studio 2010, we have made some changes to this feature to provide more flexibility.
Let’s look at these changes through an example. Let’s say you have the following piece of code:
Figure 1: Sample Code
In Visual Studio 2008, if you invoke “Find all References” on the member function printArea of class Circle as in:
Figure 2: Invoke Find all References
You will see the results showing line numbers 7, 20 & 26 as below:
Figure 3: Results in VS 2008
It is to be noted that the results window does not list all the places the word “printArea” appears. It only lists specifically the places where printArea means the “member function printArea of class Circle” (on which Find all References was invoked). The point is that this is in some sense a compiler-verified-search (I just coined that term but the concept is correctJ) wherein you will get exactly the C++ symbol you searched for.
In Visual Studio 2010 we have effectively created two modes of search: one that focuses on speed and the other that focuses on accuracy. Needless to say, you can specify the default mode through options and we will remember that setting. More on that later in this post.
If you perform the same operation as described above in VS 2010, by default you will get the following results:
Figure 4: Default results in VS 2010
Please note that this time around, the results window does list all the places the word “printArea” appears (including the comments!). Why? Because we wanted to provide the user with an option to search without invoking the compiler. Needless to say, this option will speed up the search significantly, especially for large projects with a lot of hits.
It’s worth mentioning that this search is unlike just searching for some text in the entire solution. This is because for this search, the C++ IDE uses an index to narrow the list of files to search. So it doesn’t look through all the files in the solution. The outcome is significantly better performance than just “Find in Files” (or grep), especially for large solutions.
However, we understand that there can be instances where you want to reduce the ambiguity by filtering the results further. This means you want better accuracy. If you search for a member function of a class, you only want references to that member function of that class. This is even if there are other classes with same named members or other overloads for this function within the same class. To do this, right-click on the results in the results window and invoke “Resolve Results”:
Figure 5: Invoke Resolve Results
“Resolving results” uses the compiler to actually verify/confirm the entries and removes references that don’t precisely match. You will be presented with the following results which contain only exact references to Circle::printArea:
Figure 6: Resolved results in VS 2010
If you are feeling more adventurous, there is another part of the accuracy mode which is like asking the following question to the compiler: “Filter out as many extraneous results as you can, and for those you are not sure about, show them anyway”. The reason you would want to ask that question is if you want comments, code in different macro states etc. to be included in the search results.
The way to ask this question is to simply right-click on the resolved results in the window and to uncheck “Hide Unconfirmed”:
Figure 7: Uncheck "Hide Unconfirmed"
Doing this will make sure that search results will exclude only those results which the compiler has verified are definitely not references of Circle::printArea. Anything that the compiler verifies is correct and anything it is not sure about will be listed. The results will be as shown below:
Figure 8: Resolved and Unconfirmed results in VS 2010
Notice this time the results include the comments. It’s worth mentioning that this is the only mode that was supported by VS 2008
The default mode for search is the speed mode. This means, when you invoke Find-all-References, you will see all the places your search item appears. However as with everything else in Visual Studio, there is a way to change this default behavior. If you go to “Tools -> Options -> Text Editor-> C/C++ ->Advanced”, under References you will find two new options “Disable Resolving” and “Hide Unconfirmed”:
Figure 9: Options to set default search mode
By default the “Disable Resolving” flag is set to True (means Speed mode). Setting it to False would cause all results to be verified with the compiler (means Accuracy mode). Similarly the default value of “Hide Unconfirmed” flag is True. Setting it to False will ensure that search results will contain unconfirmed results in addition to the resolved results. The second flag makes sense only when the first flag is set to False. Also to be noted is that resolving/unresolving from the results window will not affect the values of these flags. These are global settings meant to specify default behavior.
Overall, we believe that these changes have introduced more flexibility enabling users to optimize their experience based on their own needs. We are excited about this change and hope you will like it.
The more I find out about VS2010 features in blogs, the more I think that once again lead developers should be people that weren't introduced to computers two years ago and hiring of people below shouldn't be based on how many people I can get overseas for as little money as possible. This is terrible.
It is to be noted that...
Please note that this time around, ...
It’s worth mentioning that ...
Oh, editor, we have too much excessive bloat where we should not have too much excessive bloat, so it is to be noted it's worth mentionong that tihs time around, please note this. Well, it's the only thing I noticed in this very boring topic.
For anyone else who feels that the double inverted options are confusing, I've submitted a bug report on connect so that it doesn't get forgotten. You might like to add a vote to it if you feel strongly about it.
This new fast approach by default is a little weird (I did not know that there is an accurate version till I saw this blog post), but I love the accuracy of this new feature.
The only shortcoming so far is that this findref. doesn't work on function parameters.
I don't understand why 'accurate' mode is supposed to be slow. You say that it 'invokes the compiler', but doesn't VS keep the stuff generated by the compiler front end in a database? There were several articles about how this was going to improve IntelliSense immensely - why isn't that same database used to implement a blindingly-fast (and accurate) find references?
I'd agree with others who suggest that this is option bloat. If I want to find references, I want to find actual references. If I want to find everywhere the text "printArea" appears, I'll use 'Find in Files'. If you want to add this 'faster' option, in my opinion it should be in 'Find in Files', not 'Find References'.
Please consider making accurate mode the default.
after reading through the comments and thinking about it a while, I agree to the position that I think makes the majority:
I would also like "positive naming" of options like "enable something". The default value can be flipped, this change would not imply other defaults.
And I strongly prefer the accuracy mode as default. If it is very slow, it should be improved in the next versions, I don't care, I definitely want exact results.
@mikeb - I agree with you. Make Accurate mode the default, after all isn't it supposed to be pretty dang fast? (that's what I've also gathered from new Intellisense write ups).
which leads me to... just how slow is Accurate mode? Isn't it still faster than Find In Files?
This has never ever worked for me (up until vc9sp1 with freshly generated intellisense). When I try to find all references for member functions in our production code I get numerous false results, even hits with less or more (non-defaulted) parameters (not to mention ones from totally unrelated classes and/or having different parameter types). The call browser (using the same information) is therefore equally useless.
Does this really work for anyone out there?
With the intellisense database completely rewritten in vc10, I might give it another try. Until now, we have all long since resorted to using only find in files (and no, I have no time to try the beta).
@David Lowndes: Thanks for creating the bug.
@q: Find all References doesn't work for local variables and function parameters. (Isn't their scope too limited :))
@mikeb @pike @Jamome: As you said, IntelliSense is indeed much faster. This refers to the help you get while writing your code e.g. auto-complete, member-list, parameter help, quick-info tooltips. This is possible now because we can parse your active file (using the compiler) on the fly without having to reparse the entire solution. However, the database that you referred to, is not populated using the compiler. While performing search like Find all References, the database can provide potential matches which then need to be verified with the compiler (or not).
@stof: We certianly hope you will have a better experience using these features with VS2010. If they do not work the way as expected, please feel free to log connect bugs.
Can we get find similar references functionality instead? I am forever finding multiple versions of the same function in large projects with only slight variation of the argument ordering or names.
A find duplicate code would be nice as well:
- parse code into syntax tree
- write syntax tree out to a generic format (i.e., use 'IDENTIFER' for identifier, NUMBER_CONSTANT for constant numbers)
- do substring matching on the output produced to find substrings longer than X symbols/tokens that match.
Step 2 above handles the case where File1 has
'a = 1 + b' and file2 has 'q = 33 + c' which is the same code when you convert it to
'IDENTIFER ASSIGNMENT_OP NUMBER_CONSTANT ADDITON_OP IDENTIFER END_OF_STATEMENT
Other commercial and open source projects use this well known technique to find identical or nearly identical code.
This is quite useful in poorly written asp.net web applications by cut and paste developers.
One can make the case that blocks of code (i.e., a sequence of generic tokens) can be compared based on just counting the number of each type of token and comparing blocks to see how close the token counts match.
I absolutely agree with the comments by stof. I use the Visual Studio 2008 “Go To Definition”, “Go To Reference”, and “Find in Files” commands but I find the “Call Browser” and “Find All References” commands to be useless for the reasons indicated by stof. The tools for analyzing C++ code took a major step backward after Visual Studio 6, and as of Visual Studio 2008 have not yet recovered. The lack of a good browser in subsequent versions of Visual Studio was a strong incentive to stay with Visual Studio 6 long after I would have otherwise switched to a newer version.
Visual Studio 6 had a very useful and accurate browser. I have been mystified as to why subsequent versions of Visual Studio have been unable to provide anything close to the functionality provided by the Visual Studio 6 browser. Visual Studio 2008 attempted to replicate some of this functionality but failed to provide accurate results (except in very small projects) and was therefore useless. The attempt to improve the presentation of the results seemed questionable at best (although it was hard to judge because of the inaccuracy).
One significant limitation of the Visual Studio 6 browser was that the default browser database did not include code from libraries. It was possible to include this code using a method described in an MSDN article. While the browser in Visual Studio 2008 does not have this limitation (a positive factor), it is still too inaccurate to be of any use.
The Visual Studio 2010 “Find All References” feature certainly seems to be an improvement over that provided by Visual Studio 2008. I do not plan to try the beta version and will therefore have to reserve judgment until the new version is released. I would be extremely happy if Visual Studio 2010 could provide at least the functionality and accuracy of the Visual Studio 6 browser; however, I have not read anything to make me think this will be the case.
Doesn't ANYONE on the VS IDE team admit this design was a massive mistake?
Everything I used in VC6 is now several clicks away. (no more right click to bring up a tool bar. now dig through menus)
Windows magically pop up, coving what I'm working on, fighting with each other over who is 'TopMost'. And there is no way to make any of them stop being 'TopMost', no matter how much you don't want it.
If I leave every window docked to prevent things covering what I am working on, my document space is about 35 characters wide. Even punched cards were 40!
You can't even work on a normal size dialog, because it doesn't fit in the IDE anymore.
Even the tabs are gone from the memory window. Now there are multiple windows fighting to see who can cover the source code first.
VC6 was the most awesome interface I ever had the privilege of using. VS 20xx's are the most awful.
I've seen postings saying this is what happens when you allow things to be re-written without adult supervision. I now agree.
Is there anyone out there who realizes what a mistake this was, and is lobbying for restoring a good IDE? Or am I alone?
> Find all References doesn't work for local variables and function parameters. (Isn't their scope too limited :))
Too limited to work properly, or too limited to justify finding references to? Can you explain the reason this doesn't work? The C# equivalent does not have this limitation.
A Find All References in Ultimate Beta 2 on a local variable either causes a dialog to appear, saying the variable isn't referenced, or gives references to unrelated items in libraries. This is with Resolve Results checked and Hide Unconfirmed unchecked. If the feature is designed to not work for local variables and parameters, why is it enabled for those items?
I'm hoping you can help me understand this feature better so that I can use it correctly.
Find all References didn't work for local variables and function parameters in VS 2008 either. I am not saying that was a reason for us not to do it again in VS 2010. Just that the effort required to enable it (in terms of refactoring of code) far exceeded the benefit, since these variables are relatively easy to locate by eye-balling. This is what I meant by their limited scope.
I write following statement without include regex header file
const regex r("(\\w+) (\\w+)");
After I use the "Find All reference" function, the IDE display "The symblo "regex" is not refereced".
It will be more useful to find the correct header file and add it automaically like the C# IDE does.