Access SymbolInfo from Modified SyntaxNode to Roslyn SyntaxRewriter

I create a SyntaxRewriter that marks classes as partial and methods as virtual if the class inherits from a particular type

For this, I am looking for SymbolInfo from the semantic model inside Rewriter, the problem I am facing is that as soon as I modify syntaxtree to make a partial class, I invalidate the SemanticModel and cannot use it to get SymbolInfo for methods.

An example rewriting device example below .InheritsFrom <T> () is an extension method that simply inherits inheritance to find ways to use a particular type, I just stuck IDisposable as an example, but it’s not very important what type it is. .WithPartialModifier () is again just an extension method to add partial to the class syntax code modifiers.

Maybe I need to switch my approach or update the compilation using the new syntaxtree, but I'm not sure how to do this.

public class RewriterPartial : CSharpSyntaxRewriter
{
    private readonly CSharpCompilation _compiler;

    public RewriterPartial(CSharpCompilation compiler)
    {
        this._compiler = compiler;
    }

    public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        var symbol = _compiler.GetSemanticModel(node.SyntaxTree).GetDeclaredSymbol(node);
        if (symbol.InheritsFrom<System.IDisposable>())
        {
            if (!node.Modifiers.Any(SyntaxKind.PartialKeyword))
            {
                node = node.WithPartialModifier();
            }
        }

        return base.VisitClassDeclaration(node);
    }

    public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        var model = _compiler.GetSemanticModel(node.SyntaxTree);
        // fails above here as the node modified above 
        // and its SyntaxTree have no CompilationUnit
        // and I need to repeat the .InheritsFrom<T> call
        // to check if the method comes from a class in the syntaxtree
        // that inherits from the specific type
        return node;
    }
}
+4
source share
1 answer

You can first view and change the deepest nodes by calling base.VisitClassDeclaration(node);before changing the tree.

Try the following:

public class RewriterPartial : CSharpSyntaxRewriter
{
    private readonly CSharpCompilation _compilation;
    public RewriterPartial(CSharpCompilation compilation, SemanticModel model)
    {
        this._compilation = compilation;
    }

    public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node)
    {
        //Visit the deepest nodes before modifying the tree.
        var newNode = (ClassDeclarationSyntax)base.VisitClassDeclaration(node);
        if (!newNode.Modifiers.Any(SyntaxKind.PartialKeyword))
        {
            newNode = newNode.WithModifiers(
                SyntaxFactory.TokenList(
                    SyntaxFactory.Token(SyntaxKind.PartialKeyword)));
        }
        return newNode;
    }

    public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
    {
        var model = _compilation.GetSemanticModel(node.SyntaxTree);
        var symbol = model.GetDeclaredSymbol(node);
        //Do whatever you need to here
        return node;
    }
}
+3
source

All Articles