Holen Sie sich Roslyn SyntaxToken aus Visual Studio Text Selection (Position des Einfügemarke)
Ich habe versucht, eine Brücke zwischen dem VSSDK und dem Roslyn SDK in einem Visual Studio-Erweiterungspaket zu schlagen, und es war schwierig, dies zu tun. Das von Visual Studio angegebene ActivePoint.AbsoluteCharOffset stimmt nicht mit dem Element überein, das ich bei Verwendung von FindToken (Offset) von Roslyn erhalte. Ich bin mir ziemlich sicher, dass dies damit zu tun hat, wie jede Seite die EOL-Charaktere auf Grundlage meines aktuellen Arbeitshacks zählt, aber ich bin nicht zu 100% davon überzeugt, dass mein Hack auf lange Sicht Bestand haben wird.
Mein Hack ist diese Zeile:charOffset += point.Line;
Ich füge die Anzahl der Zeilen zum Zeichenoffset hinzu. Dies scheint zu funktionieren. Ich schätze, ich füge alle Zeilenumbruchzeichen hinzu, die bei der Activepoint-Zählung ignoriert werden.
Helfer
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>();
}
Haupttei
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);