1
2
3
4 package net.sourceforge.pmd.renderers;
5
6 import java.io.BufferedReader;
7 import java.io.File;
8 import java.io.FileNotFoundException;
9 import java.io.FileReader;
10 import java.io.IOException;
11 import java.io.Reader;
12 import java.util.Iterator;
13 import java.util.Map;
14
15 import net.sourceforge.pmd.PMD;
16 import net.sourceforge.pmd.Report;
17 import net.sourceforge.pmd.RuleViolation;
18 import net.sourceforge.pmd.lang.rule.properties.StringProperty;
19 import net.sourceforge.pmd.util.IOUtil;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 public class TextColorRenderer extends AbstractAccumulatingRenderer {
52
53
54 public static final String NAME = "textcolor";
55
56 public static final StringProperty COLOR = new StringProperty("color", "Enables colors with anything other than 'false' or '0'.", "yes", 0);
57 private static final String SYSTEM_PROPERTY_PMD_COLOR = "pmd.color";
58
59
60
61
62 private String pwd;
63
64 private String yellowBold = "";
65 private String whiteBold = "";
66 private String redBold = "";
67 private String cyan = "";
68 private String green = "";
69
70 private String colorReset = "";
71
72 public TextColorRenderer() {
73
74 super(NAME, "Text format, with color support (requires ANSI console support, e.g. xterm, rxvt, etc.).");
75 definePropertyDescriptor(COLOR);
76 }
77
78 public String defaultFileExtension() { return "txt"; }
79
80
81
82
83
84
85
86
87 private void initializeColorsIfSupported() {
88 if (isPropertyEnabled(getProperty(COLOR)) || isPropertyEnabled(System.getProperty(SYSTEM_PROPERTY_PMD_COLOR))) {
89 this.yellowBold = "\u001B[1;33m";
90 this.whiteBold = "\u001B[1;37m";
91 this.redBold = "\u001B[1;31m";
92 this.green = "\u001B[0;32m";
93 this.cyan = "\u001B[0;36m";
94
95 this.colorReset = "\u001B[0m";
96 }
97 }
98
99 private boolean isPropertyEnabled(String property) {
100 return property != null && !(property.equals("0") || property.equalsIgnoreCase("false"));
101 }
102
103
104
105
106 @Override
107 public void end() throws IOException {
108 StringBuffer buf = new StringBuffer(500);
109 buf.append(PMD.EOL);
110 initializeColorsIfSupported();
111 String lastFile = null;
112 int numberOfErrors = 0;
113 int numberOfWarnings = 0;
114
115 for (Iterator<RuleViolation> i = report.iterator(); i.hasNext();) {
116 buf.setLength(0);
117 numberOfWarnings++;
118 RuleViolation rv = i.next();
119 if (!rv.getFilename().equals(lastFile)) {
120 lastFile = rv.getFilename();
121 buf.append(this.yellowBold + "*" + this.colorReset + " file: " + this.whiteBold
122 + this.getRelativePath(lastFile) + this.colorReset + PMD.EOL);
123 }
124 buf.append(this.green + " src: " + this.cyan
125 + lastFile.substring(lastFile.lastIndexOf(File.separator) + 1) + this.colorReset + ":" + this.cyan
126 + rv.getBeginLine() + (rv.getEndLine() == -1 ? "" : ":" + rv.getEndLine()) + this.colorReset
127 + PMD.EOL);
128 buf.append(this.green + " rule: " + this.colorReset + rv.getRule().getName() + PMD.EOL);
129 buf.append(this.green + " msg: " + this.colorReset + rv.getDescription() + PMD.EOL);
130 buf.append(this.green + " code: " + this.colorReset + this.getLine(lastFile, rv.getBeginLine())
131 + PMD.EOL + PMD.EOL);
132 writer.write(buf.toString());
133 }
134 writer.write(PMD.EOL + PMD.EOL);
135 writer.write("Summary:" + PMD.EOL + PMD.EOL);
136 Map<String, Integer> summary = report.getCountSummary();
137 for (Map.Entry<String, Integer> entry : summary.entrySet()) {
138 buf.setLength(0);
139 String key = entry.getKey();
140 buf.append(key).append(" : ").append(entry.getValue()).append(PMD.EOL);
141 writer.write(buf.toString());
142 }
143
144 for (Iterator<Report.ProcessingError> i = report.errors(); i.hasNext();) {
145 buf.setLength(0);
146 numberOfErrors++;
147 Report.ProcessingError error = i.next();
148 if (error.getFile().equals(lastFile)) {
149 lastFile = error.getFile();
150 buf.append(this.redBold + "*" + this.colorReset + " file: " + this.whiteBold
151 + this.getRelativePath(lastFile) + this.colorReset + PMD.EOL);
152 }
153 buf.append(this.green + " err: " + this.cyan + error.getMsg() + this.colorReset + PMD.EOL + PMD.EOL);
154 writer.write(buf.toString());
155 }
156
157
158 if (numberOfErrors > 0) {
159 writer.write(this.redBold + "*" + this.colorReset + " errors: " + this.whiteBold + numberOfWarnings
160 + this.colorReset + PMD.EOL);
161 }
162 writer.write(this.yellowBold + "*" + this.colorReset + " warnings: " + this.whiteBold + numberOfWarnings
163 + this.colorReset + PMD.EOL);
164 }
165
166
167
168
169
170
171
172
173 private String getLine(String sourceFile, int line) {
174 String code = null;
175 BufferedReader br = null;
176 try {
177 br = new BufferedReader(getReader(sourceFile));
178 for (int i = 0; line > i; i++) {
179 String txt = br.readLine();
180 code = txt == null ? "" : txt.trim();
181 }
182 } catch (IOException ioErr) {
183 ioErr.printStackTrace();
184 } finally {
185 IOUtil.closeQuietly(br);
186 }
187 return code;
188 }
189
190 protected Reader getReader(String sourceFile) throws FileNotFoundException {
191 return new FileReader(new File(sourceFile));
192 }
193
194
195
196
197
198
199
200
201 private String getRelativePath(String fileName) {
202 String relativePath;
203
204
205 if (pwd == null) {
206 try {
207 this.pwd = new File(".").getCanonicalPath();
208 } catch (IOException ioErr) {
209
210 this.pwd = "";
211 }
212 }
213
214
215 if (fileName.indexOf(this.pwd) == 0) {
216 relativePath = "." + fileName.substring(this.pwd.length());
217
218
219 if (relativePath.startsWith("." + File.separator + "." + File.separator)) {
220 relativePath = relativePath.substring(2);
221 }
222 } else {
223
224
225
226 relativePath = fileName;
227 }
228
229 return relativePath;
230 }
231 }