NDepend Как написать запрос для методов косвенно, используя какой-либо метод с настраиваемым фильтром на переходах пути использования

Я немного борюсь с NDepend. Это немного сложно объяснить. В моей кодовой базе есть метод (давайте назовем этот метод «TheMethod»), который не должен вызываться другими методами определенного типа (давайте назовем этот тип «TheKind»), если они не украшены каким-либо атрибутом («TheAttr» ), прямо или косвенно; Если косвенно, любой прыжок, украшенный «TheAttr», не должен приводить к нарушению косвенного использования.

Я буду визуализировать некоторые сценарии со стрелкой «->», означающей «использует», и методами, имеющими вышеупомянутый атрибут с TheAttr с «[TheAttr]», и словом «FAIL», если правило должно быть нарушено / «SUCCESS», если правило не должно нарушаться.

So...

Я могу написать запрос CQLinq, который срабатывает для всех методов «TheKind», используя «TheMethod» прямо или косвенно. Я также могу исключить из результата методы, у которых есть «TheAttr».

somemethod -> TheMethod      FAIL
somemethod[TheAttr] -> TheMethod     SUCCESS

Получить косвенные использования в правиле также легко:

somemethod -> method1 -> method2 -> TheMethod     FAIL
somemethod[TheAttr] -> method1 -> method2 -> TheMethod    SUCCESS

Теперь, что я хочу, это:

somemethod -> method1[TheAttr] -> method2 -> TheMethod    SUCCESS

и

somemethod -> method1 -> method2[TheAttr] -> TheMethod    SUCCESS

Таким образом, другими словами, любой промежуточный вызывающий объект, имеющий украшение, должен приводить к допустимому использованию 'TheMethod'/вызовов "сквозь", допустимое использование также должно быть действительным.

Можно ли это проверить с помощью NDepend? Я экспериментировал с FillIterative, но пока безуспешно.

Спасибо, Тим

PS.: Вот моя текущая попытка:

    warnif count > 0 
let mcalling = Methods.WithFullName("My.Namespace.MyType.get_SomeProperty()").SingleOrDefault().MethodsCallingMe.ToList()
let domain = mcalling.FillIterative(callers => // Unique loop, just to let a chance to build the hashset.
                                      from o in (new object()).ToEnumerable()
                                      let hashset = callers.ToHashSet() // Use a hashet to make Intersect calls much faster!
                                      from m in Methods.UsingAny(callers).Except(callers) 
                                      where !m.HasAttribute("My.Namespace.NDependIgnore.MayUsePropAlthoughAsync".AllowNoMatch())
                                      select m
                                   )

let indirectcallers = domain.DefinitionDomain.Where(m1 => m1.IsAsync).ToArray()  // Avoid double enumeration

from m in indirectcallers
let depth = m.DepthOfIsUsing("My.Namespace.MyType.get_SomeProperty()")
where depth >= 0
select new 
{ 
  Method=m, 
  Depth=depth, 
  Level=domain[m]
}

person Dr. Tim dos Santos    schedule 24.11.2016    source источник
comment
Вы пытались поиграть с предложенным здесь запросом? (второй использует FillIterative()). ..callers.SelectMany(m1 => m1.MethodsCallingMe)...   -  person Patrick from NDepend team    schedule 24.11.2016
comment
Да, я действительно играл с этим запросом, пока безрезультатно. Я обновлю свой вопрос с моей текущей попыткой.   -  person Dr. Tim dos Santos    schedule 25.11.2016