1 /***
2 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3 */
4 package net.sourceforge.pmd.renderers;
5
6 import net.sourceforge.pmd.PMD;
7 import net.sourceforge.pmd.Report;
8 import net.sourceforge.pmd.RuleViolation;
9 import net.sourceforge.pmd.util.StringUtil;
10
11 import java.io.BufferedReader;
12 import java.io.File;
13 import java.io.FileReader;
14 import java.io.IOException;
15
16 import java.util.Iterator;
17
18 /***
19 * <p>A console renderer with optional color support under *nix systems.</p>
20 *
21 * <pre>
22 * * file: ./src/gilot/Test.java
23 * src: Test.java:12
24 * rule: AtLeastOneConstructor
25 * msg: Each class should declare at least one constructor
26 * code: public class Test
27 *
28 * * file: ./src/gilot/log/format/LogInterpreter.java
29 * src: LogInterpreter.java:317
30 * rule: AvoidDuplicateLiterals
31 * msg: The same String literal appears 4 times in this file; the first occurrence is on line 317
32 * code: logger.error( "missing attribute 'app_arg' in rule '" + ((Element)element.getParent()).getAttributeValue( "name" ) + "'" );
33 *
34 * src: LogInterpreter.java:317
35 * rule: AvoidDuplicateLiterals
36 * msg: The same String literal appears 5 times in this file; the first occurrence is on line 317
37 * code: logger.error( "missing attribute 'app_arg' in rule '" + ((Element)element.getParent()).getAttributeValue( "name" ) + "'" );
38 *
39 * * warnings: 3
40 *
41 * </pre>
42 *
43 * <p>Colorization is turned on by supplying -D<b>pmd.color</b> - any value other than
44 * '0' or 'false', enables color - including an empty value (''). <b>Nota Bene:</b>
45 * colorization is atm only supported under *nix terminals accepting ansi escape
46 * sequences, such as xterm, rxvt et cetera.</p>
47 */
48 public class PapariTextRenderer implements Renderer
49 {
50 /***
51 * Directory from where java was invoked.
52 */
53 private String pwd = null;
54
55 private String yellowBold = "";
56 private String whiteBold = "";
57 private String redBold = "";
58 private String cyan = "";
59 private String green = "";
60
61 private String colorReset = "";
62
63 /***
64 * Enables colors on *nix systems - not windows. Color support depends
65 * on the pmd.color property, which should be set with the -D option
66 * during execution - a set value other than 'false' or '0' enables color.
67 *
68 * btw, is it possible to do this on windows (ie; console colors)?
69 */
70 private void initColors()
71 {
72 if (System.getProperty("pmd.color") != null &&
73 !(System.getProperty("pmd.color").equals("0") || System.getProperty("pmd.color").equals("false")))
74 {
75 this.yellowBold = "\u001B[1;33m";
76 this.whiteBold = "\u001B[1;37m";
77 this.redBold = "\u001B[1;31m";
78 this.green = "\u001B[0;32m";
79 this.cyan = "\u001B[0;36m";
80
81 this.colorReset = "\u001B[0m";
82 }
83 }
84
85 public String render(Report report)
86 {
87 StringBuffer buf = new StringBuffer(PMD.EOL);
88
89 // init colors, if supported
90 this.initColors();
91
92 // last file
93 String fileName = null;
94
95 // keeps track of violations and errors
96 int errors = 0;
97 int warnings = 0;
98
99 // iterating rule violations
100 for (Iterator i = report.iterator(); i.hasNext();)
101 {
102 warnings++;
103
104 RuleViolation rv = (RuleViolation) i.next();
105 if (!rv.getFilename().equals(fileName))
106 {
107 fileName = rv.getFilename();
108 buf.append( this.yellowBold + "*" + this.colorReset + " file: " + this.whiteBold + this.getRelativePath(fileName) + this.colorReset + PMD.EOL);
109 }
110
111 buf.append(this.green + " src: " + this.cyan + fileName.substring( fileName.lastIndexOf(File.separator)+1)+ this.colorReset + ":" + this.cyan + rv.getLine() + this.colorReset + PMD.EOL);
112 buf.append(this.green + " rule: " + this.colorReset + rv.getRule().getName() + PMD.EOL);
113 buf.append(this.green + " msg: " + this.colorReset + rv.getDescription() + PMD.EOL);
114 buf.append(this.green + " code: " + this.colorReset + this.getLine( fileName, rv.getLine() ) + PMD.EOL + PMD.EOL);
115
116 }
117
118 // iterating errors
119 for (Iterator i = report.errors(); i.hasNext();)
120 {
121 errors++;
122
123 Report.ProcessingError error = (Report.ProcessingError)i.next();
124 if (error.getFile().equals(fileName))
125 {
126 fileName = error.getFile();
127 buf.append( this.redBold + "*" + this.colorReset + " file: " + this.whiteBold + this.getRelativePath(fileName) + this.colorReset + PMD.EOL);
128 }
129 buf.append(this.green + " err: " + this.cyan + error.getMsg() + this.colorReset + PMD.EOL + PMD.EOL);
130 }
131
132 // adding error message count, if any
133 if ( errors > 0 )
134 {
135 buf.append(this.redBold + "*" + this.colorReset + " errors: "+ this.whiteBold + warnings + this.colorReset + PMD.EOL);
136 }
137 buf.append(this.yellowBold + "*" + this.colorReset + " warnings: "+ this.whiteBold + warnings + this.colorReset + PMD.EOL);
138
139 return buf.toString();
140 }
141
142 /***
143 * Retrieves the requested line from the specified file.
144 *
145 * @param sourceFile the java or cpp source file
146 * @param line line number to extract
147 *
148 * @return a trimmed line of source code
149 */
150 private String getLine( String sourceFile, int line )
151 {
152 String code = null;
153 try
154 {
155 File file = new File( "." );
156 BufferedReader br = new BufferedReader( new FileReader( new File( sourceFile ) ) );
157
158 for ( int i = 0; line > i; i++ )
159 {
160 code = br.readLine().trim();
161 }
162 br.close();
163 }
164 catch ( IOException ioErr )
165 {
166 ioErr.printStackTrace();
167 }
168 return code;
169 }
170
171 /***
172 * Attempts to determine the relative path to the file. If relative path cannot be found,
173 * the original path is returnedi, ie - the current path for the supplied file.
174 *
175 * @param fileName well, the file with its original path.
176 * @return the relative path to the file
177 */
178 private String getRelativePath( String fileName )
179 {
180 String relativePath = null;
181
182 // check if working directory need to be assigned
183 if (pwd == null)
184 {
185 try
186 {
187 this.pwd = new File(".").getCanonicalPath();
188 }
189 catch (IOException ioErr)
190 {
191 // to avoid further error
192 this.pwd = "";
193 }
194 }
195
196 // make sure that strings match before doing any substring-ing
197 if (fileName.indexOf(this.pwd) == 0)
198 {
199 relativePath = "." + fileName.substring( this.pwd.length() );
200
201 // remove current dir occuring twice - occurs if . was supplied as path
202 if ( relativePath.startsWith( "." + File.separator + "." + File.separator ) )
203 {
204 relativePath = relativePath.substring(2);
205 }
206 }
207 else
208 {
209 // this happens when pmd's supplied argument deviates from the pwd 'branch' (god knows this terminolgy - i hope i make some sense).
210 // for instance, if supplied=/usr/lots/of/src and pwd=/usr/lots/of/shared/source
211 // TODO: a fix to get relative path?
212 relativePath = fileName;
213 }
214
215 return relativePath;
216 }
217 }
This page was automatically generated by Maven