private static void FindIndirectCircularReferences(ISet<Node> childList) { var toIgnore = new HashSet<Node>(); foreach (var node in childList.ToHashSet()) { if(toIgnore.Contains(node)) continue; var path = new HashSet<Node>(); if (IndirectlyDependsOnItself(node, node, ref path)) { path.Add(node); toIgnore.UnionWith(path); childList.ExceptWith(path); var dependantOnCircularDependencies = childList.Where(x => path.Any(x.DependsOn)); var cirularHolder = new CircularDependencyHolderNode(path); foreach (var dependantOnCircularDependency in dependantOnCircularDependencies) { //Remove all dependencies on nodes in the path dependantOnCircularDependency.SiblingDependencies.RemoveWhere(x => path.Contains(x)); //Add dependency on circular holder dependantOnCircularDependency.SiblingDependencies.Add(cirularHolder); } //Add all dependencies in the path to the new node cirularHolder.SiblingDependencies.UnionWith(path.SiblingDependencies().Except(path)); //Should not be dependant on themselves childList.Add(cirularHolder); } } }
public void FindsInnerPatternAmongNestedPatterns() { var nodesList = new HashSet<Node>(); var i = 0; var left = new Node("Left" + i); nodesList.Add(left); var prevDown = left; while (++i < 10) { var nextRight = new Node("Right" + i); var nextDown = new Node("Down" + (i + 1)); prevDown.SiblingDependencies.Add(nextDown); nextRight.SiblingDependencies.Add(nextDown); prevDown = nextDown; nodesList.Add(nextRight); nodesList.Add(nextDown); } var firstLayer = SiblingReorderer.GetFacadeNodes(nodesList); var nextLayer = SiblingReorderer.GetFacadeNodes(nodesList.SiblingDependencies()); var pattern = SiblingReorderer.FindDependencyPatterns(firstLayer, nextLayer); CollectionAssert.Contains(pattern.First().Referencers.ToArray(), left); var newList = SiblingReorderer.LayOutSiblingNodes(nodesList); var toIterate = newList.Last(); i-=1; while (toIterate != null) { var right = toIterate.Childs.Last(); right.Name.Should().Be("Right" + i); var container = toIterate?.Childs?.First(); if (!container.Childs.Any()) break; var down = container.Childs.First(); toIterate = container.Childs.Last(); down.Name.Should().Be("Down" + i); i--; } }