从 Visual Studio 文本选择(插入符号位置)获取 Roslyn SyntaxToken [英] Get Roslyn SyntaxToken from Visual Studio Text Selection (caret position)

查看:35
本文介绍了从 Visual Studio 文本选择(插入符号位置)获取 Roslyn SyntaxToken的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 Visual Studio 扩展包中的 VSSDK 和 Roslyn SDK 之间架起桥梁,但对此一直很困难.使用 FindToken(offset) 时,Visual Studio 给出的 ActivePoint.AbsoluteCharOffset 与我从 Roslyn 获得的元素不匹配.我相当确定这与每一方如何根据我当前的工作 hack 计算 EOL 字符有关,但我并不是 100% 认为我的 hack 从长远来看会坚持下去.

I am attempting to bridge between the VSSDK and Roslyn SDK in a Visual Studio extension package and have been having a hard time with this. The ActivePoint.AbsoluteCharOffset given from Visual Studio does not match the element I get from Roslyn when using FindToken(offset). I'm fairly sure this has to do with how each side counts EOL characters based on my current working hack but I'm not 100% that my hack is going to hold up in the long run.

我的黑客是这一行:charOffset += point.Line;

我将行数添加到字符偏移量上,这似乎有效,所以我猜我添加了所有被活动点计数忽略的换行符.

I add the number of lines onto the char offset, this seems to work so I'm guessing I am adding in all the line break characters that are being ignored by activepoint counting.

帮手

private VisualStudioWorkspace workspace = null;
public RoslynUtilities(VisualStudioWorkspace workspace)
{
    this.workspace = workspace;
}
public Solution Solution { get { return workspace.CurrentSolution; } }
public Document GetDocumentFromPath(string fullPath)
{
    foreach (Project proj in this.Solution.Projects)
    {               
        foreach (Document doc in proj.Documents)
        {
            if (doc.FilePath == fullPath)
                return doc;                   
        }
    }
    return null;
}
public SyntaxTree GetSyntaxTreeFromDocumentPath(string fullPath)
{
    Document doc = GetDocumentFromPath(fullPath);
    if (doc != null)
        return doc.GetSyntaxTreeAsync().Result;
    else
        return null;
}
public SyntaxNode GetNodeByFilePosition(string fullPath, int absoluteChar)
{
    SyntaxTree tree = GetSyntaxTreeFromDocumentPath(fullPath);
    if(tree != null)
    {
        var compUnit = tree.GetCompilationUnitRoot();
        if(compUnit != null)
        {
            return compUnit.FindToken(absoluteChar, true).Parent;
        }
    }
    return null;                        
}
private VisualStudioWorkspace GetRoslynWorkspace()
    {
        var componentModel = (IComponentModel)GetGlobalService(typeof(SComponentModel));
        return componentModel.GetService<VisualStudioWorkspace>();
    }

主要部分

EnvDTE80.DTE2 applicationObject = (EnvDTE80.DTE2)GetService(typeof(SDTE));
EnvDTE.TextSelection ts = applicationObject.ActiveWindow.Selection as EnvDTE.TextSelection;
if (ts == null)
    return;

EnvDTE.VirtualPoint point = ts.ActivePoint;
int charOffset = point.AbsoluteCharOffset;
charOffset += point.Line;//HACK ALERT

Parse.Roslyn.RoslynUtilities roslyn = new Parse.Roslyn.RoslynUtilities(GetRoslynWorkspace());
SyntaxNode node = roslyn.GetNodeByFilePosition(applicationObject.ActiveDocument.FullName, charOffset);

推荐答案

我强烈推荐使用 Microsoft.VisualStudio.Text.Editor 中的 Microsoft.VisualStudio.Text.SnapshotPoint.IWpfTextView 缓冲区代替 EnvDTE 接口与 Roslyn 交互.

I'd highly recommend using Microsoft.VisualStudio.Text.SnapshotPoint from a Microsoft.VisualStudio.Text.Editor.IWpfTextView buffer instead of EnvDTE interfaces to interact with Roslyn.

主要代码可能如下所示:

Main code may look like this:

Microsoft.VisualStudio.Text.Editor.IWpfTextView textView =
    GetTextView();

Microsoft.VisualStudio.Text.SnapshotPoint caretPosition =
    textView.Caret.Position.BufferPosition;

Microsoft.CodeAnalysis.Document document =
    caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges();

Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax invocationExpressionNode = 
    document.GetSyntaxRootAsync().Result.
        FindToken(caretPosition).Parent.AncestorsAndSelf().
        OfType<Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax>().
        FirstOrDefault();

请参阅从当前方法调用创建类型化变量 以获取完整示例.

See Create a typed variable from the current method invocation for a complete example.

这篇关于从 Visual Studio 文本选择(插入符号位置)获取 Roslyn SyntaxToken的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆