I'm building an analyzer for C# code which generates errors when a string literal is used instead of a const string for certain arguments for certain functions. Ie.
class MyClass
{
private void MyMethod(IWriter writer)
{
writer.WriteInteger("NamedValue", 4);
}
}
Should become:
class MyClass
{
private const string IoNamedValueKey = "NamedValue";
private void MyMethod(IWriter writer)
{
writer.WriteInteger(IoNamedValueKey , 4);
}
}
I've got the bit working where it displays the error, but I want to provide a CodeFixProvider as well. I've run into two problems:
- I need to add the
private const string IoNamedValueKey = "NamedValue";
statement, ideally just above the offending method. - But only if it doesn't exist already.
I'm not entirely sure the template approach for the CodeFixProvider uses the appropriate overloads for my purposes (it merely replaces type names with upper case variants), so what would be the best way forward from within the RegisterCodeFixesAsync method?
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
// ... now what?
}
According to roslynquoter the required node can be constructed as below, but I'm still somewhat at a loss about how to inject it into the context.
CompilationUnit()
.WithMembers(
SingletonList<MemberDeclarationSyntax>(
FieldDeclaration(
VariableDeclaration(
PredefinedType(
Token(SyntaxKind.StringKeyword)))
.WithVariables(
SingletonSeparatedList<VariableDeclaratorSyntax>(
VariableDeclarator(
Identifier("IoNamedValueKey"))
.WithInitializer(
EqualsValueClause(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal("NamedValue")))))))
.WithModifiers(
TokenList(
new []{
Token(SyntaxKind.PrivateKeyword),
Token(SyntaxKind.ConstKeyword)}))))
.NormalizeWhitespace()