假设我有一个简单的项目
class Program : TestBase
{
static void Main(string[] args)
{
}
public void Test()
{
AddItem(new Item());
AddItem(new Item());
}
}
public class Item { }
public class TestBase
{
public virtual void AddItem(Item vertex) { }
}
如何使用VSSDK提取AddItem(new Item());
?我想知道将哪些参数传递给它,以及它在文本编辑器中的哪一行。
我尝试寻找CodeElement.Kind
,但不幸的是vsCMElement.vsCMElementFunctionInvokeStmt
没有返回任何内容。还有其他提取信息的方法吗?
public static async Task InitializeAsync(AsyncPackage package)
{
// ...
_dte = (await package.GetServiceAsync(typeof(DTE))) as DTE2;
await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);
var sandboxProject = _dte.Solution.Projects;
var codeItems = new List<string>();
if (!ThreadHelper.CheckAccess())
return;
foreach (Project project in sandboxProject)
{
var projectItems = GetProjectItemsRecursively(project.ProjectItems);
foreach (ProjectItem projectItem in projectItems)
{
foreach (CodeElement element in projectItem.FileCodeModel.CodeElements)
{
codeItems.AddRange(GetItems(element).Select(codeItem => $"{codeItem.FullName} : {codeItem.Kind.ToString()}"));
}
}
}
}
private static IEnumerable<CodeElement> GetItems(CodeElement items)
{
var ret = new List<CodeElement>();
if (items == null)
return ret;
foreach (CodeElement item in items.Children)
{
ret.Add(item);
ret.AddRange(GetItems(item));
}
return ret;
}
private static List<ProjectItem> GetProjectItemsRecursively(ProjectItems items)
{
var ret = new List<EnvDTE.ProjectItem>();
if (items == null) return ret;
foreach (ProjectItem item in items)
{
ret.Add(item);
ret.AddRange(GetProjectItemsRecursively(item.ProjectItems));
}
return ret;
}
答案 0 :(得分:1)
使用Visual Studio的现代版本,如果您对语言服务感兴趣,则不必使用DTE和旧的FileCodeModel东西,但是可以利用The .NET Compiler Platform SDK(又名Roslyn)现在解析主干。
因此,首先要做的是将最新的Microsoft.CodeAnalysis.CSharp.Workspaces nuget包(对于C#为roslyn)和Microsoft.VisualStudio.LanguageServices nuget(Visual Studio Roslyn工作区)添加到您的包项目中。请注意,您可能必须修复现在常见的nuget混乱...
完成此操作后,您可以编写这种代码而不是您自己的代码:
// get component model & Visual Studio Roslyn workspace
var componentModel = await package.GetServiceAsync<SComponentModel, IComponentModel>();
var workspace = componentModel.GetService<VisualStudioWorkspace>(); // requires "Microsoft.VisualStudio.LanguageServices" nuget package
// enum all the projects
foreach (var project in workspace.CurrentSolution.Projects)
{
// enum all the documents in the project
foreach (var doc in project.Documents)
{
// get the semantic model & syntax tree root
var model = await doc.GetSemanticModelAsync();
var root = await model.SyntaxTree.GetRootAsync();
// find a class named "TestBase"
// ClassDeclarationSyntax etc. requires "Microsoft.CodeAnalysis.CSharp.Workspaces" nuget package
var myClass = root.DescendantNodes()
.OfType<ClassDeclarationSyntax>()
.FirstOrDefault(c => c.Identifier.Text == "TestBase");
if (myClass != null)
{
// find a method named "AddItem"
var myMethod = myClass.Members.Where(m => m.Kind() == SyntaxKind.MethodDeclaration)
.OfType<MethodDeclarationSyntax>()
.FirstOrDefault(m => m.Identifier.Text == "AddItem");
if (myMethod != null)
{
// get the list of method parameters
var parameters = myMethod.ParameterList.Parameters;
...
// get the start line for the method declaration
var lineSpan = model.SyntaxTree.GetLineSpan(myMethod.Span);
int startLine = lineSpan.StartLinePosition.Line;
...
}
}
}
}