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...
Glad you enjoyed the talk! We actually have some helpers in the syntax model to make it easier to add items to lists, so you should be able to do something like:
var newMethodDeclaration = methodDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
To get the new method declaration.
The expanded form of this would be something like:
var newModifiers = SyntaxFactory.TokenList(modifiers.Concat(new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword)}));
var newMethodDeclaration = methodDeclaration.WithModifiers(newModifiers);
Hope this helps
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.
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