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.sourceFiles;
6   
7   import edu.umd.cs.findbugs.annotations.NonNull;
8   import edu.umd.cs.findbugs.annotations.Nullable;
9   
10  import java.io.IOException;
11  
12  import mockit.coverage.data.FileCoverageData;
13  import mockit.coverage.dataItems.PerFileDataCoverage;
14  import mockit.coverage.reporting.OutputFile;
15  import mockit.coverage.reporting.dataCoverage.DataCoverageOutput;
16  import mockit.coverage.reporting.lineCoverage.LineCoverageOutput;
17  import mockit.coverage.reporting.parsing.FileParser;
18  import mockit.coverage.reporting.parsing.LineElement;
19  import mockit.coverage.reporting.parsing.LineParser;
20  
21  import org.checkerframework.checker.index.qual.NonNegative;
22  
23  /**
24   * Generates an HTML page containing line-by-line coverage information for a single source file.
25   */
26  public final class FileCoverageReport {
27      @NonNull
28      private final InputFile inputFile;
29      @NonNull
30      private final OutputFile output;
31      @NonNull
32      private final FileParser fileParser;
33      @NonNull
34      private final NeutralOutput neutralOutput;
35      @NonNull
36      private final LineCoverageOutput lineCoverage;
37      @Nullable
38      private final DataCoverageOutput dataCoverage;
39  
40      public FileCoverageReport(@NonNull String outputDir, @NonNull InputFile inputFile,
41              @NonNull FileCoverageData fileData, boolean withCallPoints) throws IOException {
42          this.inputFile = inputFile;
43          output = new OutputFile(outputDir, inputFile.filePath);
44          fileParser = new FileParser();
45          neutralOutput = new NeutralOutput(output);
46          lineCoverage = new LineCoverageOutput(output, fileData.getLineCoverageData(), withCallPoints);
47          dataCoverage = createDataCoverageOutput(fileData);
48      }
49  
50      @Nullable
51      private static DataCoverageOutput createDataCoverageOutput(@NonNull FileCoverageData fileData) {
52          PerFileDataCoverage dataCoverageInfo = fileData.dataCoverageInfo;
53          return dataCoverageInfo.hasFields() ? new DataCoverageOutput(dataCoverageInfo) : null;
54      }
55  
56      public void generate() throws IOException {
57          try {
58              writeHeader();
59              writeFormattedSourceLines();
60              writeFooter();
61          } finally {
62              inputFile.close();
63              output.close();
64          }
65      }
66  
67      private void writeHeader() {
68          output.writeCommonHeader(inputFile.getSourceFileName());
69          output.println("  <table>");
70          output.println("    <caption>" + inputFile.getSourceFilePath() + "</caption>");
71      }
72  
73      private void writeFormattedSourceLines() throws IOException {
74          LineParser lineParser = fileParser.lineParser;
75          String line;
76  
77          while ((line = inputFile.nextLine()) != null) {
78              boolean lineWithCodeElements = fileParser.parseCurrentLine(line);
79  
80              if (lineWithCodeElements && dataCoverage != null) {
81                  dataCoverage.writeCoverageInfoIfLineStartsANewFieldDeclaration(fileParser);
82              }
83  
84              if (!neutralOutput.writeLineWithoutCoverageInfo(lineParser)) {
85                  writeOpeningOfNewLine(lineParser.getNumber());
86  
87                  if (!lineCoverage.writeLineWithCoverageInfo(lineParser)) {
88                      writeLineWithoutCoverageInfo(lineParser.getInitialElement());
89                  }
90  
91                  output.println("    </tr>");
92              }
93          }
94      }
95  
96      private void writeOpeningOfNewLine(@NonNegative int lineNumber) {
97          output.println("    <tr>");
98          output.write("      <td>");
99          output.print(lineNumber);
100         output.write("</td>");
101     }
102 
103     private void writeLineWithoutCoverageInfo(@NonNull LineElement initialElement) {
104         output.println("<td></td>");
105         output.write("      <td><pre class='");
106         output.write(initialElement.isComment() ? "cm'>" : "pp'>");
107         output.write(initialElement.toString());
108         output.println("</pre></td>");
109     }
110 
111     private void writeFooter() {
112         output.println("  </table>");
113         output.writeCommonFooter();
114     }
115 }