Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn CodeFixProvider add attribute to the method

Tags:

c#

roslyn

I'm building CodeFixProvider for the analyzer that is detecting if custom attribute is missing from the method declaration. Basically custom attribute that should be added to the method looks like

    [CustomAttribute(param1: false, param2: new int[]{1,2,3})]

this is what I've got so far:

    public sealed override async Task RegisterCodeFixesAsync( CodeFixContext context ) {
        var root = await context.Document.GetSyntaxRootAsync( context.CancellationToken ).ConfigureAwait( false );

        var diagnostic = context.Diagnostics.First();
        var diagnosticSpan = diagnostic.Location.SourceSpan;
        var declaration = root.FindToken( diagnosticSpan.Start ).Parent.AncestorsAndSelf( ).OfType<MethodDeclarationSyntax>( ).First( );

        context.RegisterCodeFix(
            CodeAction.Create(
                title: title,
                createChangedSolution: c => this.AddCustomAttribute(context.Document, declaration, c),
                equivalenceKey: title),
            diagnostic);
    }

    private async Task<Solution> AddCustomAttribute( Document document, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken ) {
        // I suspect I need to do something like methodDeclaration.AddAttributeLists(new AttributeListSyntax[] {
        // but not sure how to use it exactly

        throw new NotImplementedException( );
    }
like image 659
AlexanderM Avatar asked Jun 02 '16 14:06

AlexanderM


1 Answers

Remember, roslyn syntax trees are immutable. You'll need something like:

private async Task<Solution> AddCustomAttribute(Document document, MethodDeclarationSyntax methodDeclaration, CancellationToken cancellationToken)
{
    var root = await document.GetSyntaxRootAsync(cancellationToken);
    var attributes = methodDeclaration.AttributeLists.Add(
        SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList<AttributeSyntax>(
            SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("CustomAttribute"))
            //  .WithArgumentList(...)
        )).NormalizeWhitespace());

    return document.WithSyntaxRoot(
        root.ReplaceNode(
            methodDeclaration,
            methodDeclaration.WithAttributeLists(attributes)
        )).Project.Solution;
}

To get the full SyntaxFactory code for the attribute constructor .WithArgumentList() throw it into the Roslyn Quoter.

like image 87
m0sa Avatar answered Nov 14 '22 00:11

m0sa