You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Visual Studio扩展场景下使用Roslyn跳转至SourceText的实现方法咨询

Visual Studio扩展中通过Roslyn Location跳转至源码位置的实现方案

存在已封装的跳转实现,不需要手动完成全流程操作,常见有两种实现路径:

路径一:直接使用EditorFeatures内置扩展方法(最简便)

在已经引用Microsoft.CodeAnalysis.EditorFeatures包的前提下,框架已经提供了封装好的跳转扩展,仅需少量代码即可完成操作:

using Microsoft.CodeAnalysis;
using Microsoft.VisualStudio.LanguageServices;

// 已通过MEF导入的VisualStudioWorkspace实例
private readonly VisualStudioWorkspace _workspace;

public void JumpToSyntaxNodeLocation(SyntaxNode node)
{
    var location = node.GetLocation();
    // 直接调用扩展方法完成跳转,已封装打开文档、定位、选中逻辑
    location.NavigateTo(_workspace);
}

路径二:基于VS原生服务自定义实现(无需依赖EditorFeatures包)

如果不想引入额外的EditorFeatures依赖,也可以通过Visual Studio原生的SDK服务实现跳转,步骤如下:

  • 先获取SVsUIShellOpenDocument服务,调用OpenDocumentViaProject方法打开位置对应的源码文件
  • 获取文件对应的IVsTextView实例,设置光标位置与选中范围即可自动滚动到对应位置
    示例代码:
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.CodeAnalysis;
using System.Runtime.InteropServices;

public void NavigateToLocation(Location location)
{
    ThreadHelper.ThrowIfNotOnUIThread();
    if (!location.IsInSource) return;

    string filePath = location.SourceTree.FilePath;
    var span = location.GetLineSpan();
    int startLine = span.StartLinePosition.Line;
    int startColumn = span.StartLinePosition.Character;
    int endLine = span.EndLinePosition.Line;
    int endColumn = span.EndLinePosition.Character;

    IVsUIShellOpenDocument openDoc = GetService<SVsUIShellOpenDocument, IVsUIShellOpenDocument>();
    IVsWindowFrame frame;
    Guid logicalView = VSConstants.LOGVIEWID_Code;

    if (ErrorHandler.Succeeded(openDoc.OpenDocumentViaProject(
        filePath, ref logicalView, out _, out _, out _, out frame)) 
        && frame != null)
    {
        frame.Show();
        if (frame.GetProperty((int)__VSFPROPID.VSFPROPID_DocData, out object docData) == VSConstants.S_OK)
        {
            if (Marshal.QueryInterface(Marshal.GetIUnknownForObject(docData), ref typeof(IVsTextView).GUID, out IntPtr textViewPtr) >= 0)
            {
                IVsTextView textView = Marshal.GetObjectForIUnknown(textViewPtr) as IVsTextView;
                textView?.SetSelection(startLine, startColumn, endLine, endColumn);
                textView?.CenterLines(startLine, 1);
                Marshal.Release(textViewPtr);
            }
        }
    }
}

注意事项

  • 所有跳转相关操作必须在Visual Studio UI线程执行,可通过ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync()切换线程上下文
  • 跳转前需判断Location.IsInSource为true,避免尝试跳转元数据、编译生成代码等非用户源码的位置
  • 如果需要选中对应SyntaxNode的全部文本,直接传入Location.SourceSpan作为选中范围即可

内容的提问来源于stack exchange,提问作者TWT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 07:54:04