NDepend CQL Query для отсутствующей IDisposable реализации
Я понимаю, что запрос, который ищет этот вопрос, будет недостаточным для обнаружения каждой маленькой проблемы с реализациями IDisposable, но каждое раннее предупреждение имеет значение, поэтому я возьму то, что смогу получить.
Я хотел бы знать, если кто-нибудь придумал запрос CQL для NDepend, который перечислит все классы, которые не реализуют IDisposable, но имеют одно или несколько полей, которые делают. Класс может оказаться в списке результатов этого запроса либо из-за ошибки (т. Е. Кто-то забыл проверить типы полей для реализаций IDisposable), либо из-за эволюции кода (т. Е. Класс, используемый в поле где-то, получает IDisposable, прикрепленный к более поздняя дата без обновлений всех использований).
Простой запрос для поиска всех классов, которые не реализуют IDisposable:
SELECT TYPES WHERE !Implement "System.IDisposable"
Однако это, конечно, не будет проверять, должен ли класс реализовывать IDisposable для вышеуказанного правила.
У кого-нибудь есть такой запрос? Я все еще сталкиваюсь с CQL, поэтому эта часть ускользает от меня.
1 ответ
Лассе, благодаря возможностям 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 }