Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CodeLineCounter/Models/DuplicationCode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace CodeLineCounter.Models
{
public class DuplicationCode
{
public string? CodeHash { get; set; }
public required string FilePath { get; set; }
public string? MethodName { get; set; }
public int StartLine { get; set; }
public int NbLines { get; set; }
}
}

7 changes: 3 additions & 4 deletions CodeLineCounter/Program.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
using CodeLineCounter.Services;
using CodeLineCounter.Utils;
using CodeLineCounter.Models;
using System.Diagnostics;
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;

namespace CodeLineCounter
{
Expand Down Expand Up @@ -31,10 +33,8 @@ static void Main(string[] args)

var solutionPath = Path.GetFullPath(solutionFiles[choice - 1]);
AnalyzeAndExportSolution(solutionPath, settings.Verbose);

}
}

}

private static void AnalyzeAndExportSolution(string solutionPath, bool verbose)
Expand All @@ -49,7 +49,7 @@ private static void AnalyzeAndExportSolution(string solutionPath, bool verbose)
timer.Stop();
TimeSpan timeTaken = timer.Elapsed;
string processingTime = $"Time taken: {timeTaken:m\\:ss\\.fff}";
var nbLinesDuplicated = duplicationMap.Sum(x => x.Value.Count);
var nbLinesDuplicated = duplicationMap.Sum(x => x.NbLines);
var percentageDuplication = (nbLinesDuplicated / (double)totalLines) * 100;

if (verbose)
Expand Down Expand Up @@ -78,6 +78,5 @@ private static void AnalyzeAndExportSolution(string solutionPath, bool verbose)
Console.WriteLine($"The code duplications have been exported to {duplicationCsvFilePath}");
Console.WriteLine(processingTime);
}

}
}
6 changes: 3 additions & 3 deletions CodeLineCounter/Services/CodeAnalyzer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace CodeLineCounter.Services
{
public static class CodeAnalyzer
{
public static (List<NamespaceMetrics>, Dictionary<string, int>, int, int, Dictionary<string, List<(string filePath, string methodName, int startLine, int nbLines)>>) AnalyzeSolution(string solutionFilePath)
public static (List<NamespaceMetrics>, Dictionary<string, int>, int, int, List<DuplicationCode>) AnalyzeSolution(string solutionFilePath)
{
string solutionDirectory = Path.GetDirectoryName(solutionFilePath) ?? string.Empty;
var projectFiles = FileUtils.GetProjectFiles(solutionFilePath);
Expand All @@ -23,14 +23,14 @@ public static (List<NamespaceMetrics>, Dictionary<string, int>, int, int, Dictio
foreach (var projectFile in projectFiles)
{
AnalyzeProject(solutionDirectory, projectFile, ref totalFilesAnalyzed, ref totalLines, namespaceMetrics, projectTotals);

}

codeDuplicationChecker.DetectCodeDuplicationInFiles(FileUtils.GetAllCsFiles(solutionDirectory));

var duplicationMap = codeDuplicationChecker.GetCodeDuplicationMap();
var duplicationList = duplicationMap.Values.SelectMany(v => v).ToList();

return (namespaceMetrics, projectTotals, totalLines, totalFilesAnalyzed, duplicationMap);
return (namespaceMetrics, projectTotals, totalLines, totalFilesAnalyzed, duplicationList);
}

private static void AnalyzeProject(string solutionDirectory, string projectFile, ref int totalFilesAnalyzed, ref int totalLines, List<NamespaceMetrics> namespaceMetrics, Dictionary<string, int> projectTotals)
Expand Down
40 changes: 23 additions & 17 deletions CodeLineCounter/Services/CodeDuplicationChecker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using CodeLineCounter.Models;
using CodeLineCounter.Utils;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -15,14 +16,14 @@ namespace CodeLineCounter.Services
{
public class CodeDuplicationChecker
{
private readonly ConcurrentDictionary<string, HashSet<(string filePath, string methodName, int startLine, int nbLines)>> duplicationMap;
private readonly ConcurrentDictionary<string, HashSet<(string filePath, string methodName, int startLine, int nbLines)>> hashMap;
private readonly ConcurrentDictionary<string, HashSet<DuplicationCode>> duplicationMap;
private readonly ConcurrentDictionary<string, HashSet<DuplicationCode>> hashMap;
private readonly object duplicationLock = new object();

public CodeDuplicationChecker()
{
duplicationMap = new ConcurrentDictionary<string, HashSet<(string filePath, string methodName, int startLine, int nbLines)>>();
hashMap = new ConcurrentDictionary<string, HashSet<(string filePath, string methodName, int startLine, int nbLines)>>();
duplicationMap = new ConcurrentDictionary<string, HashSet<DuplicationCode>>();
hashMap = new ConcurrentDictionary<string, HashSet<DuplicationCode>>();
}

public void DetectCodeDuplicationInFiles(List<string> files)
Expand Down Expand Up @@ -53,19 +54,24 @@ public void DetectCodeDuplicationInSourceCode(string normalizedPath, string sour
var location = block.GetLocation().GetLineSpan().StartLinePosition.Line;
var nbLines = block.GetLocation().GetLineSpan().EndLinePosition.Line - location + 1;

hashMap.AddOrUpdate(hash, new HashSet<(string filePath, string methodName, int startLine, int nbLines)>
var duplicationCode = new DuplicationCode
{
(normalizedPath, method.Identifier.Text, location, nbLines)
},
(key, set) =>
{
lock (set)
{
set.Add((normalizedPath, method.Identifier.Text, location, nbLines));
}
return set;
});
CodeHash = hash,
FilePath = normalizedPath,
MethodName = method.Identifier.Text,
StartLine = location,
NbLines = nbLines
};

hashMap.AddOrUpdate(hash, new HashSet<DuplicationCode> { duplicationCode },
(key, set) =>
{
lock (set)
{
set.Add(duplicationCode);
}
return set;
});
}
});

Expand All @@ -86,7 +92,7 @@ private void UpdateDuplicationMap()
}
}

public Dictionary<string, List<(string filePath, string methodName, int startLine, int nbLines)>> GetCodeDuplicationMap()
public Dictionary<string, List<DuplicationCode>> GetCodeDuplicationMap()
{
return duplicationMap.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToList());
}
Expand All @@ -109,4 +115,4 @@ private static string NormalizeCode(string code)
return stringBuilder.ToString();
}
}
}
}
45 changes: 19 additions & 26 deletions CodeLineCounter/Utils/CsvExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ namespace CodeLineCounter.Utils
{
public static class CsvExporter
{

public static void ExportToCsv(string filePath, List<NamespaceMetrics> metrics, Dictionary<string, int> projectTotals, int totalLines, Dictionary<string, List<(string filePath, string methodName, int startLine, int nbLines)>> duplicationMap, string? solutionPath)
public static void ExportToCsv(string filePath, List<NamespaceMetrics> metrics, Dictionary<string, int> projectTotals, int totalLines, List<DuplicationCode> duplications, string? solutionPath)
{
var csvBuilder = new StringBuilder();
csvBuilder.AppendLine("Project,ProjectPath,Namespace,FileName,FilePath,LineCount,CyclomaticComplexity,CodeDuplications");

string? currentProject = null;
var duplicationCounts = GetDuplicationCounts(duplicationMap);

var duplicationCounts = GetDuplicationCounts(duplications);

foreach (var metric in metrics)
{
Expand Down Expand Up @@ -48,41 +46,35 @@ public static void AppendProjectLineToCsv(Dictionary<string, int> projectTotals,
}
}

public static void ExportCodeDuplicationsToCsv(string filePath, Dictionary<string, List<(string filePath, string methodName, int startLine, int nbLines)>> duplicationMap, string? solutionPath)
public static void ExportCodeDuplicationsToCsv(string filePath, List<DuplicationCode> duplications, string? solutionPath)
{
var csvBuilder = new StringBuilder();
csvBuilder.AppendLine("Code Hash,FilePath,MethodName,StartLine, nbLines");

foreach (var entry in duplicationMap)
foreach (var detail in duplications)
{
foreach (var detail in entry.Value)
{
csvBuilder.AppendLine($"{entry.Key},{detail.filePath},{detail.methodName},{detail.startLine}, {detail.nbLines}");
}
csvBuilder.AppendLine($"{detail.CodeHash},{detail.FilePath},{detail.MethodName},{detail.StartLine},{detail.NbLines}");
}

File.WriteAllText(filePath, csvBuilder.ToString());

csvBuilder.Clear();
}

public static Dictionary<string, int> GetDuplicationCounts(Dictionary<string, List<(string filePath, string methodName, int startLine, int nbLines)>> duplicationMap)
public static Dictionary<string, int> GetDuplicationCounts(List<DuplicationCode> duplications)
{
var duplicationCounts = new Dictionary<string, int>();

foreach (var entry in duplicationMap)
foreach (var duplication in duplications)
{
foreach (var (filePath, methodName, startLine, nbLines) in entry.Value)
var normalizedPath = Path.GetFullPath(duplication.FilePath);
if (duplicationCounts.TryGetValue(normalizedPath, out int count))
{
var normalizedPath = Path.GetFullPath(filePath);
if (duplicationCounts.TryGetValue(normalizedPath, out int count))
{
duplicationCounts[normalizedPath] = count +1;
}
else
{
duplicationCounts[normalizedPath] = 1;
}
duplicationCounts[normalizedPath] = count + 1;
}
else
{
duplicationCounts[normalizedPath] = 1;
}
}

Expand All @@ -92,14 +84,15 @@ public static Dictionary<string, int> GetDuplicationCounts(Dictionary<string, Li
public static int GetFileDuplicationsCount(Dictionary<string, int> duplicationCounts, NamespaceMetrics metric, string? solutionPath)
{
int count = 0;
if (solutionPath == null) {
solutionPath = Path.GetFullPath(".");
if (solutionPath == null)
{
solutionPath = Path.GetFullPath(".");
}
else
{
solutionPath = Path.GetDirectoryName(solutionPath);
}
if (metric.FilePath !=null && solutionPath != null)
if (metric.FilePath != null && solutionPath != null)
{
var normalizedPath = solutionPath != string.Empty ? Path.GetFullPath(metric.FilePath, solutionPath) : Path.GetFullPath(metric.FilePath);
if (duplicationCounts.TryGetValue(normalizedPath, out int countValue))
Expand All @@ -111,7 +104,7 @@ public static int GetFileDuplicationsCount(Dictionary<string, int> duplicationCo
count = 0;
}
}

return count;
}
}
Expand Down