1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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 package org.codehaus.groovy.control;
48
49 import java.io.PrintWriter;
50 import java.util.Iterator;
51 import java.util.LinkedList;
52 import java.util.List;
53
54 import org.codehaus.groovy.control.messages.ExceptionMessage;
55 import org.codehaus.groovy.control.messages.LocatedMessage;
56 import org.codehaus.groovy.control.messages.Message;
57 import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
58 import org.codehaus.groovy.control.messages.WarningMessage;
59 import org.codehaus.groovy.syntax.CSTNode;
60 import org.codehaus.groovy.syntax.SyntaxException;
61
62 /***
63 * A base class for collecting messages and errors during processing.
64 * Each CompilationUnit should have one and SourceUnits should share
65 * their ErrorCollector with the CompilationUnit.
66 *
67 * @author <a href="mailto:cpoirier@dreaming.org">Chris Poirier</a>
68 * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
69 * @version $Id: ErrorCollector.java,v 1.5 2005/06/13 09:31:01 blackdrag Exp $
70 */
71 public class ErrorCollector {
72
73 /***
74 * WarningMessages collected during processing
75 */
76 protected LinkedList warnings;
77 /***
78 * ErrorMessages collected during processing
79 */
80 protected LinkedList errors;
81 /***
82 * Configuration and other settings that control processing
83 */
84 protected CompilerConfiguration configuration;
85
86 /***
87 * Initialize the ErrorReporter.
88 */
89 public ErrorCollector(CompilerConfiguration configuration) {
90 this.warnings = null;
91 this.errors = null;
92
93 this.configuration = configuration;
94 }
95
96 public void addCollectorContents(ErrorCollector er) {
97 if (er.errors!=null) {
98 if (errors==null) {
99 errors = er.errors;
100 } else {
101 errors.addAll(errors);
102 }
103 }
104 if (er.warnings!=null) {
105 if (warnings==null) {
106 warnings = er.warnings;
107 } else {
108 warnings.addAll(warnings);
109 }
110 }
111 }
112
113
114
115 /***
116 * Adds an error to the message set, but don't fail.
117 */
118 public void addErrorAndContinue(Message message) {
119 if (this.errors == null) {
120 this.errors = new LinkedList();
121 }
122
123 this.errors.add(message);
124 }
125
126 /***
127 * Adds a non-fatal error to the message set.
128 */
129 public void addError(Message message) throws CompilationFailedException {
130 addErrorAndContinue(message);
131
132 if (errors!=null && this.errors.size() >= configuration.getTolerance()) {
133 failIfErrors();
134 }
135 }
136
137 /***
138 * Adds an optionally-fatal error to the message set. Throws
139 * the unit as a PhaseFailedException, if the error is fatal.
140 */
141 public void addError(Message message, boolean fatal) throws CompilationFailedException {
142 if (fatal) {
143 addFatalError(message);
144 }
145 else {
146 addError(message);
147 }
148 }
149
150
151 /***
152 * Convenience wrapper for addError().
153 */
154 public void addError(SyntaxException error, SourceUnit source) throws CompilationFailedException {
155 addError(Message.create(error, source), error.isFatal());
156 }
157
158
159 /***
160 * Convenience wrapper for addError().
161 */
162 public void addError(String text, CSTNode context, SourceUnit source) throws CompilationFailedException {
163 addError(new LocatedMessage(text, context, source));
164 }
165
166
167 /***
168 * Adds a fatal exception to the message set and throws
169 * the unit as a PhaseFailedException.
170 */
171 public void addFatalError(Message message) throws CompilationFailedException {
172 addError(message);
173 failIfErrors();
174 }
175
176
177 public void addException(Exception cause, SourceUnit source) throws CompilationFailedException {
178 addError(new ExceptionMessage(cause,configuration.getDebug(),source));
179 failIfErrors();
180 }
181
182 /***
183 * Returns true if there are any errors pending.
184 */
185 public boolean hasErrors() {
186 return this.errors != null;
187 }
188
189 /***
190 * Returns true if there are any warnings pending.
191 */
192 public boolean hasWarnings() {
193 return this.warnings != null;
194 }
195
196 /***
197 * Returns the list of warnings, or null if there are none.
198 */
199 public List getWarnings() {
200 return this.warnings;
201 }
202
203 /***
204 * Returns the list of errors, or null if there are none.
205 */
206 public List getErrors() {
207 return this.errors;
208 }
209
210 /***
211 * Returns the number of warnings.
212 */
213 public int getWarningCount() {
214 return ((this.warnings == null) ? 0 : this.warnings.size());
215 }
216
217 /***
218 * Returns the number of errors.
219 */
220 public int getErrorCount() {
221 return ((this.errors == null) ? 0 : this.errors.size());
222 }
223
224 /***
225 * Returns the specified warning message, or null.
226 */
227 public WarningMessage getWarning(int index) {
228 if (index < getWarningCount()) {
229 return (WarningMessage) this.warnings.get(index);
230 }
231 return null;
232 }
233
234 /***
235 * Returns the specified error message, or null.
236 */
237 public Message getError(int index) {
238 if (index < getErrorCount()) {
239 return (Message) this.errors.get(index);
240 }
241 return null;
242 }
243
244 /***
245 * Returns the last error reported
246 */
247 public Message getLastError() {
248 return (Message) this.errors.getLast();
249 }
250
251 /***
252 * Convenience routine to return the specified error's
253 * underlying SyntaxException, or null if it isn't one.
254 */
255 public SyntaxException getSyntaxError(int index) {
256 SyntaxException exception = null;
257
258 Message message = getError(index);
259 if (message != null && message instanceof SyntaxErrorMessage) {
260 exception = ((SyntaxErrorMessage) message).getCause();
261 }
262 return exception;
263 }
264
265 /***
266 * Convenience routine to return the specified error's
267 * underlying Exception, or null if it isn't one.
268 */
269 public Exception getException(int index) {
270 Exception exception = null;
271
272 Message message = getError(index);
273 if (message != null) {
274 if (message instanceof ExceptionMessage) {
275 exception = ((ExceptionMessage) message).getCause();
276 }
277 else if (message instanceof SyntaxErrorMessage) {
278 exception = ((SyntaxErrorMessage) message).getCause();
279 }
280 }
281 return exception;
282 }
283
284 /***
285 * Adds a WarningMessage to the message set.
286 */
287 public void addWarning(WarningMessage message) {
288 if (message.isRelevant(configuration.getWarningLevel())) {
289 if (this.warnings == null) {
290 this.warnings = new LinkedList();
291 }
292
293 this.warnings.add(message);
294 }
295 }
296
297
298 /***
299 * Convenience wrapper for addWarning() that won't create an object
300 * unless it is relevant.
301 */
302 public void addWarning(int importance, String text, CSTNode context, SourceUnit source) {
303 if (WarningMessage.isRelevant(importance, configuration.getWarningLevel())) {
304 addWarning(new WarningMessage(importance, text, context, source));
305 }
306 }
307
308
309 /***
310 * Convenience wrapper for addWarning() that won't create an object
311 * unless it is relevant.
312 */
313 public void addWarning(int importance, String text, Object data, CSTNode context, SourceUnit source) {
314 if (WarningMessage.isRelevant(importance, configuration.getWarningLevel())) {
315 addWarning(new WarningMessage(importance, text, data, context, source));
316 }
317 }
318
319
320 /***
321 * Causes the current phase to fail by throwing a
322 * CompilationFailedException.
323 */
324 protected void failIfErrors() throws CompilationFailedException {
325 if (hasErrors()) throw new MultipleCompilationErrorsException(this);
326 }
327
328
329
330
331
332 /***
333 * Writes error messages to the specified PrintWriter.
334 */
335 public void write(PrintWriter writer, Janitor janitor) {
336 if (this.warnings != null) {
337 Iterator iterator = this.warnings.iterator();
338 while (iterator.hasNext()) {
339 WarningMessage warning = (WarningMessage) iterator.next();
340 warning.write(writer, janitor);
341 }
342
343 writer.println();
344 writer.print(warnings.size());
345 writer.print(" Warning");
346 if (warnings.size()>1) writer.print("s");
347 writer.println();
348
349 this.warnings = null;
350 }
351
352 if (this.errors != null) {
353 Iterator iterator = this.errors.iterator();
354 while (iterator.hasNext()) {
355 Message message = (Message) iterator.next();
356 message.write(writer, janitor);
357
358 if (configuration.getDebug() && (message instanceof SyntaxErrorMessage)) {
359 SyntaxErrorMessage sem = (SyntaxErrorMessage) message;
360 SyntaxException se = sem.getCause();
361 se.printStackTrace(writer);
362 }
363 }
364
365 writer.println();
366 writer.print(errors.size());
367 writer.print(" Error");
368 if (errors.size()>1) writer.print("s");
369 writer.println();
370 }
371 }
372
373 }