View Javadoc
1   /*
2    * MIT License
3    * Copyright (c) 2006-2025 JMockit developers
4    * See LICENSE file for full license text.
5    */
6   package mockit.coverage.reporting.dataCoverage;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import mockit.coverage.dataItems.FieldData;
12  import mockit.coverage.dataItems.InstanceFieldData;
13  import mockit.coverage.dataItems.PerFileDataCoverage;
14  import mockit.coverage.dataItems.StaticFieldData;
15  import mockit.coverage.reporting.parsing.FileParser;
16  import mockit.coverage.reporting.parsing.LineElement;
17  
18  import org.checkerframework.checker.index.qual.NonNegative;
19  
20  public final class DataCoverageOutput {
21      @NonNull
22      private final StringBuilder openingTag;
23      @NonNull
24      private final PerFileDataCoverage coverageInfo;
25      @NonNegative
26      private int nextField;
27      @Nullable
28      private String classAndFieldNames;
29      @Nullable
30      private String className;
31      @Nullable
32      private String fieldName;
33  
34      public DataCoverageOutput(@NonNull PerFileDataCoverage coverageInfo) {
35          openingTag = new StringBuilder(50);
36          this.coverageInfo = coverageInfo;
37          moveToNextField();
38      }
39  
40      private void moveToNextField() {
41          if (nextField >= coverageInfo.allFields.size()) {
42              classAndFieldNames = null;
43              className = null;
44              fieldName = null;
45              return;
46          }
47  
48          classAndFieldNames = coverageInfo.allFields.get(nextField);
49          nextField++;
50  
51          int p = classAndFieldNames.indexOf('.');
52          className = classAndFieldNames.substring(0, p);
53          fieldName = classAndFieldNames.substring(p + 1);
54      }
55  
56      public void writeCoverageInfoIfLineStartsANewFieldDeclaration(@NonNull FileParser fileParser) {
57          if (classAndFieldNames != null) {
58              assert className != null;
59  
60              if (className.equals(fileParser.getCurrentlyPendingClass())) {
61                  LineElement initialLineElement = fileParser.lineParser.getInitialElement();
62  
63                  assert fieldName != null;
64                  LineElement elementWithFieldName = initialLineElement.findWord(fieldName);
65  
66                  if (elementWithFieldName != null) {
67                      buildOpeningTagForFieldWrapper();
68                      elementWithFieldName.wrapText(openingTag.toString(), "</span>");
69                      moveToNextField();
70                  }
71              }
72          }
73      }
74  
75      private void buildOpeningTagForFieldWrapper() {
76          openingTag.setLength(0);
77          openingTag.append("<span class='");
78  
79          assert classAndFieldNames != null;
80          StaticFieldData staticData = coverageInfo.getStaticFieldData(classAndFieldNames);
81          boolean staticField = staticData != null;
82          openingTag.append(staticField ? "static" : "instance");
83  
84          openingTag.append(coverageInfo.isCovered(classAndFieldNames) ? " cvd" : " uncvd");
85  
86          InstanceFieldData instanceData = coverageInfo.getInstanceFieldData(classAndFieldNames);
87  
88          if (staticField || instanceData != null) {
89              openingTag.append("' title='");
90              appendAccessCounts(staticField ? staticData : instanceData);
91          }
92  
93          openingTag.append("'>");
94      }
95  
96      private void appendAccessCounts(@NonNull FieldData fieldData) {
97          openingTag.append("Reads: ").append(fieldData.getReadCount());
98          openingTag.append(" Writes: ").append(fieldData.getWriteCount());
99      }
100 }