从 Visual Studio 文本选择(插入符号位置)获取 Roslyn SyntaxToken
Get Roslyn SyntaxToken from Visual Studio Text Selection (caret position)
我正在尝试在 Visual Studio 扩展包中桥接 VSSDK 和 Roslyn SDK,但遇到了困难。
Visual Studio 给出的 ActivePoint.AbsoluteCharOffset 与我在使用 FindToken(offset) 时从 Roslyn 获得的元素不匹配。我相当确定这与每一方如何根据我当前的工作技巧计算 EOL 字符有关,但我不是 100% 我的技巧会在很长一段时间内保持 运行.
我的技巧是这一行:charOffset += point.Line;
我将行数添加到 char 偏移量上,这似乎有效,所以我猜我添加了所有被 activepoint 计数忽略的换行符。
助手
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.IWpfTextView
缓冲区中的 Microsoft.VisualStudio.Text.SnapshotPoint
而不是 EnvDTE
接口来与 Roslyn 交互。
主要代码可能如下所示:
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();
有关完整示例,请参阅 Create a typed variable from the current method invocation。
我正在尝试在 Visual Studio 扩展包中桥接 VSSDK 和 Roslyn SDK,但遇到了困难。 Visual Studio 给出的 ActivePoint.AbsoluteCharOffset 与我在使用 FindToken(offset) 时从 Roslyn 获得的元素不匹配。我相当确定这与每一方如何根据我当前的工作技巧计算 EOL 字符有关,但我不是 100% 我的技巧会在很长一段时间内保持 运行.
我的技巧是这一行:charOffset += point.Line;
我将行数添加到 char 偏移量上,这似乎有效,所以我猜我添加了所有被 activepoint 计数忽略的换行符。
助手
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.IWpfTextView
缓冲区中的 Microsoft.VisualStudio.Text.SnapshotPoint
而不是 EnvDTE
接口来与 Roslyn 交互。
主要代码可能如下所示:
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();
有关完整示例,请参阅 Create a typed variable from the current method invocation。