forked from dafny-lang/dafny
-
Notifications
You must be signed in to change notification settings - Fork 0
/
CoverageReport.cs
79 lines (66 loc) · 2.81 KB
/
CoverageReport.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#nullable disable
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading;
namespace Microsoft.Dafny;
public class CoverageReport {
private static int nextUniqueId = 0;
private readonly Dictionary<Uri, List<CoverageSpan>> labelsByFile;
public readonly string Name; // the name to assign to this coverage report
public readonly string Units; // the units of coverage (plural). This will be written in the coverage report table.
private readonly string suffix; // user-provided suffix to add to filenames that are part of this report
private readonly int uniqueId = Interlocked.Increment(ref nextUniqueId);
public string UniqueSuffix => suffix + (uniqueId == 1 ? "" : ("_" + uniqueId));
/// <summary>
/// Generate a new empty coverage report for a given program.
/// If not null, scan the <param name="program"></param> for the list of files it consists of and populate the
/// labelsByFile dictionary. <param name="name"></param> is the title of the coverage report displayed in HTML files,
/// <param name="units"></param> are the units of coverage this report uses (to be displayed in the index HTML file),
/// <param name="suffix"></param> is the suffix to add to files that are part of this coverage report.
/// </summary>
public CoverageReport(string name, string units, string suffix, Program program) {
Name = name;
Units = units;
this.suffix = suffix;
labelsByFile = new();
if (program != null) {
RegisterFiles(program);
}
}
/// <summary>
/// Assign a coverage label to the code indicated by the <param name="span"></param> range token.
/// </summary>
public void LabelCode(RangeToken span, CoverageLabel label) {
Contract.Assert(labelsByFile.ContainsKey(span.Uri));
var labeledFile = labelsByFile[span.Uri];
var coverageSpan = new CoverageSpan(span, label);
labeledFile.Add(coverageSpan);
}
public IEnumerable<CoverageSpan> CoverageSpansForFile(Uri uri) {
return labelsByFile.GetOrDefault(uri, () => new List<CoverageSpan>());
}
public IEnumerable<Uri> AllFiles() {
return labelsByFile.Keys;
}
public void RegisterFiles(Program program) {
RegisterFiles(program.DefaultModuleDef);
}
public void RegisterFile(Uri uri) {
if (!labelsByFile.ContainsKey(uri)) {
labelsByFile[uri] = new List<CoverageSpan>();
}
}
private void RegisterFiles(Node astNode) {
if (astNode.StartToken.ActualFilename != null && !labelsByFile.ContainsKey(astNode.StartToken.Uri)) {
labelsByFile[astNode.StartToken.Uri] = new();
}
foreach (var declaration in astNode.Children.OfType<LiteralModuleDecl>()) {
RegisterFiles(declaration);
}
foreach (var declaration in astNode.Children.OfType<Declaration>()) {
RegisterFiles(declaration);
}
}
}