View Javadoc
1   /*
2    * Copyright (c) 2006 JMockit developers
3    * This file is subject to the terms of the MIT license (see LICENSE.txt).
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      // Helper fields:
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 }