NDepend CQL Query для отсутствующей IDisposable реализации - PullRequest
4 голосов
/ 23 ноября 2008

Я понимаю, что запрос, который ищет этот вопрос, не будет достаточным для обнаружения каждой маленькой проблемы с реализациями IDisposable, но каждое раннее предупреждение имеет значение, поэтому я возьму то, что смогу получить.

Я хотел бы знать, если кто-нибудь придумал запрос CQL для NDepend, который перечислит все классы, которые не реализуют IDisposable, но имеет одно или несколько полей, которые это делают. Класс может оказаться в списке результатов этого запроса либо из-за ошибки (т. Е. Кто-то забыл проверить типы полей для реализаций IDisposable), либо из-за эволюции кода (т. Е. Класс, используемый в поле где-то, получает IDisposable, прикрепленный к более поздняя дата без обновления всех использований).

Простой запрос для поиска всех классов, которые не реализуют IDisposable:

SELECT TYPES WHERE !Implement "System.IDisposable"

Однако это, конечно, не проверит, должен ли класс реализовать IDisposable для вышеуказанного правила.

У кого-нибудь есть такой запрос? Я до сих пор разбираюсь с CQL, поэтому эта часть ускользает от меня.

1 Ответ

6 голосов
/ 24 ноября 2008

Lasse, благодаря возможностям CQLinq (Code Rule over LINQ) теперь возможно сопоставление типов, которые должны реализовывать IDisposable. На самом деле теперь предоставляются два связанных правила по умолчанию, и вы можете легко написать свои собственные связанные правила:


// <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 }
...