I develop a Visual Studio extension with a custom Code Map. It is a tree view control which nodes represent specific code elements. When you click on the tree node you navigate to the declaration of the corresponding code element in the code editor.
A simplified version of the navigation looks like this:
public static async Task NavigateAsync(
Microsoft.VisualStudio.Shell.IAsyncServiceProvider serviceProvider,
string filePath,int lineNumber, int character)
{
// first I obtain IWpfTextView for the active document
IWpfTextView wpfTextView = await OpenCodeWindowAsync(serviceProvider, filePath);
// next, generate the position to navigate to
ITextSnapshotLine textLine = wpfTextView.TextSnapshot.GetLineFromLineNumber(lineNumber);
int absoluteOffset = textLine.Start + character;
// expand all collapsed regions in case we navigate inside them
// with a call to the helper method
SnapshotPoint point = wpfTextView.TextSnapshot.GetPoint(absoluteOffset);
SnapshotSpan span = new SnapshotSpan(point, length: 0);
await serviceProvider.ExpandAllRegionsContainingSpanAsync(span, wpfTextView);
// move the caret to a new position and scroll the code editor to it
CaretPosition newCaretPosition = wpfTextView.MoveCaretTo(absoluteOffset);
wpfTextView.ViewScroller.EnsureSpanVisible(span, EnsureSpanVisibleOptions.AlwaysCenter);
}
Everything works fine, except the list of visited location in Visual Studio is not updated. I mean the "Navigate Backward" journal located in the top left corner of Visual Studio:
I have found this description of this functionality on MSDN:
https://learn.microsoft.com/en-us/archive/blogs/zainnab/navigate-backward-and-navigate-forward
It mentions that VS creates so-called "go-back markers" which are basically entries in the navigation journal. In some other places they could be also referred to as "way points". They are created under the following conditions:
A go-back marker is dropped under the following conditions:
An incremental search (including reverse) leaves a go-back marker at the beginning of the search and another one at the end.
A Go To Line action, like CTRL + G, or a mouse-click that moves the cursor 11 lines or more from the current position drops a go-back marker at the new location.
A destructive action (like hitting Backspace) after having moved the cursor to a new location drops a go-back marker.
Doing a search, like Ctrl+F, drops a go-back marker at the found location.
Opening a file drops a go-back marker wherever the cursor was on the old file and drops another on the opened file.
I believe this is what I need. I want to programmatically add such go-back markers but can't find a way to do it. I have looked for them in Google, MSDN, VS Extensibility examples from Mads Kristensen, open source projects on GitHub but so far I haven't managed to find any API that would allow to use them. What I already found:
Implementations very close to what I use in other projects that have custom Code Maps for VS
Implementations using old VS COM interfaces like this:
EnvDTE.TextSelection ts = dte.ActiveDocument.Selection as EnvDTE.TextSelection; ts.MoveToLineAndOffset(...);The navigation works but the navigation journal is still not updated.
The navigation implementations that internally call "Go To Definition" command like this. I can't reuse the "Go To Definition" command because:
- Code Map doesn't have a text under caret that is used by the "Go To Definition" command as a sort of input.
- In general, I need a custom navigation, not just a navigation to the definition. My extension has other functionality that requires custom navigation rules.
Currently, I'm stuck with this issue and I would really appreciate any help.
UPDATE: I've also tried to check VS open source layers which are stored on GitHub: https://github.com/microsoft/vs-editor-api/tree/main Unfortunately, I haven't found anything I can use, or the implementation of the "Navigate Backward" functionality. Maybe I've just missed it.
There are internal IDocumentNavigationService and IGoToDefinitionService in Roslyn, currently I try to see if I can use them either with a reflection or by using a similar logic. If this approach works our I'll add an answer describing it.
Still, I would always prefer a public API over the usage of the internal services, so my question is still relevant. I would mark answer that uses public API and solved my issue as correct over any answer that relies on calls to internal services.
-
You could try find usages of these calls using ILSpy in Visual Studio assemblies.aybe– aybe2023年09月04日 00:40:37 +00:00Commented Sep 4, 2023 at 0:40
-
Hi @aybe. Unfortunately, a big part of VS functionality is written in COM, not .Net. So, .net decompiles don’t help here.SENya– SENya2023年09月04日 09:04:37 +00:00Commented Sep 4, 2023 at 9:04
-
I have already tried to investigate the WPF visual tree of the control and data context behind it but to no avail. These controls seem to be formed very generally by VS automation model (remember that you can customize all VS toolbars and their location, that’s supported by making the controls logic very generic with some kind of automatiion)SENya– SENya2023年09月04日 09:11:57 +00:00Commented Sep 4, 2023 at 9:11
-
I don't see a public API that can help achieve this feature. If you really need a clear public API that can be used, you may need to submit a feature request to enhance the extensibility of the public API. :)Bowman Zhu– Bowman Zhu2023年09月06日 09:49:48 +00:00Commented Sep 6, 2023 at 9:49
-
The problem is I don't know the exact API that will solve my problem. If you mean the IDocumentNavigationService API then I found such request which was just closed: github.com/dotnet/roslyn/issues/7328SENya– SENya2023年09月06日 20:17:13 +00:00Commented Sep 6, 2023 at 20:17
1 Answer 1
Actually, a comment from @JasonMalinowski in my other question also resolved this issue. Since there wasn't any answers for a long time, I will post the link to that comment as an answer: How to navigate to a definition of a Symbol located in the external assembly
And to provide more context - to navigate correctly in Visual Studio you should use a special helper method from VisualStudioWorkspace:
https://github.com/dotnet/roslyn/blob/e1b57268c58d0ccd93992ef3495cd22b8ad07412/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspace.cs#L103
In addition to the navigation this helper will also add entries to the VS "navigation journal" I described in the question.
You can also read about this method from another SO answer by @JasonMalinowski: https://stackoverflow.com/a/69668770/2893207
Comments
Explore related questions
See similar questions with these tags.