C# 在编写Roslyn分析器时,如何获取给定变量名的当前值?

C# 在编写Roslyn分析器时,如何获取给定变量名的当前值?,c#,roslyn,code-analysis,roslyn-code-analysis,C#,Roslyn,Code Analysis,Roslyn Code Analysis,以下代码片段是我希望分析的代码: var name = "Michael"; name = "John"; var person = new Person(name); 假设我的分析器应该抱怨,如果给人的构造函数的名称的长度小于5 我知道如何获取传递到此对象创建表达式的字符串literalvar person=new person(“John”)的值,检查第一个参数类型,然后如果它是字符串literal,则获取它的value属性 但是如何让分析器在Person对象创建表达式站点上给我提供nam

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

var name = "Michael";
name = "John";
var person = new Person(name);
假设我的分析器应该抱怨,如果给
人的
构造函数
名称
的长度小于5

我知道如何获取传递到此对象创建表达式的字符串literal
var person=new person(“John”)
的值,检查第一个参数类型,然后如果它是字符串literal,则获取它的
value
属性

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

到目前为止,我已经尝试了一些类似于

var nameExpr = (IdentifierNameSyntax)objectCreation.ArgumentList?.Arguments.First()?.Expression;
var nameDataFlow = context.SemanticModel.AnalyzeDataFlow(nameExpr);
看起来我可以通过使用此数据流计算出
name
的值,但它似乎涉及一组非常复杂且不稳定的代码,并且在我看来,仅当声明位于数据流代码块内时,它才起作用。我希望它能够将这个令牌解析为它的实际值(如果可能的话),甚至在全局编译中也是如此

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

有没有一种简单的方法让库为我做这件事,如果可以的话,在调用站点给我变量的值

有没有一种简单的方法让库为我做这件事,如果可以的话,在调用站点给我变量的值

不,事实上,对于具有任意输入的任意程序,这是可以证明的

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

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

即使是简单的情况,这也会很复杂。考虑价值可能发生变化的所有方式:

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

分析器在编译时运行。您不能构建总是知道变量的运行时值的编译时工具。假设您从userinput(例如从
Console.ReadLine()
)分配
name
一个值。是的,我对此做了更多的研究,roslyn目前似乎没有算法。但是它是可以实现的,如果它最终解析为一个表达式(而不是一个值),那么我可以基于它进行一些分析,即使在多线程环境中,我也可以报告它可能的值,如果分析达到一定的复杂性,那么我最终可以放弃它并说“我不知道”这个变量的值是什么或可能是什么。你是对的,这个值很快就会完全失控,2^n个潜在值,其中n是条件赋值计数!我想我将从在块中声明变量的情况开始,只讨论文字赋值(在我的具体示例中就是这样),然后看看您可以在当前资源中走多远会很有趣。