Add access modifier to method using Roslyn CodeFixProvider?

I was at the TechEd a few days ago, and I saw this talk by Kevin Pilch-Bisson (relevent part starts at about 18 minutes) … I thought is was pretty cool, so I decided to play around with Roslyn myself.

I’m trying to make a rule “Access Modifier Must Be Declared” (Stylecop SA1400) – meaning,

This violates the rule:

    static void Main(string[] args)
    {
    }

This is ok:

    public static void Main(string[] args)
    {
    }

It must have an explicit internal keyword, public keyword, private keyword, or protected keyword.

Detecting the violation was fairly easy, but now I’m trying to provide a fix. I’ve been trying things and searching everywhere, but I can’t find out how to add access modifiers.

This is what I have so far:

public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
    var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
    var token = root.FindToken(span.Start);

    var methodDeclaration = token.Parent as MethodDeclarationSyntax;

    //var newModifiers = methodDeclaration.Modifiers.Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.PublicKeyword));         
    //var newModifiers = new SyntaxTokenList() { new SyntaxToken() };

    MethodDeclarationSyntax newMethodDeclaration = methodDeclaration.WithModifiers(methodDeclaration.Modifiers);
    var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration);
    var newDocument = document.WithSyntaxRoot(newRoot);

    return new[] { CodeAction.Create("Add Public Keyword", newDocument) };
}

The WithModifiers needs a SyntaxTokenList, which I can New(), but I don’t know how to make it of SyntaxKind.PublicKeyword. I’m also not sure if I’m even suppose to new it, or use the SyntaxFactory. However, when using the SyntaxFactory, I also can’t figure out which method I need to create a SyntaxToken of SyntaxKind.PublicKeyword

I can post the entire thing, including the DiagnosticAnalyzer if there’s interest…

Answer

What I actually needed was this:

var newModifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(accessModifierToken))
    .AddRange(methodDeclaration.Modifiers);

It’s almost what Chris Eelmaa suggested, but with that suggestion I ended up with static public void Main which is valid, but ugly.

Appending public adds it to the end of the list, and as far as I know, the access modifier should always be the first.

Leave a Reply

Your email address will not be published. Required fields are marked *