1
2
3
4
5 package mockit.coverage.reporting.lineCoverage;
6
7 import static java.lang.Character.isWhitespace;
8
9 import edu.umd.cs.findbugs.annotations.NonNull;
10 import edu.umd.cs.findbugs.annotations.Nullable;
11
12 import java.util.List;
13
14 import mockit.coverage.CallPoint;
15 import mockit.coverage.lines.BranchCoverageData;
16 import mockit.coverage.lines.LineCoverageData;
17 import mockit.coverage.lines.LineSegmentData;
18 import mockit.coverage.reporting.ListOfCallPoints;
19 import mockit.coverage.reporting.parsing.LineElement;
20 import mockit.coverage.reporting.parsing.LineParser;
21
22 import org.checkerframework.checker.index.qual.NonNegative;
23
24 final class LineSegmentsFormatter {
25 @Nullable
26 private final ListOfCallPoints listOfCallPoints;
27 @NonNull
28 private final StringBuilder formattedLine;
29
30
31 private int lineNumber;
32 @NonNegative
33 private int segmentIndex;
34 @Nullable
35 private LineElement element;
36
37 LineSegmentsFormatter(boolean withCallPoints, @NonNull StringBuilder formattedLine) {
38 listOfCallPoints = withCallPoints ? new ListOfCallPoints() : null;
39 this.formattedLine = formattedLine;
40 }
41
42 void formatSegments(@NonNull LineParser lineParser, @NonNull LineCoverageData lineData) {
43 lineNumber = lineParser.getNumber();
44
45 List<BranchCoverageData> branchData = lineData.getBranches();
46 int numSegments = lineData.getNumberOfSegments();
47
48 element = lineParser.getInitialElement().appendUntilNextCodeElement(formattedLine);
49
50 segmentIndex = 0;
51 appendUntilNextBranchingPoint(lineData);
52
53 while (element != null && segmentIndex < numSegments) {
54 LineSegmentData segmentData = segmentIndex == 0 ? lineData : branchData.get(segmentIndex - 1);
55 element = element.appendUntilNextCodeElement(formattedLine);
56 appendUntilNextBranchingPoint(segmentData);
57 }
58
59 if (element != null) {
60 element.appendAllBefore(formattedLine, null);
61 }
62
63 formattedLine.append("</pre>");
64
65 if (listOfCallPoints != null) {
66 formattedLine.append(listOfCallPoints.getContents());
67 }
68 }
69
70 private void appendUntilNextBranchingPoint(@NonNull LineSegmentData segmentData) {
71 if (element != null) {
72 LineElement firstElement = element;
73 element = element.findNextBranchingPoint();
74
75 appendToFormattedLine(segmentData, firstElement);
76
77 if (element != null && element.isBranchingElement()) {
78 formattedLine.append(element.getText());
79 element = element.getNext();
80 }
81 }
82 }
83
84 private void appendToFormattedLine(@NonNull LineSegmentData segmentData, @NonNull LineElement firstElement) {
85 if (firstElement != element) {
86 appendStartTag(segmentData);
87 firstElement.appendAllBefore(formattedLine, element);
88 appendEndTag(segmentData);
89
90 segmentIndex++;
91 }
92 }
93
94 private void appendStartTag(@NonNull LineSegmentData segmentData) {
95 formattedLine.append("<span id='l").append(lineNumber).append('s').append(segmentIndex);
96 formattedLine.append("' title='Executions: ").append(segmentData.getExecutionCount()).append("' ");
97
98 if (segmentData.isCovered()) {
99 if (segmentData.containsCallPoints()) {
100 formattedLine.append("class='cvd cp' onclick='sh(this,").append(segmentIndex).append(")'>");
101 } else {
102 formattedLine.append("class='cvd'>");
103 }
104 } else {
105 formattedLine.append("class='uncvd'>");
106 }
107 }
108
109 private void appendEndTag(@NonNull LineSegmentData segmentData) {
110 int i = formattedLine.length() - 1;
111
112 while (isWhitespace(formattedLine.charAt(i))) {
113 i--;
114 }
115
116 formattedLine.insert(i + 1, "</span>");
117
118 if (listOfCallPoints != null) {
119 List<CallPoint> callPoints = segmentData.getCallPoints();
120 listOfCallPoints.insertListOfCallPoints(callPoints);
121 }
122 }
123 }