1

I am currently trying to write a C# CodeFixProvider which is supposed to replace calls to setXXX() methods with property setter access if a corresponding property exists. Basically

setSimpleProperty(42);

is replaced with

SimpleProperty = 42;

The core seems to work fine, but I am struggling with trivia. In the following example

/*a*/setSimpleProperty(/*b*/ 42 /*c*/)/*d*/;
  1. a is leading trivia to the invocation
  2. b is trailing trivia to the open brace of the argument list
  3. c is trailing trivia to the argument itself
  4. d is trailing trivia to the invocation

I tried to correctly handle these, to get the expected result

/*a*/SimpleProperty = /*b*/42/*c*//*d*/;

However, I am getting unexpected line breaks and cannot figure out what is wrong:

        /*a*/
        SimpleProperty =
/*b*/ 42 /*c*//*d*/;

My basic code is as follows:

private static Task<Document> ReplaceMethodCallWithPropertySetAsync(Document document, InvocationExpressionSyntax invocation, ISymbol property, CancellationToken cancellationToken)
{
    ExpressionSyntax propertyAccess = null;


    if (invocation.Expression is IdentifierNameSyntax)
    {
        propertyAccess = SyntaxFactory.IdentifierName(property.Name);
    }
    else if (invocation.Expression is MemberAccessExpressionSyntax memberAccess)
    {
        propertyAccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, memberAccess.Expression, SyntaxFactory.IdentifierName(property.Name));
    }

    var val = invocation.ArgumentList.Arguments.First().Expression.AppendLeadingTrivia(invocation.ArgumentList.OpenParenToken.TrailingTrivia);

    var newNode = SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, propertyAccess, val);
    newNode = newNode.AppendLeadingTrivia(invocation.GetLeadingTrivia()).AppendTrailingTrivia(invocation.GetTrailingTrivia());

    return document.ReplaceNodeAsync(invocation, newNode, cancellationToken);
}

AppendLeadingTrivia/AppendTralingTrivia are just helper extension methods:

public static T AppendTrailingTrivia<T>(this T node, IEnumerable<SyntaxTrivia> trivias) where T : SyntaxNode
{
    if (trivias == null)
        return node;

    if (node.HasTrailingTrivia)
        return node.WithTrailingTrivia(node.GetTrailingTrivia().Concat(trivias));
    else
        return node.WithTrailingTrivia(trivias);
}

So what is wrong? Where am I getting the line breaks from?

user1211286
  • 681
  • 5
  • 17

0 Answers0