Skip to content

Instantly share code, notes, and snippets.

@robfe
Created October 27, 2010 14:39
Show Gist options
  • Save robfe/649146 to your computer and use it in GitHub Desktop.
Save robfe/649146 to your computer and use it in GitHub Desktop.
Analyses all the csproj files in a directory and generates a dot (www.graphviz.com) graph of the project references, including silverlight application references
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Linq;
namespace ReferenceReader
{
class CsProjReferencesToDot
{
static void Main(string[] args)
{
var foregroundColor = Console.ForegroundColor;
if (!args.Any())
{
args = new[] { Environment.CurrentDirectory };
}
var dict = args.SelectMany(dir => Directory.EnumerateFiles(dir, "*.csproj", SearchOption.AllDirectories)).ToDictionary(x => x, x => new Project(x));
dict.Values.AsParallel().ForAll(project => project.Link(dict));
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine("digraph g{");
Console.WriteLine(" rankdir=LR");
Console.WriteLine(" node[fontname=calibri]");
var projects = dict.Values.ToList();
int projectCount = 0;
int projectReferences = 0;
int silverlightReferences = 0;
int brokenReferences = 0;
foreach (Project project in projects)
{
projectCount++;
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine(" {0}[label=\"{1} ({2})\"]", project.Id, project.Name, project.CsFiles);
foreach (Project r in project.ProjectReferences)
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(" {0}->{1}[color=darkgreen]", project.Id, r.Id);
projectReferences++;
}
foreach (Project r in project.SilverlightReferences)
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(" {0}->{1}[color=blue]", project.Id, r.Id);
silverlightReferences++;
}
foreach (string r in project.BrokenReferences)
{
Console.ForegroundColor = ConsoleColor.Red;
var id = r.Replace('.', '_').Replace('\\', '_');
Console.WriteLine(" {0}[label=\"{1}\"]", id, r.Replace("\\", "\\\\"));
Console.WriteLine(" {0}->{1}[color=red]", project.Id, id);
brokenReferences++;
}
}
Console.ForegroundColor = ConsoleColor.DarkGray;
StringBuilder sb = new StringBuilder("Project Reference analysis: ");
sb.AppendFormat("path = [{0}], ", string.Join(", ", args).Replace("\\", "\\\\"));
sb.AppendFormat("projects = {0}, ", projectCount);
sb.AppendFormat("project references = {0}, ", projectReferences);
sb.AppendFormat("silverlight references = {0}, ", silverlightReferences);
sb.AppendFormat("external/broken references = {0}", brokenReferences);
Console.WriteLine(" graph[label=\"{0}\", fontsize=30]", sb);
Console.WriteLine("}");
Console.ForegroundColor = foregroundColor;
}
}
class Project
{
static readonly XNamespace Ns = "http://schemas.microsoft.com/developer/msbuild/2003";
public Project(string file)
{
Name = Path.GetFileNameWithoutExtension(file);
FullPath = file;
}
protected string FullPath { get; set; }
public List<Project> ProjectReferences { get; set; }
public List<Project> SilverlightReferences { get; set; }
public List<string> BrokenReferences { get; set; }
public int CsFiles { get; set; }
public string Name { get; set; }
public string Id { get { return Name.Replace('.', '_'); } }
public void Link(Dictionary<string, Project> projects)
{
ProjectReferences = new List<Project>();
SilverlightReferences = new List<Project>();
BrokenReferences = new List<string>();
var xml = XDocument.Load(FullPath).Root;
Debug.Assert(xml != null);
//<Compile Include="Program.cs" />
CsFiles = xml.Descendants(Ns + "Compile").Where(x => ((string) x.Attribute("Include")).EndsWith(".cs")).Count();
foreach (XElement element in xml.Descendants(Ns + "ProjectReference"))
{
var rel = (string)element.Attribute("Include");
var path = new Uri(Path.Combine(Path.GetDirectoryName(FullPath), rel)).AbsolutePath.Replace("%20", " ");
path = new FileInfo(path).FullName;
if (projects.ContainsKey(path))
{
ProjectReferences.Add(projects[path]);
}
else
{
BrokenReferences.Add(rel);
}
}
foreach (var item in xml.Descendants(Ns + "SilverlightApplicationList").SelectMany(x => x.Value.Split(',')))
{
var cells = item.Split('|');
var rel = cells[1];
var path = new Uri(Path.Combine(Path.GetDirectoryName(FullPath), rel)).AbsolutePath;
path = new FileInfo(path).FullName;
if (projects.ContainsKey(path))
{
SilverlightReferences.Add(projects[path]);
}
else
{
BrokenReferences.Add(rel);
}
}
}
public override string ToString()
{
return string.Format("Name: {0}, ProjectReferences [{1}]", Name, String.Join(", ", ProjectReferences.Select(x => x.Name)));
}
}
}
@robfe
Copy link
Author

robfe commented Oct 27, 2010

usage:

CsProjReferencesToDot.exe "C:\rootdirectory" | dot -Tpdf -oreferences.pdf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment