【问题标题】:calling Roslyn from VSIX command从 VSIX 命令调用 Roslyn
【发布时间】:2019-04-05 13:00:22
【问题描述】:

从 EnvDTE.ProjectItem 获取 Roslyn 的 SyntaxTree 的最佳方法是什么?我找到了另一种方法(Roslyn's Document into ProjectItem)。

我从打开的文档中调用了 VSIX 命令,我想在那里试验 Roslyn 的语法树。

这段代码有效,但对我来说看起来很尴尬:

    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))

有没有更好的方法从活动文档中获取 Roslyn 的文档?

【问题讨论】:

    标签: visual-studio-2015 roslyn vsix vsx visual-studio-package


    【解决方案1】:

    您可以使用 workspace.CurrentSolution.GetDocumentIdsWithFilePath() 来获取与文件路径匹配的 DocumentId。从中您可以使用 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);
    }
    

    【讨论】:

    • .FirstOrDefault(); 不会在活动上下文中为您提供文档(在多目标项目或共享项目的情况下)。
    【解决方案2】:

    弗兰克的回答效果很好。我发现很难弄清楚类型名是什么,所以这是 Frank 的代码,其中包含完全限定的类型名:

    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);
        }
    }
    

    以下是查找这些类型的参考:

    我希望这两个框架引用可以替换为 NuGet 引用 VSSDK.DTEVSSDK.ComponentModelHost,但是当我尝试时,它给出了关于程序集版本不匹配的构建警告,所以我放弃了。

    【讨论】:

    • .FirstOrDefault(); 不会在活动上下文中为您提供文档(在多目标项目或共享项目的情况下)。
    【解决方案3】:

    如果你能弄清楚如何从ProjectItem 到编辑器ITextSnapshot,那么最好使用snapshot.AsText().GetOpenDocumentInCurrentContextWithChanges()

    另请注意,在您上面的代码中,通过使用 TryGetSyntaxTree,您依赖于在您之前请求解析树的其他人。

    【讨论】:

    • AsText 扩展方法看起来很有用。不幸的是,我还没有找到获得 ITextSnapshot 的方法。有什么线索吗?
    • 找到这个link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多