2015-08-04 4 views
6

Что является лучшим способом получить SyntaxTree от Rosln из EnvDTE.ProjectItem? Я нашел какой-то метод по-другому (документ Рослина в ProjectItem).вызов Roslyn из команды VSIX

Я получил команду 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)) 

Есть ли лучший способ получить документ Рослин от активного документа?

ответ

1

Если вы можете выяснить, как добраться от ProjectItem до редактора ITextSnapshot, тогда было бы лучше использовать snapshot.AsText().GetOpenDocumentInCurrentContextWithChanges().

Обратите внимание, что в вашем коде выше, используя TryGetSyntaxTree, вы полагаетесь на кого-то, попросившего синтаксическое дерево перед вами.

+1

Метод расширения AsText выглядит очень полезным. К несчастью, я еще не нашел способ получить этот ITextSnapshot. Любая подсказка? – maliger

+0

нашел это [ссылка] (http://stackoverflow.com/questions/2413530/find-an-ivstextview-or-iwpftextview-for-a-given-projectitem-in-vs-2010-rc-exten) – maliger

7

Вы можете использовать workspace.CurrentSolution.GetDocumentIdsWithFilePath(), чтобы получить DocumentId (ы), соответствующие пути к файлу. Из этого вы можете получить сам документ, используя рабочее пространство. 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); 
} 
5

Ответ Фрэнка отлично работает. Я нашел, что это трудно понять, какие typenames есть, так вот код Франк с полностью квалифицированным 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); 
    } 
} 

А вот ссылки, чтобы найти эти типы:

Я надеюсь, что эти две рамочные ссылки могут быть заменены ссылками на NuGet VSSDK.DTE и VSSDK.ComponentModelHost, но когда я попробовал, он дал построить предупреждения о версии сборки несовпадений, поэтому я отказался ,