/// <summary> /// Generates the PackageReference Section of the DOT Graph. /// </summary> /// <param name="anonymizer">The Anonymizer (if used) to anonymize names</param> /// <param name="packageReferences">The Dictionary from <see cref="ResolvePackageReferenceDependencies(IEnumerable{string})"/></param> /// <returns>An <see cref="IEnumerable{T}"/> that contains the lines to add to the DOT Graph</returns> internal static IEnumerable <string> GeneratePackageReferenceSection(Anonymizer <string> anonymizer, Dictionary <string, IEnumerable <string> > packageReferences) { // First we need to create the nodes for each of the Packages IEnumerable <string> distinctPackageReferences = packageReferences.SelectMany(kvp => kvp.Value).Distinct(); foreach (string distinctPackageReference in distinctPackageReferences) { string packageReference = distinctPackageReference; if (anonymizer != null) { packageReference = anonymizer.Anonymoize(packageReference); } yield return($"\"{packageReference}\" [style = filled, fillcolor = goldenrod, fontname=\"consolas\", fontcolor=black]"); } // Now Create the Connections foreach (KeyValuePair <string, IEnumerable <string> > kvp in packageReferences) { string projectName = Path.GetFileName(kvp.Key); if (anonymizer != null) { projectName = anonymizer.Anonymoize(projectName); } IEnumerable <string> packageReferencesForCurrentProject = kvp.Value; foreach (string packageReference in packageReferencesForCurrentProject) { string packageReferenceName = packageReference; if (anonymizer != null) { packageReferenceName = anonymizer.Anonymoize(packageReferenceName); } yield return($"\"{projectName}\" -> \"{packageReferenceName}\""); } } }
/// <summary> /// Generates the AssemblyReference Section of the DOT Graph. /// </summary> /// <param name="anonymizer">The Anonymizer (if used) to anonymize names</param> /// <param name="assemblyReferences">The Dictionary from <see cref="ResolveAssemblyReferenceDependencies(IEnumerable{string})"/></param> /// <returns>An <see cref="IEnumerable{T}"/> that contains the lines to add to the DOT Graph</returns> internal static IEnumerable <string> GenerateAssemblyReferenceSection(Anonymizer <string> anonymizer, Dictionary <string, IEnumerable <string> > assemblyReferences) { // First we need to create nodes for each of the Assemblies IEnumerable <string> distinctAssemblyReferences = assemblyReferences.SelectMany(kvp => kvp.Value).Distinct(); foreach (string distinctAssemblyReference in distinctAssemblyReferences) { string assemblyName = distinctAssemblyReference; if (anonymizer != null) { assemblyName = anonymizer.Anonymoize(assemblyName); } yield return($"\"{assemblyName}\" [class=\"AssemblyReference\"]"); } // Now Create the Connections foreach (KeyValuePair <string, IEnumerable <string> > kvp in assemblyReferences) { string projectName = Path.GetFileName(kvp.Key); if (anonymizer != null) { projectName = anonymizer.Anonymoize(projectName); } IEnumerable <string> assemblyReferencesForCurrentProject = kvp.Value; foreach (string assemblyReference in assemblyReferencesForCurrentProject) { string assemblyReferenceName = assemblyReference; if (anonymizer != null) { assemblyReferenceName = anonymizer.Anonymoize(assemblyReferenceName); } yield return($"\"{projectName}\" -> \"{assemblyReferenceName}\""); } } }
/// <summary> /// Given a Dictionary in which the Key Represents the Project and the Value represents the list Project Dependencies, generate a DOT Graph. /// </summary> /// <param name="projectReferenceDependencies">The dictionary to generate the graph for.</param> /// <param name="targetProject">Determines the project (based on name) to be highlighted</param> /// <param name="anonymizeNames">Determines if the names should be anonymized.</param> /// <param name="sortProjects">Determines if the output of the DOT Graph should be sorted.</param> /// <param name="showAssemblyReferences">Determines if Assembly/PackageReferences should be shown on the graph.</param> /// <returns>A string that represents a DOT Graph</returns> internal static string CreateDOTGraph(IDictionary <string, IEnumerable <string> > projectReferenceDependencies, string targetProject, bool anonymizeNames, bool sortProjects, bool showAssemblyReferences) { // If we are going to use a anonymizer initialize it Anonymizer <string> anonymizer = null; if (anonymizeNames) { anonymizer = new Anonymizer <string>(); } // If we have a target project set a flag (string TargetProject, HashSet <string> NOrderDependencies)directNOrderDependencies = (string.Empty, new HashSet <string>()); bool highlightNonNOrderDependencies = !string.IsNullOrWhiteSpace(targetProject); if (highlightNonNOrderDependencies) { directNOrderDependencies = GenerateDirectNOrderDependencies(targetProject, projectReferenceDependencies); } StringBuilder sb = new StringBuilder(); sb.AppendLine("digraph {"); // If we need to sort the projects do so at this time IEnumerable <KeyValuePair <string, IEnumerable <string> > > projectReferenceDependenciesToPrint = projectReferenceDependencies; if (sortProjects) { projectReferenceDependenciesToPrint = projectReferenceDependencies.OrderBy(kvp => Path.GetFileName(kvp.Key)); } // Perform the ProjectReference Results foreach (KeyValuePair <string, IEnumerable <string> > kvp in projectReferenceDependenciesToPrint) { string projectName = Path.GetFileName(kvp.Key); if (anonymizeNames) { projectName = anonymizer.Anonymoize(projectName); } IEnumerable <string> projectReferences = kvp.Value; if (sortProjects) { projectReferences = projectReferences.OrderBy(filePath => Path.GetFileName(filePath)); } if (highlightNonNOrderDependencies) { // If we are being asked to highlight non-norder // dependencies then we need to perform special // formatting on the graph if (directNOrderDependencies.TargetProject.Equals(kvp.Key)) { sb.AppendLine($"\"{projectName}\" [style = filled, fillcolor = yellow, fontname=\"consolas\", fontcolor=black]"); } else if (directNOrderDependencies.NOrderDependencies.Contains(kvp.Key)) { sb.AppendLine($"\"{projectName}\" [style = filled, fillcolor = green, fontname=\"consolas\", fontcolor=black]"); } else { sb.AppendLine($"\"{projectName}\" [style = filled, fillcolor = red, fontname=\"consolas\", fontcolor=black]"); } } else { sb.AppendLine($"\"{projectName}\""); } foreach (string projectDependency in projectReferences) { string projectDependencyName = Path.GetFileName(projectDependency); if (anonymizeNames) { projectDependencyName = anonymizer.Anonymoize(projectDependencyName); } sb.AppendLine($"\"{projectName}\" -> \"{projectDependencyName}\""); } } // If we need to show assembly references find them if (showAssemblyReferences) { sb.AppendLine("//--------------------------"); sb.AppendLine("// AssemblyReference Section"); sb.AppendLine("//--------------------------"); Dictionary <string, IEnumerable <string> > assemblyReferenceDependencies = ResolveAssemblyReferenceDependencies(projectReferenceDependencies.Keys); IEnumerable <string> assemblyReferenceSection = GenerateAssemblyReferenceSection(anonymizer, assemblyReferenceDependencies); if (sortProjects) { assemblyReferenceSection = assemblyReferenceSection.OrderBy(x => x); } foreach (string line in assemblyReferenceSection) { sb.AppendLine(line); } sb.AppendLine("//--------------------------"); sb.AppendLine("// PackageReference Section"); sb.AppendLine("//--------------------------"); Dictionary <string, IEnumerable <string> > packageReferenceDependencies = ResolvePackageReferenceDependencies(projectReferenceDependencies.Keys); IEnumerable <string> packageReferenceSection = GeneratePackageReferenceSection(anonymizer, packageReferenceDependencies); if (sortProjects) { packageReferenceSection = packageReferenceSection.OrderBy(x => x); } foreach (string line in packageReferenceSection) { sb.AppendLine(line); } } sb.AppendLine("}"); return(sb.ToString()); }
/// <summary> /// Given a Dictionary in which the Key Represents the Project and the Value represents the list Project Dependencies, generate a DOT Graph. /// </summary> /// <param name="projectReferenceDependencies">The dictionary to generate the graph for.</param> /// <param name="anonymizeNames">Determines if the names should be anonymized.</param> /// <param name="sortProjects">Determines if the output of the DOT Graph should be sorted.</param> /// <param name="showAssemblyReferences">Determines if Assembly/PackageReferences should be shown on the graph.</param> /// <returns>A string that represents a DOT Graph</returns> internal static string CreateDOTGraph(IDictionary <string, IEnumerable <string> > projectReferenceDependencies, MSBPROptions options) { // If we are going to use a anonymizer initialize it Anonymizer <string> anonymizer = null; if (options.AnonymizeNames) { anonymizer = new Anonymizer <string>(); } StringBuilder sb = new StringBuilder(); sb.AppendLine("digraph {"); // If we need to sort the projects do so at this time IEnumerable <KeyValuePair <string, IEnumerable <string> > > projectReferenceDependenciesToPrint = projectReferenceDependencies; if (options.SortProjects) { projectReferenceDependenciesToPrint = projectReferenceDependencies.OrderBy(kvp => Path.GetFileName(kvp.Key)); } // Perform the ProjectReference Results foreach (KeyValuePair <string, IEnumerable <string> > kvp in projectReferenceDependenciesToPrint) { string projectName = Path.GetFileName(kvp.Key); if (options.AnonymizeNames) { projectName = anonymizer.Anonymoize(projectName); } IEnumerable <string> projectReferences = kvp.Value; if (options.SortProjects) { projectReferences = projectReferences.OrderBy(filePath => Path.GetFileName(filePath)); } sb.AppendLine($"\"{projectName}\""); foreach (string projectDependency in projectReferences) { string projectDependencyName = Path.GetFileName(projectDependency); if (options.AnonymizeNames) { projectDependencyName = anonymizer.Anonymoize(projectDependencyName); } sb.AppendLine($"\"{projectName}\" -> \"{projectDependencyName}\""); } } // If we need to show assembly references find them if (options.ShowAssemblyReferences) { sb.AppendLine("//--------------------------"); sb.AppendLine("// AssemblyReference Section"); sb.AppendLine("//--------------------------"); Dictionary <string, IEnumerable <string> > assemblyReferenceDependencies = ResolveAssemblyReferenceDependencies(projectReferenceDependencies.Keys); IEnumerable <string> assemblyReferenceSection = GenerateAssemblyReferenceSection(anonymizer, assemblyReferenceDependencies); if (options.SortProjects) { assemblyReferenceSection = assemblyReferenceSection.OrderBy(x => x); } foreach (string line in assemblyReferenceSection) { sb.AppendLine(line); } } if (options.ShowPackageReferences) { sb.AppendLine("//--------------------------"); sb.AppendLine("// PackageReference Section"); sb.AppendLine("//--------------------------"); Dictionary <string, IEnumerable <string> > packageReferenceDependencies = ResolvePackageReferenceDependencies(projectReferenceDependencies.Keys); IEnumerable <string> packageReferenceSection = GeneratePackageReferenceSection(anonymizer, packageReferenceDependencies); if (options.SortProjects) { packageReferenceSection = packageReferenceSection.OrderBy(x => x); } foreach (string line in packageReferenceSection) { sb.AppendLine(line); } } sb.AppendLine("}"); return(sb.ToString()); }