Tue, 13 Oct 2009 15:26:30 -0700
6891079: Compiler allows invalid binary literals 0b and oBL
Reviewed-by: darcy
1 /*
2 * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javac.util;
28 import java.util.Locale;
29 import java.util.Map;
31 import javax.tools.Diagnostic;
32 import javax.tools.JavaFileObject;
34 import com.sun.tools.javac.api.DiagnosticFormatter;
35 import com.sun.tools.javac.tree.JCTree;
37 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
39 /** An abstraction of a diagnostic message generated by the compiler.
40 *
41 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
42 * you write code that depends on this, you do so at your own risk.
43 * This code and its internal interfaces are subject to change or
44 * deletion without notice.</b>
45 */
46 public class JCDiagnostic implements Diagnostic<JavaFileObject> {
47 /** A factory for creating diagnostic objects. */
48 public static class Factory {
49 /** The context key for the diagnostic factory. */
50 protected static final Context.Key<JCDiagnostic.Factory> diagnosticFactoryKey =
51 new Context.Key<JCDiagnostic.Factory>();
53 /** Get the Factory instance for this context. */
54 public static Factory instance(Context context) {
55 Factory instance = context.get(diagnosticFactoryKey);
56 if (instance == null)
57 instance = new Factory(context);
58 return instance;
59 }
61 DiagnosticFormatter<JCDiagnostic> formatter;
62 final String prefix;
64 /** Create a new diagnostic factory. */
65 protected Factory(Context context) {
66 this(JavacMessages.instance(context), "compiler");
67 context.put(diagnosticFactoryKey, this);
68 }
70 /** Create a new diagnostic factory. */
71 public Factory(JavacMessages messages, String prefix) {
72 this.prefix = prefix;
73 this.formatter = new BasicDiagnosticFormatter(messages);
74 }
76 /**
77 * Create an error diagnostic.
78 * @param source The source of the compilation unit, if any, in which to report the error.
79 * @param pos The source position at which to report the error.
80 * @param key The key for the localized error message.
81 * @param args Fields of the error message.
82 */
83 public JCDiagnostic error(
84 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
85 return create(ERROR, true, source, pos, key, args);
86 }
88 /**
89 * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
90 * @param source The source of the compilation unit, if any, in which to report the warning.
91 * @param pos The source position at which to report the warning.
92 * @param key The key for the localized error message.
93 * @param args Fields of the error message.
94 * @see MandatoryWarningHandler
95 */
96 public JCDiagnostic mandatoryWarning(
97 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
98 return create(WARNING, true, source, pos, key, args);
99 }
101 /**
102 * Create a warning diagnostic.
103 * @param source The source of the compilation unit, if any, in which to report the warning.
104 * @param pos The source position at which to report the warning.
105 * @param key The key for the localized error message.
106 * @param args Fields of the error message.
107 */
108 public JCDiagnostic warning(
109 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
110 return create(WARNING, false, source, pos, key, args);
111 }
113 /**
114 * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
115 * @param key The key for the localized error message.
116 * @param args Fields of the error message.
117 * @see MandatoryWarningHandler
118 */
119 public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
120 return create(NOTE, true, source, null, key, args);
121 }
123 /**
124 * Create a note diagnostic.
125 * @param key The key for the localized error message.
126 * @param args Fields of the error message.
127 */
128 public JCDiagnostic note(String key, Object... args) {
129 return create(NOTE, false, null, null, key, args);
130 }
132 /**
133 * Create a note diagnostic.
134 * @param source The source of the compilation unit, if any, in which to report the note.
135 * @param pos The source position at which to report the note.
136 * @param key The key for the localized error message.
137 * @param args Fields of the error message.
138 */
139 public JCDiagnostic note(
140 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
141 return create(NOTE, false, source, pos, key, args);
142 }
144 /**
145 * Create a fragment diagnostic, for use as an argument in other diagnostics
146 * @param key The key for the localized error message.
147 * @param args Fields of the error message.
148 */
149 public JCDiagnostic fragment(String key, Object... args) {
150 return create(FRAGMENT, false, null, null, key, args);
151 }
153 /**
154 * Create a new diagnostic of the given kind.
155 * @param kind The diagnostic kind
156 * @param isMandatory is diagnostic mandatory?
157 * @param source The source of the compilation unit, if any, in which to report the note.
158 * @param pos The source position at which to report the note.
159 * @param key The key for the localized error message.
160 * @param args Fields of the error message.
161 */
162 public JCDiagnostic create(
163 DiagnosticType kind, boolean isMandatory, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
164 return new JCDiagnostic(formatter, kind, isMandatory, source, pos, qualify(kind, key), args);
165 }
167 protected String qualify(DiagnosticType t, String key) {
168 return prefix + "." + t.key + "." + key;
169 }
170 }
174 /**
175 * Create a fragment diagnostic, for use as an argument in other diagnostics
176 * @param key The key for the localized error message.
177 * @param args Fields of the error message.
178 *
179 */
180 @Deprecated
181 public static JCDiagnostic fragment(String key, Object... args) {
182 return new JCDiagnostic(getFragmentFormatter(),
183 FRAGMENT,
184 false,
185 null,
186 null,
187 "compiler." + FRAGMENT.key + "." + key,
188 args);
189 }
190 //where
191 @Deprecated
192 public static DiagnosticFormatter<JCDiagnostic> getFragmentFormatter() {
193 if (fragmentFormatter == null) {
194 fragmentFormatter = new BasicDiagnosticFormatter(JavacMessages.getDefaultMessages());
195 }
196 return fragmentFormatter;
197 }
199 /**
200 * A DiagnosticType defines the type of the diagnostic.
201 **/
202 public enum DiagnosticType {
203 /** A fragment of an enclosing diagnostic. */
204 FRAGMENT("misc"),
205 /** A note: similar to, but less serious than, a warning. */
206 NOTE("note"),
207 /** A warning. */
208 WARNING("warn"),
209 /** An error. */
210 ERROR("err");
212 final String key;
214 /** Create a DiagnosticType.
215 * @param key A string used to create the resource key for the diagnostic.
216 */
217 DiagnosticType(String key) {
218 this.key = key;
219 }
220 };
222 /**
223 * A DiagnosticPosition provides information about the positions in a file
224 * that gave rise to a diagnostic. It always defines a "preferred" position
225 * that most accurately defines the location of the diagnostic, it may also
226 * provide a related tree node that spans that location.
227 */
228 public static interface DiagnosticPosition {
229 /** Gets the tree node, if any, to which the diagnostic applies. */
230 JCTree getTree();
231 /** If there is a tree node, get the start position of the tree node.
232 * Otherwise, just returns the same as getPreferredPosition(). */
233 int getStartPosition();
234 /** Get the position within the file that most accurately defines the
235 * location for the diagnostic. */
236 int getPreferredPosition();
237 /** If there is a tree node, and if endPositions are available, get
238 * the end position of the tree node. Otherwise, just returns the
239 * same as getPreferredPosition(). */
240 int getEndPosition(Map<JCTree, Integer> endPosTable);
241 }
243 /**
244 * A DiagnosticPosition that simply identifies a position, but no related
245 * tree node, as the location for a diagnostic. Used for scanner and parser
246 * diagnostics. */
247 public static class SimpleDiagnosticPosition implements DiagnosticPosition {
248 public SimpleDiagnosticPosition(int pos) {
249 this.pos = pos;
250 }
252 public JCTree getTree() {
253 return null;
254 }
256 public int getStartPosition() {
257 return pos;
258 }
260 public int getPreferredPosition() {
261 return pos;
262 }
264 public int getEndPosition(Map<JCTree, Integer> endPosTable) {
265 return pos;
266 }
268 private final int pos;
269 }
271 private final DiagnosticType type;
272 private final DiagnosticSource source;
273 private final DiagnosticPosition position;
274 private final int line;
275 private final int column;
276 private final String key;
277 protected Object[] args;
278 private boolean mandatory;
280 /**
281 * Create a diagnostic object.
282 * @param messages the resource for localized messages
283 * @param dt the type of diagnostic
284 * @param name the name of the source file, or null if none.
285 * @param pos the character offset within the source file, if given.
286 * @param key a resource key to identify the text of the diagnostic
287 * @param args arguments to be included in the text of the diagnostic
288 */
289 protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
290 DiagnosticType dt,
291 boolean mandatory,
292 DiagnosticSource source,
293 DiagnosticPosition pos,
294 String key,
295 Object ... args) {
296 if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
297 throw new IllegalArgumentException();
299 this.defaultFormatter = formatter;
300 this.type = dt;
301 this.mandatory = mandatory;
302 this.source = source;
303 this.position = pos;
304 this.key = key;
305 this.args = args;
307 int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
308 if (n == Position.NOPOS || source == null)
309 line = column = -1;
310 else {
311 line = source.getLineNumber(n);
312 column = source.getColumnNumber(n, true);
313 }
314 }
316 /**
317 * Get the type of this diagnostic.
318 * @return the type of this diagnostic
319 */
320 public DiagnosticType getType() {
321 return type;
322 }
324 /**
325 * Get the subdiagnostic list
326 * @return subdiagnostic list
327 */
328 public List<JCDiagnostic> getSubdiagnostics() {
329 return List.nil();
330 }
332 public boolean isMultiline() {
333 return false;
334 }
336 /**
337 * Check whether or not this diagnostic is required to be shown.
338 * @return true if this diagnostic is required to be shown.
339 */
340 public boolean isMandatory() {
341 return mandatory;
342 }
344 /**
345 * Get the name of the source file referred to by this diagnostic.
346 * @return the name of the source referred to with this diagnostic, or null if none
347 */
348 public JavaFileObject getSource() {
349 if (source == null)
350 return null;
351 else
352 return source.getFile();
353 }
355 /**
356 * Get the source referred to by this diagnostic.
357 * @return the source referred to with this diagnostic, or null if none
358 */
359 public DiagnosticSource getDiagnosticSource() {
360 return source;
361 }
363 protected int getIntStartPosition() {
364 return (position == null ? Position.NOPOS : position.getStartPosition());
365 }
367 protected int getIntPosition() {
368 return (position == null ? Position.NOPOS : position.getPreferredPosition());
369 }
371 protected int getIntEndPosition() {
372 return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
373 }
375 public long getStartPosition() {
376 return getIntStartPosition();
377 }
379 public long getPosition() {
380 return getIntPosition();
381 }
383 public long getEndPosition() {
384 return getIntEndPosition();
385 }
387 /**
388 * Get the line number within the source referred to by this diagnostic.
389 * @return the line number within the source referred to by this diagnostic
390 */
391 public long getLineNumber() {
392 return line;
393 }
395 /**
396 * Get the column number within the line of source referred to by this diagnostic.
397 * @return the column number within the line of source referred to by this diagnostic
398 */
399 public long getColumnNumber() {
400 return column;
401 }
403 /**
404 * Get the arguments to be included in the text of the diagnostic.
405 * @return the arguments to be included in the text of the diagnostic
406 */
407 public Object[] getArgs() {
408 return args;
409 }
411 /**
412 * Get the prefix string associated with this type of diagnostic.
413 * @return the prefix string associated with this type of diagnostic
414 */
415 public String getPrefix() {
416 return getPrefix(type);
417 }
419 /**
420 * Get the prefix string associated with a particular type of diagnostic.
421 * @return the prefix string associated with a particular type of diagnostic
422 */
423 public String getPrefix(DiagnosticType dt) {
424 return defaultFormatter.formatKind(this, Locale.getDefault());
425 }
427 /**
428 * Return the standard presentation of this diagnostic.
429 */
430 @Override
431 public String toString() {
432 return defaultFormatter.format(this,Locale.getDefault());
433 }
435 private DiagnosticFormatter<JCDiagnostic> defaultFormatter;
436 @Deprecated
437 private static DiagnosticFormatter<JCDiagnostic> fragmentFormatter;
439 // Methods for javax.tools.Diagnostic
441 public Diagnostic.Kind getKind() {
442 switch (type) {
443 case NOTE:
444 return Diagnostic.Kind.NOTE;
445 case WARNING:
446 return mandatory ? Diagnostic.Kind.MANDATORY_WARNING
447 : Diagnostic.Kind.WARNING;
448 case ERROR:
449 return Diagnostic.Kind.ERROR;
450 default:
451 return Diagnostic.Kind.OTHER;
452 }
453 }
455 public String getCode() {
456 return key;
457 }
459 public String getMessage(Locale locale) {
460 return defaultFormatter.formatMessage(this, locale);
461 }
463 public static class MultilineDiagnostic extends JCDiagnostic {
465 private final List<JCDiagnostic> subdiagnostics;
467 public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) {
468 super(other.defaultFormatter,
469 other.getType(),
470 other.isMandatory(),
471 other.getDiagnosticSource(),
472 other.position,
473 other.getCode(),
474 other.getArgs());
475 this.subdiagnostics = subdiagnostics;
476 }
478 @Override
479 public List<JCDiagnostic> getSubdiagnostics() {
480 return subdiagnostics;
481 }
483 @Override
484 public boolean isMultiline() {
485 return true;
486 }
487 }
488 }