What is the easiest way to get an ISymbol
from a ClassDeclaration
that I just created?
Consider the following code:
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
The last line throws an exception saying "Syntax node is not within syntax tree".
I assume I need to get the ClassDeclarationSyntax
that I just created again from the new SyntaxTree
. But what is the easiest way to find it in the new SyntaxTree
given that I only have the old ClassDeclarationSyntax
?
In the example above the class is the only class in the SyntaxTree
and is the first child of the CompilationUnit
, so it would be easy to find in this simple case. But imagine a situation where the syntax tree contains a lot of declarations, that may be nested, and the sought after class declaration is nested deep within? Is there some way to use the old ClassDeclarationSyntax
to find the new one? (Or am I going about things all wrong here?)
You can use a SyntaxAnnotation
to keep track of your class nodes:
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);
This should work no matter what kind of complex documents you end up adding your class to.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With