Every symbol in your code has significance. Every symbol is a jumping off point for all sorts of investigation.
Typically you’ll be used to being able to see “All References” to a variable or class, and determine exactly how heavily used it is within your code.
This is a great way to get a general feel for where your code is used within your project\solution, but what happens if you need to ask some more specific questions? What if you wanted to find something more focused than “every reference” to your chosen symbol?
Enter the Navigation Menu
The Navigation menu (AKA the JumpTo menu) is your one stop shop for all sorts of navigation goodies.
Place your caret on any symbol in your code and hit Ctrl+Alt+N (or Num Decimal if you’ve enabled numeric keypad bindings)
I’ve chosen to place my caret on an instantiation of a StringBuilder in the source of OpenLiveWriter. As a result I’m being offered the choice of locating related Base Types, Declaration, Derived Types, Instantiations, Parent Types and more.
All I have to do to choose one of these options, is highlight one (using Arrow keys) and select it (using Enter).
Once selected, the Navigation menu will delegate to the appropriate NavigationProvider, which will then list all of the qualifying code elements.
In my case I’ve chosen ‘Instantiations’ because I’m interested in finding a particular piece of code I was looking at earlier which I know created a StringBuilder.
When I pick ‘Instantiations’ from the list I get the following window:
It looks like OpenLiveWriter uses quite a few StringBuilders within it’s code. However I remember that the code I was looking at, created it’s StringBuilder using the length of a buffer as a parameter.
So I type ‘buffer’ into the search window at the top of the list, and CodeRush narrows it’s list down from over 100 items, to only 6.
From here it was very easy to locate the code I was looking for. Once I found the correct entry, I simply hit [Enter] and CodeRush positioned me right where I wanted to be.
As you can see from our worked example, the Navigation menu can be very useful. However I’ve only scratched the surface. I worked through an example with the instantiations entry which, as you saw, provides a list of places where your chosen symbol is instantiated.
However if you recall the Navigation menu offered me 7 other choices to help us navigate to the code of our choice.
The last 2 of these are fixed items. Symbols and Files will take us to the Quick Nav and Quick File Nav features respectively.
The others are Navigation Providers each dedicated to locating a specific type of related code.
At the time of writing there are 11 NavigationProviders and counting. Each dedicated to a specific type of code relationship. The reason we only saw 6 of them in the previous example is that they are context sensitive. They only appear when appropriate.
- Base Types
- Derived Types
- Parent Type
- Overridden Members
While all of these providers are useful, I feel it’s worth drawing attention to a few of them in particular.
Firstly the Assignments provider. How often have you wondered about all the places in your code where a field is altered? The Assignments navigation provider will let you locate all the statements that assign a value to your chosen symbol.
The Base Types provider will provide you with a list, not just of immediate base types, but of the entire ancestral hierarchy of your nominated type, including interfaces.
The Implementations provider is particularly useful.
You can use this one on references to interfaces or abstract classes…
Place your caret on the reference to the interface and ask to see all implementations. Immediately you’ll be presented with a list of classes which implement the interface in question.
Ordinarily you might think to use the “All References” functionality to locate these classes. However the All References feature does exactly what it says. It returns ALL references and sometimes this can be a bit excessive. For example: Users of VB.net will be used to asking for All References to a given interface, and then having to deal with more results than they might want to. This is because the default interface implementation technique is explicit. As such the name of the interface is mentioned (and thus creates a ‘reference’) for each and every member in that interface. Implementations makes this a non-issue.
You can also use it on references to interfaces or abstract members…
Imagine you have a variable of type IFoo and are calling it’s Bar method. If you place your caret on the call to Bar and invoke the Implementations Navigation provider, you’ll be provided with a list of every class that implements IFoo and more specifically, the methods that implement IFoo.Bar. You’ll then be able to navigate directly to any one of them.
Naturally each Navigation Provider has it’s own custom set of options. These are typically used to filter the available list of items: Source Code vs Meta, Open Files vs All Files
Just tap Ctrl to reveal the options for any given Navigation provider
The Navigation Menu is so full of functionality that it’s starting to become the first place I go for almost any form of navigation. I highly recommend you check it out, whatever you’re looking for.
Can you think of an additional Navigation Provider you’d like to see? Let us know in the comments and we’ll see what we can do to help.
Oh and one more thing
The NavigationProvider user interface leaves things simple in the interests of speed. If at any point you’d like to examine the hierarchy of your result set, you can transfer it to the References interface in a new tab by pressing Ctrl+P or clicking the icon in the upper right of the NavigationProvider. Since the References tool window can host multiple tabs, you can maintain several lists of interest at the same time.
So if you’ve not already got your copy of CodeRush for Roslyn, head on over to the visual studio gallery and grab a copy of our preview now