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.sourceFiles;
7   
8   import edu.umd.cs.findbugs.annotations.NonNull;
9   import edu.umd.cs.findbugs.annotations.Nullable;
10  
11  import java.io.PrintWriter;
12  
13  import mockit.coverage.reporting.parsing.LineElement;
14  import mockit.coverage.reporting.parsing.LineParser;
15  
16  final class NeutralOutput {
17      @NonNull
18      private final PrintWriter output;
19      private boolean previousLineInImports;
20      private boolean previousLineInComments;
21      @Nullable
22      private String lineIndentation;
23      private boolean blankLinesPending;
24  
25      NeutralOutput(@NonNull PrintWriter output) {
26          this.output = output;
27      }
28  
29      boolean writeLineWithoutCoverageInfo(@NonNull LineParser lineParser) {
30          if (previousLineInComments || !previousLineInImports) {
31              if (writeLineInComments(lineParser) || writeLineInImports(lineParser)) {
32                  return true;
33              }
34          } else if (writeLineInImports(lineParser) || writeLineInComments(lineParser)) {
35              return true;
36          }
37  
38          if (lineParser.isBlankLine()) {
39              blankLinesPending = true;
40              return true;
41          }
42  
43          writeBlankLineIfPending();
44          return false;
45      }
46  
47      private boolean writeLineInComments(@NonNull LineParser lineParser) {
48          LineElement initialElement = lineParser.getInitialElement();
49  
50          if (lineParser.isInComments()
51                  || previousLineInComments && initialElement.isComment() && initialElement.getNext() == null) {
52              String lineText = initialElement.toString();
53  
54              if (previousLineInComments) {
55                  output.println();
56              } else {
57                  writeOpeningForCollapsibleBlockOfLines();
58                  output.write("      <td class='cm' onclick='shLns(this)'><div>");
59                  extractLineIndentation(lineText);
60                  previousLineInComments = true;
61              }
62  
63              output.write(lineText);
64              return true;
65          }
66          if (previousLineInComments) {
67              output.append("</div><span>").append(lineIndentation).println("/*...*/</span></td>");
68              output.println("    </tr>");
69              previousLineInComments = false;
70          }
71  
72          return false;
73      }
74  
75      private void writeOpeningForCollapsibleBlockOfLines() {
76          writeBlankLineIfPending();
77          output.println("    <tr>");
78          output.println("      <td></td><td></td>");
79      }
80  
81      private void writeBlankLineIfPending() {
82          if (blankLinesPending) {
83              output.println("    <tr><td></td><td></td><td></td></tr>");
84              blankLinesPending = false;
85          }
86      }
87  
88      private void extractLineIndentation(@NonNull String lineText) {
89          int indentationSize = 0;
90  
91          for (int i = 0; i < lineText.length(); i++, indentationSize++) {
92              if (lineText.charAt(i) > ' ') {
93                  break;
94              }
95          }
96  
97          lineIndentation = lineText.substring(0, indentationSize);
98      }
99  
100     private boolean writeLineInImports(@NonNull LineParser lineParser) {
101         LineElement initialElement = lineParser.getInitialElement();
102         boolean isImport = initialElement.isKeyword("import");
103 
104         if (!previousLineInImports && isImport || previousLineInImports && (isImport || lineParser.isBlankLine())) {
105             String lineText = initialElement.toString();
106 
107             if (previousLineInImports) {
108                 output.println();
109                 blankLinesPending = !isImport;
110             } else {
111                 writeOpeningForCollapsibleBlockOfLines();
112                 output.write("      <td><pre class='ims pp' onclick='shLns(this)'><div>");
113                 previousLineInImports = true;
114             }
115 
116             output.write(lineText);
117             return true;
118         }
119         if (previousLineInImports) {
120             output.println("</div><span>import ...</span></pre></td>");
121             output.println("    </tr>");
122             previousLineInImports = false;
123         }
124 
125         return false;
126     }
127 }