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