Roslyn Rewrite Method调用使用await Modifier

时间:2016-12-21 14:04:19

标签: c# roslyn roslyn-code-analysis

我想要迁移到我们用于开发的内部框架的新版本的一堆C#文件。到目前为止,我已经能够完成某些事情但是有一个特定的方法调用,我必须修改以使用await修饰符,方法调用有不同的风格,如此

 var a = EntityService.GetBy(Entities.INSTANT_ISSUANCE_REQUEST, requestFilter);
 var b = EntityService.GetBy(Entities.ISSUANCE_SETTINGS, new DejaVuObject()).FirstOrDefault();

我必须修改上面的方法调用,以便它们使用以下语法

 var a = await EntityService.GetBy(Entities.INSTANT_ISSUANCE_REQUEST, requestFilter);
 var b = await EntityService.GetBy(Entities.ISSUANCE_SETTINGS, new DejaVuObject()).FirstOrDefault();

我正在使用Roslyn CSharpSyntaxWriter来遍历语法树。

public override SyntaxNode VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
{
    var variableDeclarations = 
        from i in node.DescendantNodes().OfType<VariableDeclaratorSyntax>()
        where i.DescendantNodes().OfType<EqualsValueClauseSyntax>().Any<EqualsValueClauseSyntax>(
            p => p.DescendantNodes().OfType<InvocationExpressionSyntax>().Any<InvocationExpressionSyntax>())
        select i;

    foreach (var syntax in variableDeclarations)
    {
        var equalsToken = syntax.DescendantNodes();
        //now we have the equals token 
        foreach (var syntaxNode in equalsToken)
        {
            if (syntaxNode is EqualsValueClauseSyntax)
            {
                var equalsValueSyntax = syntaxNode.DescendantNodes().OfType<InvocationExpressionSyntax>();
                foreach (var invocationExpressionSyntax in equalsValueSyntax)
                {
                    var simpleMemberAcessExpressions = invocationExpressionSyntax
                        .DescendantNodes()
                        .OfType<IdentifierNameSyntax>()
                        .Where(i => i.Identifier.Text == "EntityService");
                    foreach (var simpleMemberAcessExpression in simpleMemberAcessExpressions)
                    {
                        var newExpression = $"{invocationExpressionSyntax.ToFullString()}";
                        Console.WriteLine(newExpression);
                        //TODO: Modify the Node
                    }
                }
            }
        }
    }
    return base.VisitLocalDeclarationStatement(node);
}

我的问题是Console中的输出有些重复

EntityService.GetBy(Entities.ISSUANCE_SETTINGS, new DejaVuObject()).FirstOrDefault();
EntityService.GetBy(Entities.ISSUANCE_SETTINGS, new DejaVuObject())

两者都引用相同的InvocationExpression,但由于FirstOrDefault()它在控制台输出中显示两次

我想要一种方法来过滤结果,使它们只包含唯一的方法调用,并通过添加await修饰符和更新节点来执行方法调用的实际修改。

1 个答案:

答案 0 :(得分:0)

首先,为什么要覆盖VisitLocalDeclarationStatement?看起来你应该重写VisitInvocationExpression

你不应该这样做:

var simpleMemberAcessExpressions = 
    invocationExpressionSyntax.DescendantNodes().OfType<IdentifierNameSyntax>()

相反,它应该是这样的:

var identifier = 
    (node.Expression as MemberAccessExpressionSyntax)?.Expression as IdentifierNameSyntax;

if (identifier != null && identifier.Identifier.Text == "EntityService")
{
    // process the invocation expression
}

假设调用表达式被称为node,您的新表达式可能是

var newExpression = 
    SyntaxFactory.ParenthesizedExpression(SyntaxFactory.AwaitExpression(node))
    .WithAdditionalAnnotations(Simplifier.Annotation)
    .WithAdditionalAnnotations(Formatter.Annotation);