1

我们有 NDepend 5.4.1,我们想要更改可能具有较低可见性的字段/类型/方法的查询。我们希望查询在决定是否将其视为违规时考虑封闭类的范围。

例如,

internal class X
{
   public int A;
   public void B() { }
   public class C
   {
      // …
   }
}

我们不希望 A、B 或 C 产生违规,说它们中的任何一个都应该是内部的。另一方面,如果类 X 是公共的,并且 A、B 和 C 都没有在程序集之外使用,那么它们都应该产生违规。

为此,我在查询中添加了以下行:

 // consider visibility of enclosing class
 f.ParentType.Visibility < f.OptimalVisibility

因此对于字段,新查询如下所示:

// <Name>Fields that could have a lower visibility</Name>
warnif count > 0 from f in JustMyCode.Fields where 
  f.Visibility != f.OptimalVisibility &&
 !f.HasAttribute("NDepend.Attributes.CannotDecreaseVisibilityAttribute".AllowNoMatch()) &&
 !f.HasAttribute("NDepend.Attributes.IsNotDeadCodeAttribute".AllowNoMatch()) &&
 // consider visibility of enclosing class
 f.ParentType.Visibility < f.OptimalVisibility

select new { f, 
             f.Visibility , 
             CouldBeDeclared = f.OptimalVisibility,
             f.MethodsUsingMe }

我以类似的方式更改了方法可见性和类型可见性的查询,除了类型我确保有一个封闭的父类型:

(t.ParentType == null || t.ParentType.Visibility < t.OptimalVisibility)

乍一看,在运行了一些测试之后,这似乎是在做正确的事情。我的问题是这是否会产生任何误报或错过任何违规行为,因为我不确定枚举可见性排序(比较)是否在所有情况下都会做正确的事情。

4

1 回答 1

0

这是NDepend.CodeModel.Visibility枚举声明:

   public enum Visibility {
      None = 0,
      Public = 1,
      ProtectedAndInternal = 2,
      ProtectedOrInternal = 3,
      Internal = 4,
      Protected = 5,
      Private = 6
   }

因此x.ParentType.Visibility < x.OptimalVisibility意味着x parent type visibility is strictly less restrictive than x optimal visibility

请注意,Protected被排序为比Internalwhich is not更严格,true也不Internal是比 更严格Protected。所以我们必须在这两个可见性级别之间提供任意排序。

另请注意,可以在嵌套类型(递归)中声明方法/字段/嵌套类型,因此为了正确起见,我们需要收集所有外部类型的可见性。

这两个事实使我认为我们可以构建您的规则将返回误报的极端情况,但经过一番修改后我没有成功。

我们的建议是查看您的代码库您的自定义规则的行为方式,以确定是否应该修改它们。如果它没问题,那么在你最终发现误报之前认为它没问题。


在Eric Lippert 的博客上,关于内部类型的成员是否应该被声明为 public 或 internal有一个长期的相关辩论。双方都有充分的论据,我们的代码规则的编写方式有利于它应该被声明为 internal的一方,而您的更改有利于它应该被声明为 public的一方。

于 2015-06-03T06:03:44.417 回答