如何使用SemanticModel检查变量是否已经过测试?

Tom*_*rst 7 c# roslyn

我正在研究Roslyn扩展,以警告不受保护.ValueNullable<T>值访问.

这提供了以下行为:

警告:

这个扩展已经很有效了,但是测试访问是否"安全"的代码有点像黑客.我现在只需走语法树,寻找if语句.

这种方法非常难看,会产生一堆无效的警告.

以下是访问x.Value应该是安全的一些示例:

int y;
int? x = foo();

y = x != null ? x.Value : 42;

if (x > 4)
  y = x.Value;

if (x != null && someExpr) // With && only one branch needs to be a test
  y = x.Value;

if (x == 3 || x == 4) // With || both branches must be a test
  y = x.Value;

if (x == null) return; // Exit method body before access .Value
y = x.Value;
Run Code Online (Sandbox Code Playgroud)

有没有办法使用SemanticModel正确编写此测试?

我正在考虑的一件事是对语法树进行抽象解释.但这似乎很多工作,我希望不需要一个完整的抽象解释器.

我不太确定在Roslyn中如何实现死代码分析,但它似乎与此有些相关.

Rob*_*tto 2

我还没有和罗斯林一起玩过。但作为 ReSharper 的用户,它也具有这个功能,我可以做以下声明:

我的观察是,ReSharper 只查看相应符号的最近使用情况(类型 Nullable<>)。这是一个迭代证明。如果该变量已(显然)成功使用,则连续使用是安全的。然后由之前的使用检查来证明这再次是安全的访问。因此:检查先前的访问是否有另一个先前的访问或与 null 进行挽救比较,以查看它是否安全。

if( x != null)
     x.access
Run Code Online (Sandbox Code Playgroud)

例子:

var z = x.Value; // unsafe because it is first and un-tested
var y = x.Value; // safe because it is not first and therefore dependent on first access
Run Code Online (Sandbox Code Playgroud)