2

给定一个SyntaxNode实例,我如何打开适当的源代码文件并将光标放在节点所在的位置?

我正在写一些简单的分析器。我可以按需启动它并从当前光标位置获取语法节点。但我不知道如何从结果语法节点返回编辑器。我看到节点有一个Span属性,但除此之外我没有看到任何信息。我要显示的节点可以在其他一些甚至可能无法打开的文件中。

我希望我的搜索结果具有类似于“转到...”命令的行为。

4

2 回答 2

3

我花了一整天的时间,但终于明白了。

private void selectNodeInEditor(SyntaxNode n) {
    var cm = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel));
    var tm = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
    var ws = (Workspace)cm.GetService<VisualStudioWorkspace>();
    var did = ws.CurrentSolution.GetDocumentId(n.SyntaxTree);
    ws.OpenDocument(did);
    tm.GetActiveView(1, null, out var av);
    var sp = n.GetLocation().GetMappedLineSpan().StartLinePosition;
    var ep = n.GetLocation().GetMappedLineSpan().EndLinePosition;
    av.SetSelection(sp.Line, sp.Character, ep.Line, ep.Character);
}
于 2019-08-06T07:25:53.627 回答
1

语法节点有一个GetLocation()方法,它Microsoft.CodeAnalysis.Location为该语法节点返回一个,所以这是从SyntaxNode.

var nodeLocation = syntaxNode.GetLocation();

如果您碰巧也需要符号,还可以使用界面Locations上的属性从符号中获取位置信息。ISymbol从文档:

获取最初在源或元数据中定义符号的位置。某些符号(例如,部分类)可能在多个位置定义。

https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.isymbol?view=roslyn-dotnet

这可能是可取的,因为根据 的类型SyntaxNode,您可能想要获取符号的原始定义而不是符号本身,例如,您可以从字段的类型中获取类声明。这可以通过OriginalDefinition属性来完成。

// assumes there's a SemanticModel in scope and your node is called synatxNode
var syntaxNodeSymbol = semanticModel.GetSymbolInfo(syntaxNode).Symbol;

// make sure syntaxNodeSymbol is null checked

var nodeLocation = syntaxNodeSymbol.Locations[0];
var originalNodeLocation = syntaxNodeSymbol.OriginalDefinition.Locations[0];

至于实际跳转到节点,这个问题可能是一个很好的起点: Go to definition from text position with roslyn

但是,通过双击错误列表面板中的消息,这已经可以在 Visual Studio 中实现。此外,您想在该位置进行的任何代码修复都将显示在代码修复窗口中。

于 2019-08-03T12:25:49.897 回答