Skip to content

Commit 6cc5e3b

Browse files
committed
#367: Cobertura: Added support for cycolmatic complexity
2 parents 2ffeaf0 + 246b6e2 commit 6cc5e3b

File tree

12 files changed

+171
-4
lines changed

12 files changed

+171
-4
lines changed

src/Readme.txt

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ CHANGELOG
6565

6666
4.6.5.0
6767

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

src/ReportGenerator.Core/Parser/Analysis/Assembly.cs

+11
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,17 @@ public string ShortName
109109
/// </value>
110110
public int TotalCodeElements => this.classes.Sum(f => f.TotalCodeElements);
111111

112+
/// <summary>
113+
/// Returns a <see cref="string" /> that represents this instance.
114+
/// </summary>
115+
/// <returns>
116+
/// A <see cref="string" /> that represents this instance.
117+
/// </returns>
118+
public override string ToString()
119+
{
120+
return this.Name;
121+
}
122+
112123
/// <summary>
113124
/// Determines whether the specified <see cref="object"/> is equal to this instance.
114125
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/Branch.cs

+11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ internal Branch(int branchVisits, string identifier)
2626
/// </summary>
2727
public int BranchVisits { get; internal set; }
2828

29+
/// <summary>
30+
/// Returns a <see cref="string" /> that represents this instance.
31+
/// </summary>
32+
/// <returns>
33+
/// A <see cref="string" /> that represents this instance.
34+
/// </returns>
35+
public override string ToString()
36+
{
37+
return this.identifier;
38+
}
39+
2940
/// <summary>
3041
/// Determines whether the specified <see cref="object"/> is equal to this instance.
3142
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/Class.cs

+11
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,17 @@ public decimal? CoverageQuota
149149
/// </value>
150150
public int TotalCodeElements => this.files.Sum(f => f.TotalCodeElements);
151151

152+
/// <summary>
153+
/// Returns a <see cref="string" /> that represents this instance.
154+
/// </summary>
155+
/// <returns>
156+
/// A <see cref="string" /> that represents this instance.
157+
/// </returns>
158+
public override string ToString()
159+
{
160+
return this.Name;
161+
}
162+
152163
/// <summary>
153164
/// Determines whether the specified <see cref="object"/> is equal to this instance.
154165
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/CodeElement.cs

+11
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ internal CodeElement(string name, CodeElementType type, int firstLine, int lastL
6565
/// <value>The coverage quota.</value>
6666
public decimal? CoverageQuota { get; }
6767

68+
/// <summary>
69+
/// Returns a <see cref="string" /> that represents this instance.
70+
/// </summary>
71+
/// <returns>
72+
/// A <see cref="string" /> that represents this instance.
73+
/// </returns>
74+
public override string ToString()
75+
{
76+
return this.Name;
77+
}
78+
6879
/// <summary>
6980
/// Determines whether the specified <see cref="object"/> is equal to this instance.
7081
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/CodeFile.cs

+11
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,17 @@ public int? TotalBranches
215215
}
216216
}
217217

218+
/// <summary>
219+
/// Returns a <see cref="string" /> that represents this instance.
220+
/// </summary>
221+
/// <returns>
222+
/// A <see cref="string" /> that represents this instance.
223+
/// </returns>
224+
public override string ToString()
225+
{
226+
return this.Path;
227+
}
228+
218229
/// <summary>
219230
/// Determines whether the specified <see cref="object"/> is equal to this instance.
220231
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/FileAnalysis.cs

+11
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ internal FileAnalysis(string path, string error)
5050
/// <value>The lines.</value>
5151
public IEnumerable<LineAnalysis> Lines => this.lineAnalysis;
5252

53+
/// <summary>
54+
/// Returns a <see cref="string" /> that represents this instance.
55+
/// </summary>
56+
/// <returns>
57+
/// A <see cref="string" /> that represents this instance.
58+
/// </returns>
59+
public override string ToString()
60+
{
61+
return this.Path;
62+
}
63+
5364
/// <summary>
5465
/// Adds the given line analysis to the file analysis.
5566
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/MethodMetric.cs

+11
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ public MethodMetric(string fullName, string shortName, IEnumerable<Metric> metri
5050
/// </value>
5151
public int? Line { get; internal set; }
5252

53+
/// <summary>
54+
/// Returns a <see cref="string" /> that represents this instance.
55+
/// </summary>
56+
/// <returns>
57+
/// A <see cref="string" /> that represents this instance.
58+
/// </returns>
59+
public override string ToString()
60+
{
61+
return this.ShortName;
62+
}
63+
5364
/// <summary>
5465
/// Determines whether the specified <see cref="object"/> is equal to this instance.
5566
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/Metric.cs

+11
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ public Metric(string name, Uri explanationUrl, MetricType metricType, decimal? v
6060
/// </summary>
6161
public decimal? Value { get; internal set; }
6262

63+
/// <summary>
64+
/// Returns a <see cref="string" /> that represents this instance.
65+
/// </summary>
66+
/// <returns>
67+
/// A <see cref="string" /> that represents this instance.
68+
/// </returns>
69+
public override string ToString()
70+
{
71+
return $"{this.Name}: {this.Value}";
72+
}
73+
6374
/// <summary>
6475
/// Determines whether the specified <see cref="object"/> is equal to this instance.
6576
/// </summary>

src/ReportGenerator.Core/Parser/Analysis/ShortLineAnalysis.cs

+11
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,16 @@ internal ShortLineAnalysis(int lineVisits, LineVisitStatus lineVisitStatus)
2525
/// Gets the number of line visits.
2626
/// </summary>
2727
public int LineVisits { get; }
28+
29+
/// <summary>
30+
/// Returns a <see cref="string" /> that represents this instance.
31+
/// </summary>
32+
/// <returns>
33+
/// A <see cref="string" /> that represents this instance.
34+
/// </returns>
35+
public override string ToString()
36+
{
37+
return $"{this.LineVisitStatus}: {this.LineVisits}";
38+
}
2839
}
2940
}

src/ReportGenerator.Core/Parser/Analysis/TestMethod.cs

+11
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ internal TestMethod(string name, string shortName)
4949
/// </value>
5050
public long Id { get; }
5151

52+
/// <summary>
53+
/// Returns a <see cref="string" /> that represents this instance.
54+
/// </summary>
55+
/// <returns>
56+
/// A <see cref="string" /> that represents this instance.
57+
/// </returns>
58+
public override string ToString()
59+
{
60+
return this.Name;
61+
}
62+
5263
/// <summary>
5364
/// Determines whether the specified <see cref="object"/> is equal to this instance.
5465
/// </summary>

src/ReportGenerator.Core/Reporting/Builders/CoberturaReportBuilder.cs

+60-4
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalys
6262

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

9495
methodElement.Add(new XAttribute("line-rate", methodLineRate.ToString(CultureInfo.InvariantCulture)));
9596
methodElement.Add(new XAttribute("branch-rate", methodBranchRate.ToString(CultureInfo.InvariantCulture)));
96-
methodElement.Add(new XAttribute("complexity", "NaN"));
97+
98+
var methodMetrics = file.MethodMetrics
99+
.FirstOrDefault(q => q.ShortName == codeElement.Name
100+
&& q.Line == codeElement.FirstLine);
101+
102+
if (methodMetrics != null)
103+
{
104+
var complexityMetric = methodMetrics.Metrics.FirstOrDefault(m => m.Name == ReportResources.CyclomaticComplexity);
105+
if (complexityMetric != null && complexityMetric.Value.HasValue)
106+
{
107+
if (!fileComplexity.HasValue)
108+
{
109+
fileComplexity = 0;
110+
}
111+
112+
fileComplexity += complexityMetric.Value.Value;
113+
methodElement.Add(new XAttribute("complexity", complexityMetric.Value.Value.ToString(CultureInfo.InvariantCulture)));
114+
}
115+
}
116+
else
117+
{
118+
methodElement.Add(new XAttribute("complexity", "NaN"));
119+
}
97120

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

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

115138
classElement.Add(linesElement);
116139

@@ -124,16 +147,49 @@ public void CreateClassReport(Class @class, IEnumerable<FileAnalysis> fileAnalys
124147
/// <param name="summaryResult">The summary result.</param>
125148
public void CreateSummaryReport(SummaryResult summaryResult)
126149
{
150+
decimal? summaryComplexity = null;
151+
127152
foreach (var assembly in summaryResult.Assemblies)
128153
{
154+
decimal? assemblyComplexity = null;
129155
if (this.packageElementsByName.TryGetValue(assembly.Name, out XElement packageElement))
130156
{
131157
double packageLineRate = assembly.CoverableLines == 0 ? 1 : assembly.CoveredLines / (double)assembly.CoverableLines;
132158
double packageBranchRate = assembly.TotalBranches.GetValueOrDefault() == 0 ? 1 : assembly.CoveredBranches.GetValueOrDefault() / (double)assembly.TotalBranches.GetValueOrDefault();
133159

134160
packageElement.Add(new XAttribute("line-rate", packageLineRate.ToString(CultureInfo.InvariantCulture)));
135161
packageElement.Add(new XAttribute("branch-rate", packageBranchRate.ToString(CultureInfo.InvariantCulture)));
136-
packageElement.Add(new XAttribute("complexity", "NaN"));
162+
163+
foreach (var @class in assembly.Classes)
164+
{
165+
foreach (var file in @class.Files)
166+
{
167+
foreach (var methodMetric in file.MethodMetrics)
168+
{
169+
var metric = methodMetric.Metrics.FirstOrDefault(m =>
170+
m.Name == ReportResources.CyclomaticComplexity
171+
&& m.Value.HasValue);
172+
173+
if (metric != null)
174+
{
175+
if (!assemblyComplexity.HasValue)
176+
{
177+
assemblyComplexity = 0;
178+
}
179+
180+
if (!summaryComplexity.HasValue)
181+
{
182+
summaryComplexity = 0;
183+
}
184+
185+
assemblyComplexity += metric.Value.Value;
186+
summaryComplexity += metric.Value.Value;
187+
}
188+
}
189+
}
190+
}
191+
192+
packageElement.Add(new XAttribute("complexity", assemblyComplexity.HasValue ? assemblyComplexity.Value.ToString(CultureInfo.InvariantCulture) : "NaN"));
137193
}
138194
}
139195

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

0 commit comments

Comments
 (0)