Reputation: 490
Given a SyntaxNode
instance, how can I open appropriate source code file and place cursor at position where the node resides?
I'm writing some simple analyzer. I'm able start it on demand and get a syntax node from current cursor position. But I can't figure out how do I get back to editor from result syntax node. I see the node has a Span
property but other than that I don't see any info. The Node I want to show can be in some other file that may not be even opened.
I would like to have behavior similar to "go to..." command for the result of my search.
Upvotes: 3
Views: 311
Reputation: 490
I spend whole day on this but finally got it.
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);
}
Upvotes: 3
Reputation: 149
Syntax nodes have a GetLocation()
method, which returns a Microsoft.CodeAnalysis.Location
for that syntax node, so that's one way to get a location object from the SyntaxNode
.
var nodeLocation = syntaxNode.GetLocation();
You can also get location information from a symbol using the Locations
property on the ISymbol
interface, if you happen to need the symbol as well. From the docs:
Gets the locations where the symbol was originally defined, either in source or metadata. Some symbols (for example, partial classes) may be defined in more than one location.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.isymbol?view=roslyn-dotnet
This may be prefereable, as depending on the type of the SyntaxNode
, you may want to get the symbol's original definition rather than the symbol itself e.g. you could get a class declaration from a field's type. This can be done with the OriginalDefinition
property.
// 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];
As for actually jumping to the node, this question would probably be a good place to start: Go to definition from text position with roslyn
However, this is already possible in Visual Studio by double clicking on the message in the error list panel. Furthermore, any code fixes you want to make at that location will show up in the code fix window.
Upvotes: 1