Gargoyle
Gargoyle

Reputation: 10375

Extra iterative code fix when adding using statement via roslyn

I'm trying to add an attribute and a using statement in my code fix, but it's happening as two iterations, and thus fails to work properly. I don't understand enough about Roslyn yet to know why I'm getting a second iteration.

This is my code fix:

private static async Task<Document> AddRequiredAttributeAsync(Document document, PropertyDeclarationSyntax property, CancellationToken cancellationToken) {
    var attribute = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Required"));
    var attributeList = SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(attribute));
    var updated = property.AddAttributeLists(attributeList);

    var editor = await DocumentEditor
        .CreateAsync(document, cancellationToken)
        .ConfigureAwait(false);

    editor.ReplaceNode(property, updated);

    const string @ns = "System.ComponentModel.DataAnnotations";

    var root = (CompilationUnitSyntax)editor.OriginalRoot;
    if (root.Usings.Any(x => x.Name?.ToString() == @ns) is false) {
        var usingDirective = SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(@ns));
        var newRoot = root.AddUsings(usingDirective);
        editor.ReplaceNode(root, newRoot);
    }

    return editor.GetChangedDocument();
}

In my test, for the fixed code, it fails saying it got two iterations if I use the following:

var fixedCode = """
    using System.ComponentModel.DataAnnotations;

    [Table("foo")]
    class SomeClass {
        [Required]
        public int Age { get; set; }
    }
    """;

Interestingly, if I move the { on the class definition to the next line, then it does not fail with a second iteration, but the match then fails because the fixed code expects the { to be on the same line as the class.

Upvotes: 0

Views: 18

Answers (0)

Related Questions