Roslyn:分析调用该方法的对象

时间:2016-06-14 06:08:37

标签: c# roslyn roslyn-code-analysis

例如:

SqlCommand command = new SqlCommand();
SqlDataReader datareader = command.ExecuteReader();

此处的调用节点为command.ExecuteReader()。我如何使用roslyn从调用节点获取command的变量标识符标记/节点? 假设此调用节点在其之前可以有许多其他方法调用,例如classA.methodA().methodB().classB.methodC(command.ExecuteReader())因此通过node.DescendantNodes获取标识符可能没有用。 我想到的解决方案是首先获得ExecuteReader的SpanStart,然后通过调用位置为command的{​​{1}}来获取SymbolFinder.FindSymbolAtPosition的符号。但是我不确定这个解决方案是否可以处理每一种情况。我正在处理的应用程序是静态代码分析器。

1 个答案:

答案 0 :(得分:4)

如果有调用节点,则可以查看其表达式是否为成员访问权限。如果调用是用于语句" DoThis()"然后没有成员访问权限但是如果调用是针对" x.DoThis()"那么成员访问,因为" DoThis"正在被引用" x"。

一旦确认 成员访问权限,您就可以获得目标引用的表达式 - 这是正在访问其成员的引用。该表达式可以是简单的名称标识符(例如,"命令"),或者它可以是另一个成员访问(例如," x.command"),或者它可能是另一个调用(例如, " GetCommand()")或者它们可能是这些的组合。

用代码说明 -

private static void AnalyseInvocation(SyntaxNodeAnalysisContext context)
{
    var invocation = (InvocationExpressionSyntax)context.Node;
    var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
    if ((memberAccess == null) || (memberAccess.Name.Identifier.ValueText != "ExecuteReader"))
        return;

    if (memberAccess.Expression is IdentifierNameSyntax)
    {
        // The target is a simple identifier, the code being analysed is of the form
        // "command.ExecuteReader()" and memberAccess.Expression is the "command"
        // node
    }
    else if (memberAccess.Expression is InvocationExpressionSyntax)
    {
        // The target is another invocation, the code being analysed is of the form
        // "GetCommand().ExecuteReader()" and memberAccess.Expression is the
        // "GetCommand()" node
    }
    else if (memberAccess.Expression is MemberAccessExpressionSyntax)
    {
        // The target is a member access, the code being analysed is of the form
        // "x.Command.ExecuteReader()" and memberAccess.Expression is the "x.Command"
        // node
    }
}