Skip to content

Commit 4d6e1d4

Browse files
committed
Refactor BranchInfo/LineInfo to use unique keys
A branch point now uses a (named) tuple as a key, to uniquely identify its location. As a downside, JIL cannot be used, since it doesn't support keys other than strings, integers or enums.
1 parent 3d86243 commit 4d6e1d4

File tree

14 files changed

+73
-101
lines changed

14 files changed

+73
-101
lines changed

src/coverlet.core/App.config

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<configuration>
3+
<runtime>
4+
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5+
<dependentAssembly>
6+
<assemblyIdentity name="Newtonsoft.Json" culture="Neutral" publicKeyToken="30ad4fe6b2a6aeed" />
7+
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="9.0.0.0" />
8+
</dependentAssembly>
9+
</assemblyBinding>
10+
</runtime>
11+
</configuration>

src/coverlet.core/Coverage.cs

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -66,81 +66,62 @@ public CoverageResult GetCoverageResult()
6666
{
6767
if (methods.TryGetValue(line.Method, out Method method))
6868
{
69-
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new LineInfo { Hits = line.Hits });
69+
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new HitInfo { Hits = line.Hits });
7070
}
7171
else
7272
{
7373
documents[doc.Path][line.Class].Add(line.Method, new Method());
74-
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new LineInfo { Hits = line.Hits });
74+
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new HitInfo { Hits = line.Hits });
7575
}
7676
}
7777
else
7878
{
7979
documents[doc.Path].Add(line.Class, new Methods());
8080
documents[doc.Path][line.Class].Add(line.Method, new Method());
81-
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new LineInfo { Hits = line.Hits });
81+
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new HitInfo { Hits = line.Hits });
8282
}
8383
}
8484
else
8585
{
8686
documents.Add(doc.Path, new Classes());
8787
documents[doc.Path].Add(line.Class, new Methods());
8888
documents[doc.Path][line.Class].Add(line.Method, new Method());
89-
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new LineInfo { Hits = line.Hits });
89+
documents[doc.Path][line.Class][line.Method].Lines.Add(line.Number, new HitInfo { Hits = line.Hits });
9090
}
9191
}
9292

9393
// Construct Branch Results
9494
foreach (var branch in doc.Branches)
9595
{
96+
var key = (branch.Number, branch.Offset, branch.EndOffset, branch.Path, branch.Ordinal);
97+
9698
if (documents.TryGetValue(doc.Path, out Classes classes))
9799
{
98100
if (classes.TryGetValue(branch.Class, out Methods methods))
99101
{
100102
if (methods.TryGetValue(branch.Method, out Method method))
101103
{
102-
if (method.Branches.TryGetValue(branch.Number, out List<BranchInfo> branchInfo))
103-
{
104-
documents[doc.Path][branch.Class][branch.Method].Branches[branch.Number].Add(new BranchInfo
105-
{ Hits = branch.Hits, Offset = branch.Offset, EndOffset = branch.EndOffset, Path = branch.Path, Ordinal = branch.Ordinal }
106-
);
107-
}
108-
else
109-
{
110-
documents[doc.Path][branch.Class][branch.Method].Branches.Add(branch.Number, new List<BranchInfo>());
111-
documents[doc.Path][branch.Class][branch.Method].Branches[branch.Number].Add(new BranchInfo
112-
{ Hits = branch.Hits, Offset = branch.Offset, EndOffset = branch.EndOffset, Path = branch.Path, Ordinal = branch.Ordinal }
113-
);
114-
}
104+
documents[doc.Path][branch.Class][branch.Method].Branches[key] = new HitInfo { Hits = branch.Hits };
115105
}
116106
else
117107
{
118108
documents[doc.Path][branch.Class].Add(branch.Method, new Method());
119-
documents[doc.Path][branch.Class][branch.Method].Branches.Add(branch.Number, new List<BranchInfo>());
120-
documents[doc.Path][branch.Class][branch.Method].Branches[branch.Number].Add(new BranchInfo
121-
{ Hits = branch.Hits, Offset = branch.Offset, EndOffset = branch.EndOffset, Path = branch.Path, Ordinal = branch.Ordinal }
122-
);
109+
documents[doc.Path][branch.Class][branch.Method].Branches[key] = new HitInfo { Hits = branch.Hits };
123110
}
124111
}
125112
else
126113
{
127114
documents[doc.Path].Add(branch.Class, new Methods());
128115
documents[doc.Path][branch.Class].Add(branch.Method, new Method());
129-
documents[doc.Path][branch.Class][branch.Method].Branches.Add(branch.Number, new List<BranchInfo>());
130-
documents[doc.Path][branch.Class][branch.Method].Branches[branch.Number].Add(new BranchInfo
131-
{ Hits = branch.Hits, Offset = branch.Offset, EndOffset = branch.EndOffset, Path = branch.Path, Ordinal = branch.Ordinal }
132-
);
116+
documents[doc.Path][branch.Class][branch.Method].Branches[key] = new HitInfo { Hits = branch.Hits };
133117
}
134118
}
135119
else
136120
{
137121
documents.Add(doc.Path, new Classes());
138122
documents[doc.Path].Add(branch.Class, new Methods());
139123
documents[doc.Path][branch.Class].Add(branch.Method, new Method());
140-
documents[doc.Path][branch.Class][branch.Method].Branches.Add(branch.Number, new List<BranchInfo>());
141-
documents[doc.Path][branch.Class][branch.Method].Branches[branch.Number].Add(new BranchInfo
142-
{ Hits = branch.Hits, Offset = branch.Offset, EndOffset = branch.EndOffset, Path = branch.Path, Ordinal = branch.Ordinal }
143-
);
124+
documents[doc.Path][branch.Class][branch.Method].Branches[key] = new HitInfo { Hits = branch.Hits };
144125
}
145126
}
146127
}

src/coverlet.core/CoverageResult.cs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,18 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.IO;
34

45
using Jil;
56

67
namespace Coverlet.Core
78
{
8-
public class LineInfo
9+
public class HitInfo
910
{
1011
public int Hits { get; set; }
1112
}
1213

13-
public class BranchInfo : LineInfo
14-
{
15-
public int Offset { get; set; }
16-
public int EndOffset { get; set; }
17-
public int Path { get; set; }
18-
public uint Ordinal { get; set; }
19-
}
20-
21-
public class Lines : SortedDictionary<int, LineInfo> { }
22-
public class Branches : SortedDictionary<int, List<BranchInfo>> { }
14+
public class Lines : SortedDictionary<int, HitInfo> { }
15+
public class Branches : SortedDictionary<(int Number, int Offset, int EndOffset, int Path, uint Ordinal), HitInfo> { }
2316
public class Method
2417
{
2518
internal Method()

src/coverlet.core/CoverageSummary.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,19 +62,19 @@ public CoverageDetails CalculateLineCoverage(Modules modules)
6262
return details;
6363
}
6464

65-
public CoverageDetails CalculateBranchCoverage(List<BranchInfo> branchInfo)
65+
public CoverageDetails CalculateBranchCoverage(List<KeyValuePair<(int Number, int Offset, int EndOffset, int Path, uint Ordinal), HitInfo>> branches)
6666
{
6767
var details = new CoverageDetails();
68-
details.Covered = branchInfo.Count(bi => bi.Hits > 0);
69-
details.Total = branchInfo.Count;
68+
details.Covered = branches.Count(kv => kv.Value.Hits > 0);
69+
details.Total = branches.Count;
7070
return details;
7171
}
7272

7373
public CoverageDetails CalculateBranchCoverage(Branches branches)
7474
{
7575
var details = new CoverageDetails();
76-
details.Covered = branches.Sum(b => b.Value.Where(bi => bi.Hits > 0).Count());
77-
details.Total = branches.Sum(b => b.Value.Count());
76+
details.Covered = branches.Count(kv => kv.Value.Hits > 0);
77+
details.Total = branches.Count;
7878
return details;
7979
}
8080

src/coverlet.core/Reporters/CoberturaReporter.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,18 @@ public string Report(CoverageResult result)
7272
foreach (var ln in meth.Value.Lines)
7373
{
7474
XElement line = new XElement("line");
75+
var branches = meth.Value.Branches.Where(kv => kv.Key.Number == ln.Key).ToList();
76+
7577
line.Add(new XAttribute("number", ln.Key.ToString()));
7678
line.Add(new XAttribute("hits", ln.Value.Hits.ToString()));
77-
line.Add(new XAttribute("branch", meth.Value.Branches.ContainsKey(ln.Key).ToString()));
79+
line.Add(new XAttribute("branch", branches.Any().ToString()));
7880

79-
if (meth.Value.Branches.TryGetValue(ln.Key, out List<BranchInfo> branches))
81+
if (branches.Any())
8082
{
8183
var branchInfoCoverage = summary.CalculateBranchCoverage(branches);
8284
line.Add(new XAttribute("condition-coverage", $"{branchInfoCoverage.Percent*100}% ({branchInfoCoverage.Covered}/{branchInfoCoverage.Total})"));
8385
XElement conditions = new XElement("conditions");
84-
var byOffset = branches.GroupBy(b => b.Offset).ToDictionary(b => b.Key, b => b.ToList());
86+
var byOffset = branches.GroupBy(kv => kv.Key.Offset).ToDictionary(b => b.Key, b => b.ToList());
8587
foreach (var entry in byOffset)
8688
{
8789
XElement condition = new XElement("condition");
Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.IO;
2-
using Jil;
1+
using Newtonsoft.Json;
32

43
namespace Coverlet.Core.Reporters
54
{
@@ -11,11 +10,7 @@ public class JsonReporter : IReporter
1110

1211
public string Report(CoverageResult result)
1312
{
14-
using (var writer = new StringWriter())
15-
{
16-
JSON.Serialize(result.Modules, writer, Options.PrettyPrint);
17-
return writer.ToString();
18-
}
13+
return JsonConvert.SerializeObject(result.Modules, Formatting.Indented);
1914
}
2015
}
2116
}

src/coverlet.core/Reporters/LcovReporter.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,9 @@ public string Report(CoverageResult result)
3838
foreach (var line in method.Value.Lines)
3939
lcov.Add($"DA:{line.Key},{line.Value.Hits}");
4040

41-
foreach (var branchs in method.Value.Branches)
41+
foreach (var branch in method.Value.Branches)
4242
{
43-
foreach (var branch in branchs.Value)
44-
lcov.Add($"BRDA:{branchs.Key},{branch.Offset},{branch.Path},{branch.Hits}");
43+
lcov.Add($"BRDA:{branch.Key},{branch.Key.Offset},{branch.Key.Path},{branch.Value.Hits}");
4544
}
4645
}
4746
}

src/coverlet.core/Reporters/OpenCoverReporter.cs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,20 +133,17 @@ public string Report(CoverageResult result)
133133

134134
foreach (var branches in meth.Value.Branches)
135135
{
136-
foreach (var branch in branches.Value)
137-
{
138-
XElement branchPoint = new XElement("BranchPoint");
139-
branchPoint.Add(new XAttribute("vc", branch.Hits.ToString()));
140-
branchPoint.Add(new XAttribute("upsid", branches.Key.ToString()));
141-
branchPoint.Add(new XAttribute("ordinal", branch.Ordinal.ToString()));
142-
branchPoint.Add(new XAttribute("path", branch.Path.ToString()));
143-
branchPoint.Add(new XAttribute("offset", branch.Offset.ToString()));
144-
branchPoint.Add(new XAttribute("offsetend", branch.EndOffset.ToString()));
145-
branchPoint.Add(new XAttribute("sl", branches.Key.ToString()));
146-
branchPoint.Add(new XAttribute("fileid", i.ToString()));
147-
branchPoints.Add(branchPoint);
148-
kBr++;
149-
}
136+
XElement branchPoint = new XElement("BranchPoint");
137+
branchPoint.Add(new XAttribute("vc", branches.Value.Hits.ToString()));
138+
branchPoint.Add(new XAttribute("upsid", branches.Key.Number.ToString()));
139+
branchPoint.Add(new XAttribute("ordinal", branches.Key.Ordinal.ToString()));
140+
branchPoint.Add(new XAttribute("path", branches.Key.Path.ToString()));
141+
branchPoint.Add(new XAttribute("offset", branches.Key.Offset.ToString()));
142+
branchPoint.Add(new XAttribute("offsetend", branches.Key.EndOffset.ToString()));
143+
branchPoint.Add(new XAttribute("sl", branches.Key.Number.ToString()));
144+
branchPoint.Add(new XAttribute("fileid", i.ToString()));
145+
branchPoints.Add(branchPoint);
146+
kBr++;
150147
}
151148

152149
numMethods++;

src/coverlet.core/coverlet.core.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<AssemblyVersion>2.0.1</AssemblyVersion>
66
</PropertyGroup>
77

88
<ItemGroup>
9-
<PackageReference Include="Jil" Version="2.15.4" />
109
<PackageReference Include="Mono.Cecil" Version="0.10.0" />
10+
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
1111
<PackageReference Include="System.Reflection.Metadata" Version="1.5.0" />
1212
<PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="2.0.1" />
1313
</ItemGroup>

test/coverlet.core.tests/CoverageSummaryTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ public class CoverageSummaryTests
1515
public CoverageSummaryTests()
1616
{
1717
Lines lines = new Lines();
18-
lines.Add(1, new LineInfo { Hits = 1 });
19-
lines.Add(2, new LineInfo { Hits = 0 });
18+
lines.Add(1, new HitInfo { Hits = 1 });
19+
lines.Add(2, new HitInfo { Hits = 0 });
2020
Branches branches = new Branches();
21-
branches.Add(1, new List<BranchInfo>());
22-
branches[1].Add(new BranchInfo { Hits = 1, Offset = 1, Path = 0, Ordinal = 1 });
23-
branches[1].Add(new BranchInfo { Hits = 1, Offset = 1, Path = 1, Ordinal = 2 });
21+
22+
branches[(Number: 1, Offset: 1, EndOffset: 1, Path: 0, Ordinal: 1)] = new HitInfo { Hits = 1 };
23+
branches[(Number: 2, Offset: 1, EndOffset: 1, Path: 0, Ordinal: 2)] = new HitInfo { Hits = 1 };
2424

2525
Methods methods = new Methods();
2626
var methodString = "System.Void Coverlet.Core.Tests.CoverageSummaryTests::TestCalculateSummary()";

0 commit comments

Comments
 (0)