001: // Copyright (c) 1999, 2005 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.text;
005:
006: /** A collection of (zero or more) SourceErrors.
007: * Has a "current line number" which clients can use as the default line
008: * number, or clients can explicitly provide a line number.
009: * Does not handle localization of messages.
010: */
011:
012: public class SourceMessages implements SourceLocator {
013: // Number of errors (not counting warnings). A value of 1000 is "fatal".
014: private int errorCount = 0;
015:
016: /** The first error or warning in a linked list. */
017: SourceError firstError;
018: /** The last error or warning in a linked list. */
019: SourceError lastError;
020:
021: public SourceError getErrors() {
022: return firstError;
023: }
024:
025: SourceLocator locator;
026:
027: String current_filename;
028: int current_line;
029: int current_column;
030:
031: /** If true, print out stack trace with any warning. */
032: public static boolean debugStackTraceOnWarning = false;
033:
034: /** If true, print out stack trace with any error. */
035: public static boolean debugStackTraceOnError = false;
036:
037: /** Return true iff errors (not warnings) have been seen. */
038: public boolean seenErrors() {
039: return errorCount > 0;
040: }
041:
042: public boolean seenErrorsOrWarnings() {
043: return firstError != null;
044: }
045:
046: /** Get the number of errors (not counting warnings). */
047: public int getErrorCount() {
048: return errorCount;
049: }
050:
051: /** Clear the error count (only). */
052: public void clearErrors() {
053: errorCount = 0;
054: }
055:
056: /** Clear the contained errors and warnings. */
057: public void clear() {
058: firstError = lastError = null;
059: errorCount = 0;
060: }
061:
062: // The last SourceError with a *differnt* filename than prev has.
063: SourceError lastPrevFilename = null;
064:
065: /** True if we should sort messages by line number. */
066: public boolean sortMessages;
067:
068: /** Link in an error. */
069: public void error(SourceError error) {
070: if (error.severity == 'f')
071: errorCount = 1000;
072: else if (error.severity != 'w')
073: errorCount++;
074: if ((SourceMessages.debugStackTraceOnError && (error.severity == 'e' || error.severity == 'f'))
075: || SourceMessages.debugStackTraceOnWarning
076: && error.severity == 'w') {
077: error.fakeException = new Throwable();
078: }
079:
080: // Insert the next error so that line numbers are increasing.
081: if (lastError != null && lastError.filename != null
082: && !lastError.filename.equals(error.filename))
083: lastPrevFilename = lastError;
084: SourceError prev = lastPrevFilename;
085: if (!sortMessages || error.severity == 'f')
086: prev = lastError;
087: else {
088: for (;;) {
089: SourceError next;
090: if (prev == null)
091: next = firstError;
092: else
093: next = prev.next;
094: if (next == null)
095: break;
096: if (error.line != 0 && next.line != 0) {
097: if (error.line < next.line)
098: break;
099: if (error.line == next.line && error.column != 0
100: && next.column != 0) {
101: if (error.column < next.column)
102: break;
103: }
104: }
105: prev = next;
106: }
107: }
108: if (prev == null) {
109: error.next = firstError;
110: firstError = error;
111: } else {
112: error.next = prev.next;
113: prev.next = error;
114: }
115: if (prev == lastError)
116: lastError = error;
117: }
118:
119: /** Record a new error.
120: * @param severity is the seriousness of the error
121: * - one of 'w' (for warning), 'e' (for error), or 'f' (for fatal error)
122: * @param filename the name or URL of the file containing the error
123: * @param line the (1-origin) line number or 0 if unknown
124: * @param column the (1-origin) column number or 0 if unknown
125: * @param message the error message
126: */
127: public void error(char severity, String filename, int line,
128: int column, String message) {
129: error(new SourceError(severity, filename, line, column, message));
130: }
131:
132: public void error(char severity, SourceLocator location,
133: String message) {
134: error(new SourceError(severity, location, message));
135: }
136:
137: public void error(char severity, String filename, int line,
138: int column, String message, String code) {
139: SourceError err = new SourceError(severity, filename, line,
140: column, message);
141: err.code = code;
142: error(err);
143: }
144:
145: public void error(char severity, SourceLocator location,
146: String message, String code) {
147: SourceError err = new SourceError(severity, location, message);
148: err.code = code;
149: error(err);
150: }
151:
152: /** Record a new error at the current default source file location.
153: * @param severity is the seriousness of the error
154: * - one of 'w' (for warning), 'e' (for error), or 'f' (for fatal error)
155: * @param message the error message
156: */
157: public void error(char severity, String message) {
158: error(new SourceError(severity, current_filename, current_line,
159: current_column, message));
160: }
161:
162: public void error(char severity, String message, String code) {
163: SourceError err = new SourceError(severity, current_filename,
164: current_line, current_column, message);
165: err.code = code;
166: error(err);
167: }
168:
169: /** Print all the error messages to a PrintStream. */
170: public void printAll(java.io.PrintStream out, int max) {
171: for (SourceError err = firstError; err != null && --max >= 0; err = err.next) {
172: err.println(out);
173: }
174: }
175:
176: /** Print all the error messages to a PrintWriter. */
177: public void printAll(java.io.PrintWriter out, int max) {
178: for (SourceError err = firstError; err != null && --max >= 0; err = err.next) {
179: err.println(out);
180: }
181: }
182:
183: /** Convert this to a String containing the recorded errors.
184: * @param max the maximum number of error error to list
185: * @return a String with one '\n'-terminated line per recorded error
186: */
187: public String toString(int max) {
188: if (firstError == null)
189: return null;
190: StringBuffer buffer = new StringBuffer();
191: for (SourceError err = firstError; err != null && --max >= 0; err = err.next) {
192: buffer.append(err);
193: buffer.append('\n');
194: }
195: return buffer.toString();
196: }
197:
198: /** Checks if an error was seen; if so, prints and clears the messages.
199: * @param out where to write the error message to
200: * @param max maximum number of messages to print (can be 0)
201: */
202: public boolean checkErrors(java.io.PrintWriter out, int max) {
203: if (firstError != null) {
204: printAll(out, max);
205: firstError = lastError = null;
206: int saveCount = errorCount;
207: errorCount = 0;
208: return saveCount > 0;
209: }
210: return false;
211: }
212:
213: /** Checks if an error was seen; if so, prints and clears the messages.
214: * @param out where to write the error message to
215: * @param max maximum number of messages to print (can be 0) */
216: public boolean checkErrors(java.io.PrintStream out, int max) {
217: if (firstError != null) {
218: printAll(out, max);
219: firstError = lastError = null;
220: int saveCount = errorCount;
221: errorCount = 0;
222: return saveCount > 0;
223: }
224: return false;
225: }
226:
227: /** Links our location to the one give. */
228: public final void setSourceLocator(SourceLocator locator) {
229: this .locator = locator == this ? null : locator;
230: }
231:
232: /** Copies the current position of locator. */
233: public final void setLocation(SourceLocator locator) {
234: this .locator = null;
235: current_line = locator.getLineNumber();
236: current_column = locator.getColumnNumber();
237: current_filename = locator.getFileName();
238: }
239:
240: public String getPublicId() {
241: return locator == null ? null : locator.getPublicId();
242: }
243:
244: public String getSystemId() {
245: return locator == null ? current_filename : locator
246: .getSystemId();
247: }
248:
249: public boolean isStableSourceLocation() {
250: return false;
251: }
252:
253: /** The default filename to use for a new error. */
254: public final String getFileName() {
255: return current_filename;
256: }
257:
258: /** The default line number to use for a new error. */
259: public final int getLineNumber() {
260: return locator == null ? current_line : locator.getLineNumber();
261: }
262:
263: /** The default column number to use for a new error. */
264: public final int getColumnNumber() {
265: return locator == null ? current_column : locator
266: .getColumnNumber();
267: }
268:
269: /** Set the default filename to use for a new error. */
270: public void setFile(String filename) {
271: current_filename = filename;
272: }
273:
274: /** Set the default line number to use for a new error. */
275: public void setLine(int line) {
276: current_line = line;
277: }
278:
279: /** Set the default column number to use for a new error. */
280: public void setColumn(int column) {
281: current_column = column;
282: }
283:
284: /** Set the default filename, line and column to use for a new error. */
285: public void setLine(String filename, int line, int column) {
286: current_filename = filename;
287: current_line = line;
288: current_column = column;
289: }
290:
291: }
|