如何从 SemanticModel 获取新创建的 class 的声明符号?
How to get declared symbol from SemanticModel for newly created class?
从我刚刚创建的 ClassDeclaration
中获取 ISymbol
的最简单方法是什么?
考虑以下代码:
AdhocWorkspace workspace = new AdhocWorkspace();
Project project = workspace.AddProject("Test", LanguageNames.CSharp);
ClassDeclarationSyntax classDeclaration = SyntaxFactory.ClassDeclaration("MyClass");
CompilationUnitSyntax compilationUnit = SyntaxFactory.CompilationUnit().AddMembers(classDeclaration);
Document document = project.AddDocument("Test.cs", compilationUnit);
SemanticModel semanticModel = await document.GetSemanticModelAsync();
ISymbol symbol = semanticModel.GetDeclaredSymbol(classDeclaration); // <-- Throws Exception
最后一行抛出异常“语法节点不在语法树中”。
我假设我需要从新的 SyntaxTree
中获取我刚刚创建的 ClassDeclarationSyntax
。但是鉴于我只有旧的 ClassDeclarationSyntax
,在新的 SyntaxTree
中找到它的最简单方法是什么?
在上面的示例中,class 是 SyntaxTree
中唯一的 class,也是 CompilationUnit
中的第一个 child,因此它会在这个简单的案例中很容易找到。但是想象一下语法树包含很多声明的情况,这些声明可能是嵌套的,而寻求的 class 声明嵌套得很深?有什么方法可以使用旧的 ClassDeclarationSyntax
找到新的吗? (或者我在这里做错了什么?)
您可以使用 SyntaxAnnotation
来跟踪您的 class 节点:
AdhocWorkspace workspace = new AdhocWorkspace();
Project project = workspace.AddProject("Test", LanguageNames.CSharp);
//Attach a syntax annotation to the class declaration
var syntaxAnnotation = new SyntaxAnnotation("ClassTracker");
var classDeclaration = SyntaxFactory.ClassDeclaration("MyClass")
.WithAdditionalAnnotations(syntaxAnnotation);
var compilationUnit = SyntaxFactory.CompilationUnit().AddMembers(classDeclaration);
Document document = project.AddDocument("Test.cs", compilationUnit);
SemanticModel semanticModel = document.GetSemanticModelAsync().Result;
//Use the annotation on our original node to find the new class declaration
var changedClass = document.GetSyntaxRootAsync().Result.DescendantNodes().OfType<ClassDeclarationSyntax>()
.Where(n => n.HasAnnotation(syntaxAnnotation)).Single();
var symbol = semanticModel.GetDeclaredSymbol(changedClass);
无论您最终将 class 添加到哪种复杂文档,这都应该有效。
从我刚刚创建的 ClassDeclaration
中获取 ISymbol
的最简单方法是什么?
考虑以下代码:
AdhocWorkspace workspace = new AdhocWorkspace();
Project project = workspace.AddProject("Test", LanguageNames.CSharp);
ClassDeclarationSyntax classDeclaration = SyntaxFactory.ClassDeclaration("MyClass");
CompilationUnitSyntax compilationUnit = SyntaxFactory.CompilationUnit().AddMembers(classDeclaration);
Document document = project.AddDocument("Test.cs", compilationUnit);
SemanticModel semanticModel = await document.GetSemanticModelAsync();
ISymbol symbol = semanticModel.GetDeclaredSymbol(classDeclaration); // <-- Throws Exception
最后一行抛出异常“语法节点不在语法树中”。
我假设我需要从新的 SyntaxTree
中获取我刚刚创建的 ClassDeclarationSyntax
。但是鉴于我只有旧的 ClassDeclarationSyntax
,在新的 SyntaxTree
中找到它的最简单方法是什么?
在上面的示例中,class 是 SyntaxTree
中唯一的 class,也是 CompilationUnit
中的第一个 child,因此它会在这个简单的案例中很容易找到。但是想象一下语法树包含很多声明的情况,这些声明可能是嵌套的,而寻求的 class 声明嵌套得很深?有什么方法可以使用旧的 ClassDeclarationSyntax
找到新的吗? (或者我在这里做错了什么?)
您可以使用 SyntaxAnnotation
来跟踪您的 class 节点:
AdhocWorkspace workspace = new AdhocWorkspace();
Project project = workspace.AddProject("Test", LanguageNames.CSharp);
//Attach a syntax annotation to the class declaration
var syntaxAnnotation = new SyntaxAnnotation("ClassTracker");
var classDeclaration = SyntaxFactory.ClassDeclaration("MyClass")
.WithAdditionalAnnotations(syntaxAnnotation);
var compilationUnit = SyntaxFactory.CompilationUnit().AddMembers(classDeclaration);
Document document = project.AddDocument("Test.cs", compilationUnit);
SemanticModel semanticModel = document.GetSemanticModelAsync().Result;
//Use the annotation on our original node to find the new class declaration
var changedClass = document.GetSyntaxRootAsync().Result.DescendantNodes().OfType<ClassDeclarationSyntax>()
.Where(n => n.HasAnnotation(syntaxAnnotation)).Single();
var symbol = semanticModel.GetDeclaredSymbol(changedClass);
无论您最终将 class 添加到哪种复杂文档,这都应该有效。