Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a parameter to a method with a Roslyn CodeFixProvider

I'm writing a Roslyn Code Analyzer that I want to identify if an async method does not take a CancellationToken and then suggest a code fix that adds it:

 //Before Code Fix:
 public async Task Example(){}

 //After Code Fix
 public async Task Example(CancellationToken token){}

I've wired up the DiagnosticAnalyzer to correctly report a Diagnostic by inspecting the methodDeclaration.ParameterList.Parameters, but I can't find the Roslyn API for adding a Paramater to the ParameterList inside a CodeFixProvider.

This is what I've got so far:

private async Task<Document> HaveMethodTakeACancellationTokenParameter(
        Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken)
{
    var method = syntaxNode as MethodDeclarationSyntax;

    // what goes here?
    // what I want to do is: 
    // method.ParameterList.Parameters.Add(
          new ParameterSyntax(typeof(CancellationToken));

    //somehow return the Document from method         
}

How do I correctly update the Method Declaration and return the updated Document?

like image 260
Philip Pittle Avatar asked Apr 29 '16 22:04

Philip Pittle


1 Answers

@Nate Barbettini is correct, syntax nodes are all immutable, so I needed to create a new version of the MethodDeclarationSyntax, then replace the old method with the new method in the document's SyntaxTree:

private async Task<Document> HaveMethodTakeACancellationTokenParameter(
        Document document, SyntaxNode syntaxNode, CancellationToken cancellationToken)
    {
        var method = syntaxNode as MethodDeclarationSyntax;

        var updatedMethod = method.AddParameterListParameters(
            SyntaxFactory.Parameter(
                SyntaxFactory.Identifier("cancellationToken"))
                .WithType(SyntaxFactory.ParseTypeName(typeof (CancellationToken).FullName)));

        var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);

        var updatedSyntaxTree = 
            syntaxTree.GetRoot().ReplaceNode(method, updatedMethod);

        return document.WithSyntaxRoot(updatedSyntaxTree);
    }
like image 141
Philip Pittle Avatar answered Oct 15 '22 10:10

Philip Pittle