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.packages;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import java.io.PrintWriter;
12  import java.util.Arrays;
13  import java.util.Collection;
14  import java.util.List;
15  import java.util.Map;
16  
17  import mockit.coverage.data.FileCoverageData;
18  
19  import org.checkerframework.checker.index.qual.NonNegative;
20  
21  final class PackageCoverageReport extends ListWithFilesAndPercentages {
22      @NonNull
23      private final Map<String, FileCoverageData> filesToFileData;
24      @Nullable
25      private final Collection<String> sourceFilesNotFound;
26      @NonNull
27      private final char[] fileNameWithSpaces;
28  
29      PackageCoverageReport(@NonNull PrintWriter output, @Nullable Collection<String> sourceFilesNotFound,
30              @NonNull Map<String, FileCoverageData> filesToFileData,
31              @NonNull Collection<List<String>> allSourceFileNames) {
32          super(output, "          ");
33          this.sourceFilesNotFound = sourceFilesNotFound;
34          this.filesToFileData = filesToFileData;
35          fileNameWithSpaces = new char[maximumSourceFileNameLength(allSourceFileNames)];
36      }
37  
38      @NonNegative
39      private static int maximumSourceFileNameLength(@NonNull Collection<List<String>> allSourceFileNames) {
40          int maxLength = 0;
41  
42          for (List<String> files : allSourceFileNames) {
43              for (String fileName : files) {
44                  int n = fileName.length();
45  
46                  if (n > maxLength) {
47                      maxLength = n;
48                  }
49              }
50          }
51  
52          return maxLength;
53      }
54  
55      @Override
56      protected void writeMetricsForFile(@Nullable String packageName, @NonNull String fileName) {
57          String filePath = packageName == null || packageName.isEmpty() ? fileName : packageName + '/' + fileName;
58          FileCoverageData fileData = filesToFileData.get(filePath);
59  
60          writeRowStart();
61          printIndent();
62          output.write("  <td class='");
63          output.write(fileData.kindOfTopLevelType != null ? fileData.kindOfTopLevelType : "cls");
64          output.write("'>");
65  
66          int fileNameLength = buildFileNameWithTrailingSpaces(fileName);
67          writeTableCellWithFileName(filePath, fileNameLength);
68          writeCodeCoverageMetricForFile(fileData);
69          writeRowClose();
70      }
71  
72      @NonNegative
73      private int buildFileNameWithTrailingSpaces(@NonNull String fileName) {
74          int n = fileName.length();
75  
76          fileName.getChars(0, n, fileNameWithSpaces, 0);
77          Arrays.fill(fileNameWithSpaces, n, fileNameWithSpaces.length, ' ');
78  
79          return n;
80      }
81  
82      private void writeTableCellWithFileName(@NonNull String filePath, @NonNegative int fileNameLen) {
83          if (sourceFilesNotFound == null || sourceFilesNotFound.contains(filePath)) {
84              output.write(fileNameWithSpaces);
85          } else {
86              output.write("<a href='");
87              int p = filePath.lastIndexOf('.');
88              output.write(filePath.substring(0, p));
89              output.write(".html'>");
90              output.write(fileNameWithSpaces, 0, fileNameLen);
91              output.write("</a>");
92              output.write(fileNameWithSpaces, fileNameLen, fileNameWithSpaces.length - fileNameLen);
93          }
94  
95          output.println("</td>");
96      }
97  
98      private void writeCodeCoverageMetricForFile(@NonNull FileCoverageData coverageInfo) {
99          int percentage = coverageInfo.getCoveragePercentage();
100         int covered = coverageInfo.getCoveredItems();
101         int total = coverageInfo.getTotalItems();
102 
103         coveredItems += covered;
104         totalItems += total;
105 
106         printCoveragePercentage(covered, total, percentage);
107     }
108 }