private void getReferencedFilesRecursive(DirectedTypeNode node, HashSet <string> result, HashSet <DirectedTypeNode> seenTypes = null, int level = 0) { // A '.' is prepended since the logger trims lines. logger.Add($"{(level > 0 ? $".{new string(' ', level * 2 - 1)}| " : string.Empty)} {node}"); seenTypes ??= new HashSet <DirectedTypeNode>(); if (seenTypes.Contains(node)) { return; } seenTypes.Add(node); // Add all the current type's locations to the resulting set. foreach (var location in node.Reference.Symbol.Locations) { var syntaxTree = location.SourceTree; if (syntaxTree != null) { result.Add(syntaxTree.FilePath); } } // Follow through the process for all parents. foreach (var p in node.Parents) { getReferencedFilesRecursive(p, result, seenTypes, level + 1); } }
/// <summary> /// Traverses <see cref="referenceMap"/> to build a directed graph of <see cref="DirectedTypeNode"/> joined by their parents. /// </summary> /// <returns>A dictionary containing the directed graph from each <see cref="TypeReference"/> in <see cref="referenceMap"/>.</returns> private Dictionary <TypeReference, DirectedTypeNode> getDirectedGraph() { // Given the reference map (from above): // // P -> { C1, C2 } // C1 -> { C3, C4 } // C2 -> { C5, C6 } // C3 -> { } // C4 -> { C6 } // C5 -> { C6 } // C6 -> { C2 } // // The respective directed graph is built by traversing upwards and finding all incoming references at each type, such that: // // P -> { } // C1 -> { P } // C2 -> { C6, P, C5, C4, C2, C1 } // C3 -> { C1, P } // C4 -> { C1, P } // C5 -> { C2, P } // C6 -> { C5, C4, C2, C1, C6, P } // // The directed graph may contain cycles where multiple paths lead to the same node (e.g. C2, C6). logger.Add("Retrieving reference graph..."); var result = new Dictionary <TypeReference, DirectedTypeNode>(); // Traverse through the reference map and assign parents to all children referenced types. foreach (var kvp in referenceMap) { var parentNode = getNode(kvp.Key); foreach (var typeRef in kvp.Value) { getNode(typeRef).Parents.Add(parentNode); } } return(result); DirectedTypeNode getNode(TypeReference typeSymbol) { if (!result.TryGetValue(typeSymbol, out var existing)) { result[typeSymbol] = existing = new DirectedTypeNode(typeSymbol); } return(existing); } }
private bool computeExpansionFactors(DirectedTypeNode node, HashSet <DirectedTypeNode> seenTypes = null) { seenTypes ??= new HashSet <DirectedTypeNode>(); if (seenTypes.Contains(node)) { return(false); } seenTypes.Add(node); node.ExpansionFactor = (ulong)node.Parents.Count; foreach (var p in node.Parents) { if (computeExpansionFactors(p, seenTypes)) { node.ExpansionFactor += p.ExpansionFactor; } } return(true); }
private void getReferencedFilesRecursive(DirectedTypeNode node, HashSet <string> result, (double min, double max) exclusionRange, HashSet <DirectedTypeNode> seenTypes = null,