简体   繁体   English

从Visual Studio文本选择中获取Roslyn SyntaxToken(插入位置)

[英]Get Roslyn SyntaxToken from Visual Studio Text Selection (caret position)

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. 我试图在Visual Studio扩展包中的VSSDK和Roslyn SDK之间架起桥梁,并且一直很难用。 The ActivePoint.AbsoluteCharOffset given from Visual Studio does not match the element I get from Roslyn when using FindToken(offset). Visual Studio提供的ActivePoint.AbsoluteCharOffset与使用FindToken(offset)时从Roslyn获取的元素不匹配。 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. 我很确定这与我的当前工作黑客的每一方如何计算EOL字符有关,但我不是100%,我的黑客将长期坚持。

My hack is this line: charOffset += point.Line; 我的黑客是这一行: 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. 我在char偏移量上添加行数,这似乎有效,所以我猜我正在添加所有被activepoint计数忽略的换行符。

Helpers 助手

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

Main Part 主要部分

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

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. 我强烈建议使用Microsoft.VisualStudio.Text.SnapshotPoint缓冲区中的Microsoft.VisualStudio.Text.Editor.IWpfTextView而不是EnvDTE接口与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. 有关完整示例,请参阅从当前方法调用创建类型变量

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在当前版本的Roslyn中获取SyntaxToken.Kind? - How to get the SyntaxToken.Kind in current version of Roslyn? Roslyn - 更改SyntaxToken或SyntaxNode的TextSpan - Roslyn - Change TextSpan of SyntaxToken or SyntaxNode 用roslyn从文本位置转到定义 - Go to definition from text position with roslyn 如何从 Visual Studio 编辑器中检索文本以与 Roslyn SyntaxTree 一起使用? - How do I retrieve text from the Visual Studio editor for use with Roslyn SyntaxTree? Visual Studio 2010 SDK,获取插入符号列 - Visual Studio 2010 SDK, Get Caret Column 如何在Visual Studio扩展中进行选择之前获取文本 - How to get the text before a selection in visual studio extension 在为 Visual Studio 定义模板时,有没有办法指定 cursor(插入符号)position? - Is there a way to specify cursor (caret) position when defining template for Visual Studio? 如何在Visual Studio中确定当前插入符号位置在注释块中? - How to determine in Visual Studio that the current caret position is in a comment block? 从Visual Studio扩展中的ProjectItem获取Roslyn SemanticModel - Getting Roslyn SemanticModel from ProjectItem in Visual Studio extension 在Visual Studio中使用自编译的Roslyn? - Using self-compiled Roslyn from within Visual Studio?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM