Skip to content

Instantly share code, notes, and snippets.

@praeclarum
Created January 13, 2012 20:42
Show Gist options
  • Save praeclarum/1608597 to your computer and use it in GitHub Desktop.
Save praeclarum/1608597 to your computer and use it in GitHub Desktop.
Computes the code share stats for the iCircuit project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using System.IO;
namespace CodeShareReport
{
class App
{
static void Main (string[] args)
{
var projects = new List<Solution> {
new Solution {
Name = "Mac",
ProjectFiles = new List<string> {
"C:\\Projects\\Circuit\\CircuitMac\\CircuitMac.csproj"
},
},
new Solution {
Name = "WP7",
ProjectFiles = new List<string> {
"C:\\Projects\\Circuit\\CircuitMetro\\CircuitMetro.csproj"
},
},
new Solution {
Name = "iOS",
ProjectFiles = new List<string> {
"C:\\Projects\\Circuit\\CircuitTouch\\CircuitTouch.csproj",
"C:\\Projects\\Circuit\\CircuitLib\\CircuitLib.csproj"
},
},
};
new App().Run(projects);
}
class Solution
{
public string Name = "";
public List<string> ProjectFiles = new List<string>();
public List<FileInfo> CodeFiles = new List<FileInfo>();
public override string ToString ()
{
return Name;
}
public int UniqueLinesOfCode
{
get
{
return (from f in CodeFiles
where f.Solutions.Count == 1
select f.LinesOfCode).Sum();
}
}
public int SharedLinesOfCode
{
get
{
return (from f in CodeFiles
where f.Solutions.Count > 1
select f.LinesOfCode).Sum();
}
}
public int TotalLinesOfCode
{
get
{
return (from f in CodeFiles
select f.LinesOfCode).Sum();
}
}
}
class FileInfo
{
public string Path = "";
public List<Solution> Solutions = new List<Solution>();
public int LinesOfCode = 0;
public override string ToString ()
{
return Path;
}
}
Dictionary<string, FileInfo> _files = new Dictionary<string, FileInfo>();
void AddRef (string path, Solution sln)
{
if (_files.ContainsKey(path)) {
_files[path].Solutions.Add(sln);
sln.CodeFiles.Add(_files[path]);
}
else {
var info = new FileInfo { Path = path, };
info.Solutions.Add(sln);
_files[path] = info;
sln.CodeFiles.Add(info);
}
}
void Run (List<Solution> solutions)
{
//
// Find all the files
//
foreach (var sln in solutions) {
foreach (var projectFile in sln.ProjectFiles) {
var dir = Path.GetDirectoryName(projectFile);
var projectName = Path.GetFileNameWithoutExtension(projectFile);
var doc = XDocument.Load(projectFile);
var q = from x in doc.Descendants()
let e = x as XElement
where e != null
where e.Name.LocalName == "Compile"
where e.Attributes().Any(a => a.Name.LocalName == "Include")
select e.Attribute("Include").Value;
foreach (var inc in q) {
AddRef(Path.GetFullPath(Path.Combine(dir, inc)), sln);
}
}
}
//
// Get the lines of code
//
foreach (var f in _files.Values) {
try {
f.LinesOfCode = File.ReadAllLines(f.Path).Length;
}
catch (Exception) {
}
}
//
// Output
//
Console.WriteLine("app\tt\tu\ts\tu%\ts%");
foreach (var sln in solutions) {
Console.WriteLine("{0}\t{1}\t{2}\t{3}\t{4:p}\t{5:p}",
sln.Name,
sln.TotalLinesOfCode,
sln.UniqueLinesOfCode,
sln.SharedLinesOfCode,
sln.UniqueLinesOfCode / (double)sln.TotalLinesOfCode,
sln.SharedLinesOfCode / (double)sln.TotalLinesOfCode);
}
Console.WriteLine("DONE");
}
}
}
@Cheesebaron
Copy link

To make it work with shared projects. Instead of adding the shproj file use the projitem one instead. Then add:

const string SharedProjectPrefix = "$(MSBuildThisFileDirectory)";

and modify L128-130 to:

foreach (var inc in q) {
    var inc1 = inc;
    if (inc.StartsWith(SharedProjectPrefix)) {
        inc1 = inc.Remove(0, SharedProjectPrefix.Length);
    }
    AddRef(Path.GetFullPath(Path.Combine(dir, inc1)), sln);
}

Thanks!

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