首页 > 解决方案 > 编写 Roslyn 分析器时如何获取给定变量名称的当前值?

问题描述

以下代码片段是我要分析的代码:

var name = "Michael";
name = "John";
var person = new Person(name);

假设我的分析器应该抱怨如果name给定constructor的长度Person小于 5。

我知道如何获取var person = new Person("John")传递给此对象创建表达式的字符串文字的值,检查第一个参数类型,然后如果它是字符串文字,则抓住它的Value属性。

但是我如何让分析器给我namePerson对象创建表达式站点的值。这name在代码中明确定义,因此在这种情况下应该是可能的。

到目前为止,我已经尝试过类似...

var nameExpr = (IdentifierNameSyntax)objectCreation.ArgumentList?.Arguments.First()?.Expression;
var nameDataFlow = context.SemanticModel.AnalyzeDataFlow(nameExpr);

看起来我可以通过使用此数据流来计算 的值name,但它似乎涉及一组非常复杂且易碎的代码,并且在我看来,只有在声明位于数据流代码块内时才有效。我希望它能够将此令牌解析为它的实际值(如果可能的话),即使在全局编译中也是如此。

即使我自己编写了全局编译钩子,我也必须手动跟踪对变量的每个分配(包括来自其他变量和方法调用等)

有没有一种简单的方法可以让图书馆为我做这件事,如果可以的话,只需在调用站点给我变量的值吗?

标签: c#roslyncode-analysisroslyn-code-analysis

解决方案


有没有一种简单的方法可以让图书馆为我做这件事,如果可以的话,只需在调用站点给我变量的值吗?

不,事实上这对于具有任意输入的任意程序来说是不可能的。

一个例外是当变量是编译类型常量 ( const) 时,在这种情况下,您可以使用SemanticModel.GetConstantValue.

我可以报告它的可能值,如果分析达到一定的复杂性,那么我最终可以放弃它并说“我不知道”这个变量的值是什么或可能是什么。

即使是简单的情况,这也会很复杂。想想值可能改变的所有方式:

  • 该变量可以有条件地分配给代码块内。您将如何尝试确定条件是否为真?
  • 该变量可以在 lambda 函数中捕获。您将如何分析 lambda 函数及其调用?
  • 该变量可以分配给一个表达式,其中可能包括对其他方法的调用等。您将如何确定任意表达式的值?
  • 变量的值可能取决于程序在运行时读取的数据。举个简单的例子, 的值是DateTime.Now多少?您无法使用静态分析来确定这一点。
  • 好多其它的。

推荐阅读