calling Roslyn from VSIX command

老子叫甜甜 提交于 2019-12-07 02:32:08

问题


What is best way to obtain Roslyn's SyntaxTree from EnvDTE.ProjectItem? I found some method for the other way (Roslyn's Document into ProjectItem).

I got VSIX command called from opened document and I'd like to experiment with Roslyn's syntax tree there.

This code works, but looks awkward to me:

    var pi = GetProjectItem();
    var piName = pi.get_FileNames(1);

    var componentModel = (IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel));
    var workspace = componentModel.GetService<Microsoft.VisualStudio.LanguageServices.VisualStudioWorkspace>();
    var ids = workspace.GetOpenDocumentIds();
    var id1 = ids.First(id => workspace.GetFilePath(id) == piName);

        Microsoft.CodeAnalysis.Solution sln = workspace.CurrentSolution;
        var doc = sln.GetDocument(id1);
        //var w = await doc.GetSyntaxTreeAsync();
        Microsoft.CodeAnalysis.SyntaxTree syntaxTree;
        if (doc.TryGetSyntaxTree(out syntaxTree))

Is there better way to get Roslyn's Document from active document?


回答1:


You can use workspace.CurrentSolution.GetDocumentIdsWithFilePath() to get the DocumentId(s) matching a file path. From that you can get the document itself using workspace.CurrentSolution.GetDocument()

private Document GetActiveDocument()
{
    var dte = Package.GetGlobalService(typeof(DTE)) as DTE;
    var activeDocument = dte?.ActiveDocument;
    if (activeDocument == null) return null;

    var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel));
    var workspace = (Workspace) componentModel.GetService<VisualStudioWorkspace>();

    var documentid = workspace.CurrentSolution.GetDocumentIdsWithFilePath(activeDocument.FullName).FirstOrDefault();
    if (documentid == null) return null;

    return workspace.CurrentSolution.GetDocument(documentid);
}



回答2:


Frank's answer works great. I found it hard to figure out what the type-names are, so here's Frank's code with fully qualified typenames:

using System.Linq;

var dte = Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
var activeDocument = dte?.ActiveDocument;
if (activeDocument != null)
{
    var componentModel = (Microsoft.VisualStudio.ComponentModelHost.IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(Microsoft.VisualStudio.ComponentModelHost.SComponentModel));
    var workspace = (Microsoft.CodeAnalysis.Workspace)componentModel.GetService<Microsoft.VisualStudio.LanguageServices.VisualStudioWorkspace>();
    var documentId = workspace.CurrentSolution.GetDocumentIdsWithFilePath(activeDocument.FullName).FirstOrDefault();
    if (documentId != null)
    {
        var document = workspace.CurrentSolution.GetDocument(documentId);
    }
}

And here are the references to find those types:

  • nuget: Microsoft.VisualStudio.Shell.14.0
  • nuget: Microsoft.CodeAnalysis
  • nuget: Microsoft.VisualStudio.LanguageService
  • framework: EnvDTE (version 8.0, and set Embed Interop Types to false)
  • framework: Microsoft.VisualStudio.ComponentModelHost

I hope the two framework references can be replaced with NuGet references to VSSDK.DTE and VSSDK.ComponentModelHost, but when I tried, it gave build warnings about assembly version mismatches so I gave up.




回答3:


If you can figure out how to get from a ProjectItem to an editor ITextSnapshot, then it would be better to use snapshot.AsText().GetOpenDocumentInCurrentContextWithChanges().

Note also that in your code above, by using TryGetSyntaxTree you are relying on someone else having requested the parse tree before you.



来源:https://stackoverflow.com/questions/31808766/calling-roslyn-from-vsix-command

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!