如何以编程方式将自定义导航集成到 Visual Studio“向后导航”列表中

问题描述 投票:0回答:1

我使用自定义代码图开发 Visual Studio 扩展。它是一个树视图控件,其节点代表特定的代码元素。单击树节点时,您将导航到代码编辑器中相应代码元素的声明。

简化版的导航如下所示:

    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); 
    }

一切正常,除了 Visual Studio 中访问位置的列表未更新。 我的意思是位于 Visual Studio 左上角的“向后导航”日志:

Navigate Backward screenshot

我在 MSDN 上找到了此功能的描述:

https://learn.microsoft.com/en-us/archive/blogs/zainnab/navigate-backward-and-navigate-forward

它提到 VS 创建了所谓的“返回标记”,这些标记基本上是导航日志中的条目。在其他一些地方,它们也可以被称为“航路点”。它们是在以下条件下创建的:

在以下情况下会删除返回标记:

  • 增量搜索(包括反向)会在以下位置留下返回标记: 搜索的开始和结束时的另一个搜索。

  • “转到行”操作(例如 CTRL + G)或单击鼠标将光标从当前位置移动 11 行或更多,则会返回 在新位置进行标记。

  • 将光标移动到新位置后的破坏性操作(例如按 Backspace)会掉落返回标记。

  • 执行搜索(如 Ctrl+F)会在找到的位置放置一个返回标记。

  • 打开文件会在光标位于旧文件上的任何位置放置一个返回标记,并在打开的文件上放置另一个标记。

我相信这就是我所需要的。我想以编程方式添加此类回退标记,但找不到方法。我已经在 Google、MSDN、Mads Kristensen 的 VS 可扩展性示例、GitHub 上的开源项目中查找过它们,但到目前为止,我还没有找到任何允许使用它们的 API。我已经发现了什么:

  • 实现非常接近我在其他具有 VS 自定义代码映射的项目中使用的实现

  • 使用旧的 VS COM 接口实现,如 this:

    EnvDTE.TextSelection ts = dte.ActiveDocument.Selection as EnvDTE.TextSelection;
    ts.MoveToLineAndOffset(…); 
    

    导航可以工作,但导航日志仍未更新。

  • 内部调用“转到定义”命令的导航实现,如this。我无法重复使用 “转到定义” 命令,因为:

    • 代码映射在插入符号下没有文本,“转到定义”命令使用该文本作为输入。
    • 一般来说,我需要自定义导航,而不仅仅是定义的导航。我的扩展程序还有其他需要自定义导航规则的功能。

目前,我遇到了这个问题,我非常感谢任何帮助。

更新:我还尝试检查存储在 GitHub 上的 VS 开源层: https://github.com/microsoft/vs-editor-api/tree/main 不幸的是,我还没有找到任何可以使用的东西,也没有找到“向后导航”功能的实现。也许我只是错过了。

Roslyn 中有内部的 IDocumentNavigationServiceIGoToDefinitionService,目前我尝试看看是否可以通过反射或使用类似的逻辑来使用它们。 如果这种方法有效,我将添加一个描述它的答案。

不过,与使用内部服务相比,我始终更喜欢公共 API,所以我的问题仍然相关。我会将使用公共 API 并解决我的问题的答案标记为正确,而不是依赖于调用内部服务的任何答案。

c# visual-studio visual-studio-2022 visual-studio-extensions code-navigation
1个回答
0
投票

实际上,@JasonMalinowski 在我的另一个问题中的评论也解决了这个问题。由于很长时间没有任何答案,我将发布该评论的链接作为答案: 如何导航到位于外部程序集中的符号定义

为了提供更多上下文 - 要在 Visual Studio 中正确导航,您应该使用

VisualStudioWorkspace
中的特殊帮助器方法: https://github.com/dotnet/roslyn/blob/e1b57268c58d0ccd93992ef3495cd22b8ad07412/src/VisualStudio/Core/Def/Implementation/ProjectSystem/VisualStudioWorkspace.cs#L103

您还可以从 @JasonMalinowski 的另一个 SO 答案中了解此方法: https://stackoverflow.com/a/69668770/2893207

© www.soinside.com 2019 - 2024. All rights reserved.