c# - 编写 Roslyn 分析器时如何获取给定变量名称的当前值?
问题描述
以下代码片段是我要分析的代码:
var name = "Michael";
name = "John";
var person = new Person(name);
假设我的分析器应该抱怨如果name
给定constructor
的长度Person
小于 5。
我知道如何获取var person = new Person("John")
传递给此对象创建表达式的字符串文字的值,检查第一个参数类型,然后如果它是字符串文字,则抓住它的Value
属性。
但是我如何让分析器给我name
在Person
对象创建表达式站点的值。这name
在代码中明确定义,因此在这种情况下应该是可能的。
到目前为止,我已经尝试过类似...
var nameExpr = (IdentifierNameSyntax)objectCreation.ArgumentList?.Arguments.First()?.Expression;
var nameDataFlow = context.SemanticModel.AnalyzeDataFlow(nameExpr);
看起来我可以通过使用此数据流来计算 的值name
,但它似乎涉及一组非常复杂且易碎的代码,并且在我看来,只有在声明位于数据流代码块内时才有效。我希望它能够将此令牌解析为它的实际值(如果可能的话),即使在全局编译中也是如此。
即使我自己编写了全局编译钩子,我也必须手动跟踪对变量的每个分配(包括来自其他变量和方法调用等)
有没有一种简单的方法可以让图书馆为我做这件事,如果可以的话,只需在调用站点给我变量的值吗?
解决方案
有没有一种简单的方法可以让图书馆为我做这件事,如果可以的话,只需在调用站点给我变量的值吗?
不,事实上这对于具有任意输入的任意程序来说是不可能的。
一个例外是当变量是编译类型常量 ( const
) 时,在这种情况下,您可以使用SemanticModel.GetConstantValue
.
我可以报告它的可能值,如果分析达到一定的复杂性,那么我最终可以放弃它并说“我不知道”这个变量的值是什么或可能是什么。
即使是简单的情况,这也会很复杂。想想值可能改变的所有方式:
- 该变量可以有条件地分配给代码块内。您将如何尝试确定条件是否为真?
- 该变量可以在 lambda 函数中捕获。您将如何分析 lambda 函数及其调用?
- 该变量可以分配给一个表达式,其中可能包括对其他方法的调用等。您将如何确定任意表达式的值?
- 变量的值可能取决于程序在运行时读取的数据。举个简单的例子, 的值是
DateTime.Now
多少?您无法使用静态分析来确定这一点。 - 好多其它的。
推荐阅读
- flutter - 我需要做这个布局,但我很困惑我应该用什么来放置它们,就像我在下面发布的图片中一样
- java - Spring Boot 自定义 HTTP 异常
- mysql - SQL查询以匹配日期的最后一个实例
- amazon-web-services - S3 生命周期配置与使用 PowerShell 的过滤器
- shell - Jenkins shell 中的多个变量
- meteor - Meteor:可以按 _id 过滤集合,但我不能使用其他字段过滤集合
- c# - 在 C# 中访问对象的“名称”属性
- tensorflow - Mlflow:使用 Tensorflow train_and_evaluate 在评估阶段记录步骤
- regex - 如何在 Go 中使用/访问捕获组?
- apache-spark - PySpark 无法通过 sparkContext/hiveContext 读取 Hive ORC 事务表?我们可以使用 Pyspark 更新/删除配置单元表数据吗?