如何从SemanticModel中获得新创建类的声明符号

本文关键字:创建 符号 声明 新创建 SemanticModel | 更新日期: 2023-09-27 18:13:15

从我刚刚创建的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中找到它的最简单方法是什么?

在上面的例子中,类是SyntaxTree中唯一的类,并且是CompilationUnit的第一个子类,因此在这个简单的情况下很容易找到。但是,想象一下这样一种情况:语法树包含许多声明,这些声明可能是嵌套的,而所追求的类声明嵌套在其中的深处?有没有办法用旧的ClassDeclarationSyntax找到新的?

如何从SemanticModel中获得新创建类的声明符号

您可以使用SyntaxAnnotation来跟踪您的类节点:

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

无论您最终将类添加到哪种复杂的文档中,这都应该有效。