Roslyn C#CodeFixProvider和Trivia发生意外的换行符

时间:2019-04-22 15:47:49

标签: c# roslyn codefixprovider

我目前正在尝试编写一个C#CodeFixProvider,如果存在相应的属性,则应该使用属性设置程序访问权限来替换对setXXX()方法的调用。 基本上

setSimpleProperty(42);

替换为

SimpleProperty = 42;

核心似乎工作正常,但我在琐事上苦苦挣扎。在以下示例中

/*a*/setSimpleProperty(/*b*/ 42 /*c*/)/*d*/;
  1. a导致琐事的调用
  2. b将琐事拖到参数列表的大括号中
  3. c将琐事拖到论点本身
  4. d正在跟踪琐事到调用

我试图正确处理这些问题,以获得预期的结果

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

但是,我遇到了意外的换行符,无法找出问题所在:

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

我的基本代码如下:

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只是辅助扩展方法:

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);
}

那怎么了?我从哪里得到换行符?

1 个答案:

答案 0 :(得分:0)

为什么要使用AppendLeadingTrivia而不是WithLeadingTrivia,这与Trailing相同。我认为您是“附加”到ElasticTrivia,然后取决于Normalizer的功能。您正在控制示例中的所有琐事。