Skip to content

Commit

Permalink
#367: Cobertura: Added support for cycolmatic complexity
Browse files Browse the repository at this point in the history
  • Loading branch information
danielpalme committed Aug 29, 2020
2 parents 2ffeaf0 + 246b6e2 commit 6cc5e3b
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 4 deletions.
1 change: 1 addition & 0 deletions src/Readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ CHANGELOG

4.6.5.0

* New: #367: Cobertura: Added support for cycolmatic complexity
* Fix: #363: Fixed OpenCover file handling (not unique tracked methods)
* Fix: #371: Fixed order of metrics

Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/Assembly.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,17 @@ public string ShortName
/// </value>
public int TotalCodeElements => this.classes.Sum(f => f.TotalCodeElements);

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Name;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/Branch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ internal Branch(int branchVisits, string identifier)
/// </summary>
public int BranchVisits { get; internal set; }

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.identifier;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/Class.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ internal Class(string name, Assembly assembly)
/// </value>
public int TotalCodeElements => this.files.Sum(f => f.TotalCodeElements);

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Name;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/CodeElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ internal CodeElement(string name, CodeElementType type, int firstLine, int lastL
/// <value>The coverage quota.</value>
public decimal? CoverageQuota { get; }

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Name;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/CodeFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,17 @@ public int CoveredCodeElements
}
}

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Path;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/FileAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ internal FileAnalysis(string path, string error)
/// <value>The lines.</value>
public IEnumerable<LineAnalysis> Lines => this.lineAnalysis;

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Path;
}

/// <summary>
/// Adds the given line analysis to the file analysis.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/MethodMetric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ public MethodMetric(string fullName, string shortName, IEnumerable<Metric> metri
/// </value>
public int? Line { get; internal set; }

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.ShortName;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/Metric.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,17 @@ public Metric(string name, Uri explanationUrl, MetricType metricType, decimal? v
/// </summary>
public decimal? Value { get; internal set; }

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return $"{this.Name}: {this.Value}";
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/ShortLineAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,16 @@ internal ShortLineAnalysis(int lineVisits, LineVisitStatus lineVisitStatus)
/// Gets the number of line visits.
/// </summary>
public int LineVisits { get; }

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return $"{this.LineVisitStatus}: {this.LineVisits}";
}
}
}
11 changes: 11 additions & 0 deletions src/ReportGenerator.Core/Parser/Analysis/TestMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,17 @@ internal TestMethod(string name, string shortName)
/// </value>
public long Id { get; }

/// <summary>
/// Returns a <see cref="string" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="string" /> that represents this instance.
/// </returns>
public override string ToString()
{
return this.Name;
}

/// <summary>
/// Determines whether the specified <see cref="object"/> is equal to this instance.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalys

foreach (var fileAnalysis in fileAnalyses)
{
decimal? fileComplexity = null;
var classElement = new XElement(
"class",
new XAttribute("name", @class.Name),
Expand Down Expand Up @@ -93,7 +94,29 @@ public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalys

methodElement.Add(new XAttribute("line-rate", methodLineRate.ToString(CultureInfo.InvariantCulture)));
methodElement.Add(new XAttribute("branch-rate", methodBranchRate.ToString(CultureInfo.InvariantCulture)));
methodElement.Add(new XAttribute("complexity", "NaN"));

var methodMetrics = file.MethodMetrics
.FirstOrDefault(q => q.ShortName == codeElement.Name
&& q.Line == codeElement.FirstLine);

if (methodMetrics != null)
{
var complexityMetric = methodMetrics.Metrics.FirstOrDefault(m => m.Name == ReportResources.CyclomaticComplexity);
if (complexityMetric != null && complexityMetric.Value.HasValue)
{
if (!fileComplexity.HasValue)
{
fileComplexity = 0;
}

fileComplexity += complexityMetric.Value.Value;
methodElement.Add(new XAttribute("complexity", complexityMetric.Value.Value.ToString(CultureInfo.InvariantCulture)));
}
}
else
{
methodElement.Add(new XAttribute("complexity", "NaN"));
}

methodsElement.Add(methodElement);
}
Expand All @@ -110,7 +133,7 @@ public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalys

classElement.Add(new XAttribute("line-rate", lineRate.ToString(CultureInfo.InvariantCulture)));
classElement.Add(new XAttribute("branch-rate", branchRate.ToString(CultureInfo.InvariantCulture)));
classElement.Add(new XAttribute("complexity", "NaN"));
classElement.Add(new XAttribute("complexity", fileComplexity.HasValue ? fileComplexity.Value.ToString(CultureInfo.InvariantCulture) : "NaN"));

classElement.Add(linesElement);

Expand All @@ -124,16 +147,49 @@ public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalys
/// <param name="summaryResult">The summary result.</param>
public void CreateSummaryReport(SummaryResult summaryResult)
{
decimal? summaryComplexity = null;

foreach (var assembly in summaryResult.Assemblies)
{
decimal? assemblyComplexity = null;
if (this.packageElementsByName.TryGetValue(assembly.Name, out XElement packageElement))
{
double packageLineRate = assembly.CoverableLines == 0 ? 1 : assembly.CoveredLines / (double)assembly.CoverableLines;
double packageBranchRate = assembly.TotalBranches.GetValueOrDefault() == 0 ? 1 : assembly.CoveredBranches.GetValueOrDefault() / (double)assembly.TotalBranches.GetValueOrDefault();

packageElement.Add(new XAttribute("line-rate", packageLineRate.ToString(CultureInfo.InvariantCulture)));
packageElement.Add(new XAttribute("branch-rate", packageBranchRate.ToString(CultureInfo.InvariantCulture)));
packageElement.Add(new XAttribute("complexity", "NaN"));

foreach (var @class in assembly.Classes)
{
foreach (var file in @class.Files)
{
foreach (var methodMetric in file.MethodMetrics)
{
var metric = methodMetric.Metrics.FirstOrDefault(m =>
m.Name == ReportResources.CyclomaticComplexity
&& m.Value.HasValue);

if (metric != null)
{
if (!assemblyComplexity.HasValue)
{
assemblyComplexity = 0;
}

if (!summaryComplexity.HasValue)
{
summaryComplexity = 0;
}

assemblyComplexity += metric.Value.Value;
summaryComplexity += metric.Value.Value;
}
}
}
}

packageElement.Add(new XAttribute("complexity", assemblyComplexity.HasValue ? assemblyComplexity.Value.ToString(CultureInfo.InvariantCulture) : "NaN"));
}
}

Expand All @@ -148,7 +204,7 @@ public void CreateSummaryReport(SummaryResult summaryResult)
rootElement.Add(new XAttribute("lines-valid", summaryResult.CoverableLines.ToString(CultureInfo.InvariantCulture)));
rootElement.Add(new XAttribute("branches-covered", summaryResult.CoveredBranches.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)));
rootElement.Add(new XAttribute("branches-valid", summaryResult.TotalBranches.GetValueOrDefault().ToString(CultureInfo.InvariantCulture)));
rootElement.Add(new XAttribute("complexity", "NaN"));
rootElement.Add(new XAttribute("complexity", summaryComplexity.HasValue ? summaryComplexity.Value.ToString(CultureInfo.InvariantCulture) : "NaN"));
rootElement.Add(new XAttribute("version", 0));
rootElement.Add(new XAttribute("timestamp", ((long)(DateTime.Now - new DateTime(1970, 1, 1)).TotalSeconds).ToString(CultureInfo.InvariantCulture)));

Expand Down

0 comments on commit 6cc5e3b

Please sign in to comment.