【问题标题】:How to use SemanticModel to check if variable has been tested?如何使用 SemanticModel 检查变量是否已经过测试?
【发布时间】:2014-06-06 06:57:27
【问题描述】:

我正在处理 Roslyn extension 以警告 .ValueNullable<T> 值的未受保护的访问。

这提供了以下行为:

这个扩展已经可以工作了,但是测试访问是否“安全”的代码有点像 hack。我现在只是遍历语法树,looking for if statements

这种方法很丑陋,并且会产生一堆无效的警告。

以下是访问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;

有没有办法使用SemanticModel 来正确编写这个测试?

我正在考虑的一件事是在语法树上执行Abstract interpretation。但这似乎需要做很多工作,我希望不需要一个成熟的抽象解释器。

我不太清楚 Roslyn 是如何实现死代码分析的,但似乎与此有些相关。

【问题讨论】:

  • 我认为你的例子有一个错误:如果 bar == true 和 x == null,这将崩溃。 ||我认为,操作员在“安全”方面应该是对称的(尽管左侧可能意味着右侧的安全)。
  • 应该是&&,而不是||
  • 而您所要求的称为可达性分析。
  • Roslyn 的实现是内部的,可以在source.roslyn.codeplex.com/#Microsoft.CodeAnalysis.CSharp/…找到
  • @SLaks:实现是一个公共 API,你可以调用 SemanticModel.AnalyzeDataFlow。不过,汤姆需要更强大的东西。

标签: c# roslyn


【解决方案1】:

我还没有和 Roslyn 一起玩过。但是作为 ReSharper 的用户,它也有这个确切的功能,我可以做以下声明:

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

if( x != null)
     x.access

例子:

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

【讨论】:

  • 我喜欢你的想法(或 ReSharpers ;-)),但它不是更多的优化而不是问题的实际解决方案吗?您仍然必须证明对变量的第一次访问是安全的或空检查(通过 != null 或 HasValue 显式或通过比较、非空赋值等隐式)。
  • 它可能最终会成为一个递归问题。可以这么说:证明第一次访问和进一步访问是安全的。
【解决方案2】:

解决这个问题需要流量分析,而 Roslyn 还没有这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    • 2019-04-12
    • 2011-11-03
    • 2022-01-17
    相关资源
    最近更新 更多