Roslyn:分析调用方法的对象
Roslyn: Analyzing the object invoking the method
例如:
SqlCommand command = new SqlCommand();
SqlDataReader datareader = command.ExecuteReader();
这里的调用节点是command.ExecuteReader()
。我如何使用 roslyn 从调用节点获取 command
的变量标识符 token/node?
假设这个调用节点之前可以有许多其他方法调用,例如classA.methodA().methodB().classB.methodC(command.ExecuteReader())
并因此通过 node.DescendantNodes
获取标识符可能没有用。
我想到的解决办法是先获取ExecuteReader
的SpanStart,然后在ExecuteReader.SpanStart - 2
的位置调用SymbolFinder.FindSymbolAtPosition
获取command
的symbol。但是我不确定这个解决方案是否可以处理每一种情况。我正在处理的应用程序是一个静态代码分析器。
当你有一个调用节点时,你可以看到它的表达式是否是一个成员访问。如果调用是针对语句 "DoThis()" 的,则没有成员访问权限,但如果调用是针对 "x.DoThis()" 的调用,则 是 成员访问权限,因为 [=正在针对引用 "x".
调用 23=]
一旦您确认是成员访问,您就可以得到目标引用的表达式——这是其成员被访问的引用。这个表达式可能是一个简单的名称标识符(例如 "command"),也可能是另一个成员访问(例如 "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
}
}
例如:
SqlCommand command = new SqlCommand();
SqlDataReader datareader = command.ExecuteReader();
这里的调用节点是command.ExecuteReader()
。我如何使用 roslyn 从调用节点获取 command
的变量标识符 token/node?
假设这个调用节点之前可以有许多其他方法调用,例如classA.methodA().methodB().classB.methodC(command.ExecuteReader())
并因此通过 node.DescendantNodes
获取标识符可能没有用。
我想到的解决办法是先获取ExecuteReader
的SpanStart,然后在ExecuteReader.SpanStart - 2
的位置调用SymbolFinder.FindSymbolAtPosition
获取command
的symbol。但是我不确定这个解决方案是否可以处理每一种情况。我正在处理的应用程序是一个静态代码分析器。
当你有一个调用节点时,你可以看到它的表达式是否是一个成员访问。如果调用是针对语句 "DoThis()" 的,则没有成员访问权限,但如果调用是针对 "x.DoThis()" 的调用,则 是 成员访问权限,因为 [=正在针对引用 "x".
调用 23=]一旦您确认是成员访问,您就可以得到目标引用的表达式——这是其成员被访问的引用。这个表达式可能是一个简单的名称标识符(例如 "command"),也可能是另一个成员访问(例如 "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
}
}