NDepend CQL Query for missing IDisposable implementation

I realize that the query this question is looking for won't be enough to find every little problem with IDisposable implementations, but every early warning counts, so I'll take what I can get.

I'd like to know if anyone has come up with a CQL query for NDepend that will list all classes that doesn't implement IDisposable, but has one or more fields that does. A class could end up on the resultlist of this query either through a bug (ie. someone forgot to check the field types for IDisposable implementations), or through code evolution (ie. a class used in a field somewhere gets IDisposable tacked on at a later date without all usages being updated).

The simple query to find all classes that doesn't implement IDisposable is:

SELECT TYPES WHERE !Implement "System.IDisposable"

However, this will of course not check if the class should implement IDisposable for the above rule.

Does anyone have such a query? I'm still getting to grips with CQL so this part eludes me.


Lasse, thanks to CQLinq (Code Rule over LINQ) capabilities matching types that should implement IDisposable is now possible. Actually two related default rules are now provided, and you can easily write your own related rules:

  • Types with disposable instance fields must be disposable
  • Disposable types with unmanaged resources should declare finalizer

  • // <Name>Types with disposable instance fields must be disposable</Name>
    warnif count > 0
    
    let iDisposable = ThirdParty.Types.WithFullName("System.IDisposable").FirstOrDefault() 
    where iDisposable != null // iDisposable can be null if the code base doesn't use at all System.IDisposable
    
    from t in Application.Types where 
       !t.Implement(iDisposable) && 
       !t.IsGeneratedByCompiler 
    
    let instanceFieldsDisposable = 
        t.InstanceFields.Where(f => f.FieldType != null &&
                                    f.FieldType.Implement(iDisposable))
    
    where instanceFieldsDisposable.Count() > 0
    select new { t, instanceFieldsDisposable }
    

    // <Name>Disposable types with unmanaged resources should declare finalizer</Name>
    // warnif count > 0
    let iDisposable = ThirdParty.Types.WithFullName("System.IDisposable").SingleOrDefault()
    where iDisposable != null // iDisposable can be null if the code base deosn't use at all System.IDisposable
    
    let disposableTypes = Application.Types.ThatImplement(iDisposable)
    let unmanagedResourcesFields = disposableTypes.ChildFields().Where(f => 
       !f.IsStatic && 
        f.FieldType != null && 
        f.FieldType.FullName.EqualsAny("System.IntPtr","System.UIntPtr","System.Runtime.InteropServices.HandleRef")).ToHashSet()
    let disposableTypesWithUnmanagedResource = unmanagedResourcesFields.ParentTypes()
    
    from t in disposableTypesWithUnmanagedResource
    where !t.HasFinalizer
    let unmanagedResourcesTypeFields = unmanagedResourcesFields.Intersect(t.InstanceFields)
    select new { t, unmanagedResourcesTypeFields }
    
    链接地址: http://www.djcxy.com/p/37720.html

    上一篇: 如何以编程方式创建NDepend项目文件?

    下一篇: N缺少IDisposable实现的CQL查询