优化嵌套可见性的CQLinq规则

时间:2015-06-02 16:09:41

标签: ndepend cqlinq

我们有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)

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

1 个答案:

答案 0 :(得分: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的排序限制比Internal更严格,true Internal Protected的限制性比{{1}}更严格。所以我们必须在这两个可见性级别之间提供任意顺序。

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

这两个事实让我觉得我们可以构建一些边缘情况,你的规则会返回误报,但经过修改后我没有成功。

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

关于Eric Lippert blog关于内部类型的成员是否应被宣布为公开或内部的问题,存在长期相关的争论。双方都有坚实的论据,而且我们的代码规则的编写方式有利于方它应该被声明为内部,而你的更改有利于方它应该被声明为public