KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > incava > analysis > ContextReport


1 package org.incava.analysis;
2
3 import java.io.*;
4 import java.util.*;
5 import net.sourceforge.pmd.ast.Token;
6 import org.incava.lang.StringExt;
7 import org.incava.util.ANSI;
8
9
10 /**
11  * Reports errors in multiple lines, displaying the contextual code, and
12  * denoting the code to which a violation applies.
13  */

14 public class ContextReport extends Report
15 {
16     /**
17      * The number of spaces a tab is equivalent to.
18      */

19     public static int tabWidth = 4;
20
21     /**
22      * The end-of-line character/sequence for this OS.
23      */

24     private final static String JavaDoc EOLN = System.getProperty("line.separator");
25
26     /**
27      * The reader associated with the source code, which is used for reproducing
28      * the code associated with a violation.
29      */

30     private Reader sourceReader;
31
32     /**
33      * Whether the file name has been written yet.
34      */

35     private boolean wroteFileName = false;
36
37     /**
38      * The contents, separated by new lines, which are included at the end of
39      * each string.
40      */

41     private String JavaDoc[] contents;
42
43     /**
44      * Creates a context report for the given writer.
45      *
46      * @param writer The writer associated with this report.
47      */

48     public ContextReport(Writer writer)
49     {
50         super(writer);
51     }
52
53     /**
54      * Creates a context report for the given output stream.
55      *
56      * @param os The output stream associated with this report.
57      */

58     public ContextReport(OutputStream os)
59     {
60         super(os);
61     }
62
63     /**
64      * Creates a context report for the given writer, and a string source.
65      *
66      * @param writer The writer associated with this report.
67      * @param source The source code to which this report applies.
68      */

69     public ContextReport(Writer writer, String JavaDoc source)
70     {
71         super(writer, source);
72     }
73
74     /**
75      * Creates a context report for the given writer, and a file source.
76      *
77      * @param writer The writer associated with this report.
78      * @param file The file, containing source code, to which this report applies.
79      */

80     public ContextReport(Writer writer, File file)
81     {
82         super(writer, file);
83     }
84
85     /**
86      * Creates a context report for the given output stream, and string source.
87      *
88      * @param os The output stream associated with this report.
89      * @param source The source code to which this report applies.
90      */

91     public ContextReport(OutputStream os, String JavaDoc source)
92     {
93         super(os, source);
94     }
95
96     /**
97      * Creates a context report for the given output stream, and file.
98      *
99      * @param os The output stream associated with this report.
100      * @param file The file, containing source code, to which this report applies.
101      */

102     public ContextReport(OutputStream os, File file)
103     {
104         super(os, file);
105     }
106     
107     /**
108      * Associates the given file with the list of violations, including that are
109      * adding to this report later, i.e., prior to <code>flush</code>.
110      *
111      * @param file The file associated with the set of violations.
112      */

113     public void reset(File file)
114     {
115         super.reset(file);
116         wroteFileName = false;
117         contents = null;
118         
119         try {
120             sourceReader = new FileReader(file);
121         }
122         catch (IOException ioe) {
123             tr.Ace.log("error reading file: " + file);
124         }
125     }
126
127     /**
128      * Associates the given string source with the list of violations, including
129      * that are adding to this report later, i.e., prior to <code>flush</code>.
130      *
131      * @param source The source code associated with the set of violations.
132      */

133     public void reset(String JavaDoc source)
134     {
135         super.reset(source);
136         wroteFileName = false;
137         contents = null;
138         
139         sourceReader = new StringReader(source);
140     }
141
142     /**
143      * Returns a string representing the given violation, consistent with the
144      * format of the Report subclass.
145      *
146      * @param violation The violation to represent as a string.
147      */

148     protected String JavaDoc toString(Violation violation)
149     {
150         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
151         if (!wroteFileName) {
152             buf.append("In " + ANSI.BOLD + ANSI.REVERSE + fileName + ANSI.RESET + ":" + EOLN + EOLN);
153             wroteFileName = true;
154         }
155
156         if (contents == null) {
157             tr.Ace.log("opening reader for " + sourceReader);
158                 
159             try {
160                 List cont = new ArrayList();
161                 BufferedReader br = new BufferedReader(sourceReader);
162                 
163                 String JavaDoc line = br.readLine();
164                 while (line != null) {
165                     cont.add(line);
166                     line = br.readLine();
167                 }
168
169                 contents = (String JavaDoc[])cont.toArray(new String JavaDoc[0]);
170
171                 for (int i = 0; i < contents.length; ++i) {
172                     tr.Ace.log("contents[" + i + "]: " + contents[i]);
173                 }
174             }
175             catch (IOException ioe) {
176                 tr.Ace.log("error reading source: " + ioe);
177             }
178         }
179
180         tr.Ace.log("writing: " + violation);
181
182         int beginLine = violation.getBeginLine() - 1;
183         int endLine = violation.getEndLine() - 1;
184         int beginColumn = violation.getBeginColumn() - 1;
185         int endColumn = violation.getEndColumn() - 1;
186         
187         if (beginLine == endLine) {
188             writeLine(buf, beginLine);
189             underline(buf, beginLine, beginColumn, endColumn);
190         }
191         else {
192             markToEndOfLine(buf, beginLine, beginColumn);
193             for (int lnum = beginLine; lnum <= endLine; ++lnum) {
194                 writeLine(buf, lnum);
195             }
196             markToStartPosition(buf, endLine, endColumn);
197         }
198         
199         buf.append("*** " + violation.getMessage() + EOLN);
200         buf.append(EOLN);
201         
202         return buf.toString();
203     }
204
205     /**
206      * Adds indentation to the buffer, replacing spacing and tabs. Replaces tabs
207      * with <code>tabWidth</code> occurrences of <code>ch</code>.
208      *
209      * @param buf The buffer to be written to.
210      * @param line The current line number.
211      * @param column The column to indent to.
212      * @param ch The character with which to replace spaces and tabs.
213      */

214     protected void indent(StringBuffer JavaDoc buf, int line, int column, char ch)
215     {
216         buf.append(" ");
217
218         // move it over for the column, replacing tabs with spaces
219
buf.append(StringExt.repeat(ch, column));
220     }
221
222     /**
223      * Marks the given line with leading spaces to the column position
224      * (inclusive), and from there marking to the end of the line with
225      * "<---...".
226      *
227      * @param buf The buffer to be written to.
228      * @param line The current line number.
229      * @param column The column to mark to/from.
230      */

231     protected void markToEndOfLine(StringBuffer JavaDoc buf, int line, int column)
232     {
233         indent(buf, line, column, ' ');
234         
235         int len = contents[line].length();
236         
237         buf.append('<');
238         for (int i = column + 1; i < len; ++i) {
239             buf.append('-');
240         }
241         buf.append(EOLN);
242     }
243
244     /**
245      * Marks the given line with "...--->" leading to the column position
246      * (inclusive).
247      *
248      * @param buf The buffer to be written to.
249      * @param line The current line number.
250      * @param column The column to mark to.
251      */

252     protected void markToStartPosition(StringBuffer JavaDoc buf, int line, int column)
253     {
254         indent(buf, line, column, '-');
255
256         buf.append('>');
257         buf.append(EOLN);
258     }
259
260     /**
261      * Underlines ("<--...-->") from <code>beginColumn</code> to
262      * <code>endColumn</code> in the given line. If the columns are equal, a
263      * single caret is shown.
264      *
265      * @param buf The buffer to be written to.
266      * @param line The current line number.
267      * @param beginColumn The column to mark from.
268      * @param endColumn The column to mark to.
269      */

270     protected void underline(StringBuffer JavaDoc buf, int line, int beginColumn, int endColumn)
271     {
272         indent(buf, line, beginColumn, ' ');
273         
274         if (beginColumn == endColumn) {
275             buf.append('^');
276         }
277         else {
278             buf.append('<');
279             for (int i = beginColumn + 1; i < endColumn; ++i) {
280                 buf.append('-');
281             }
282             buf.append('>');
283         }
284         buf.append(EOLN);
285     }
286
287     /**
288      * Writes the given line, adding the line number, right-aligned. Appends the
289      * end-of-line character/sequence.
290      *
291      * @param buf The buffer to be written to.
292      * @param line The current line number.
293      */

294     protected void writeLine(StringBuffer JavaDoc buf, int line)
295     {
296         StringBuffer JavaDoc lnBuf = new StringBuffer JavaDoc("" + (1 + line));
297         while (lnBuf.length() < 6) {
298             lnBuf.insert(0, ' ');
299         }
300
301         buf.append(lnBuf);
302         buf.append(". ");
303         buf.append(contents[line]);
304         buf.append(EOLN);
305     }
306
307 }
308
Popular Tags