从 VSIX 命令调用 Roslyn
calling Roslyn from VSIX command
从 EnvDTE.ProjectItem 获取 Roslyn 语法树的最佳方法是什么?我找到了另一种方法(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 的文档?
如果你能弄清楚如何从 ProjectItem
变成编辑器 ITextSnapshot
,那么使用 snapshot.AsText().GetOpenDocumentInCurrentContextWithChanges()
.
会更好
另请注意,在您上面的代码中,通过使用 TryGetSyntaxTree
,您依赖于其他人在您之前请求了解析树。
您可以使用 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);
}
Frank 的回答很有效。我发现很难弄清楚类型名称是什么,所以这里是 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: Microsoft.VisualStudio.Shell.14.0
- nuget: Microsoft.CodeAnalysis
- nuget: Microsoft.VisualStudio.LanguageService
- 框架:EnvDTE(版本 8.0,并将 Embed Interop Types 设置为 false)
- 框架:Microsoft.VisualStudio.ComponentModelHost
我希望这两个框架引用可以替换为对 VSSDK.DTE and VSSDK.ComponentModelHost 的 NuGet 引用,但是当我尝试时,它给出了有关程序集版本不匹配的构建警告,所以我放弃了。
从 EnvDTE.ProjectItem 获取 Roslyn 语法树的最佳方法是什么?我找到了另一种方法(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 的文档?
如果你能弄清楚如何从 ProjectItem
变成编辑器 ITextSnapshot
,那么使用 snapshot.AsText().GetOpenDocumentInCurrentContextWithChanges()
.
另请注意,在您上面的代码中,通过使用 TryGetSyntaxTree
,您依赖于其他人在您之前请求了解析树。
您可以使用 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);
}
Frank 的回答很有效。我发现很难弄清楚类型名称是什么,所以这里是 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: Microsoft.VisualStudio.Shell.14.0
- nuget: Microsoft.CodeAnalysis
- nuget: Microsoft.VisualStudio.LanguageService
- 框架:EnvDTE(版本 8.0,并将 Embed Interop Types 设置为 false)
- 框架:Microsoft.VisualStudio.ComponentModelHost
我希望这两个框架引用可以替换为对 VSSDK.DTE and VSSDK.ComponentModelHost 的 NuGet 引用,但是当我尝试时,它给出了有关程序集版本不匹配的构建警告,所以我放弃了。