Tue, 29 Mar 2011 16:41:18 +0100
7027157: Project Coin: javac warnings for AutoCloseable.close throwing InterruptedException
Summary: javac should warn about use/declaration of AutoCloseable subclasses that can throw InterruptedException
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javac.util;
28 import java.util.EnumSet;
29 import java.util.Locale;
30 import java.util.Map;
31 import java.util.Set;
33 import javax.tools.Diagnostic;
34 import javax.tools.JavaFileObject;
36 import com.sun.tools.javac.api.DiagnosticFormatter;
37 import com.sun.tools.javac.code.Lint.LintCategory;
38 import com.sun.tools.javac.tree.JCTree;
40 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
42 /** An abstraction of a diagnostic message generated by the compiler.
43 *
44 * <p><b>This is NOT part of any supported API.
45 * If you write code that depends on this, you do so at your own risk.
46 * This code and its internal interfaces are subject to change or
47 * deletion without notice.</b>
48 */
49 public class JCDiagnostic implements Diagnostic<JavaFileObject> {
50 /** A factory for creating diagnostic objects. */
51 public static class Factory {
52 /** The context key for the diagnostic factory. */
53 protected static final Context.Key<JCDiagnostic.Factory> diagnosticFactoryKey =
54 new Context.Key<JCDiagnostic.Factory>();
56 /** Get the Factory instance for this context. */
57 public static Factory instance(Context context) {
58 Factory instance = context.get(diagnosticFactoryKey);
59 if (instance == null)
60 instance = new Factory(context);
61 return instance;
62 }
64 DiagnosticFormatter<JCDiagnostic> formatter;
65 final String prefix;
66 final Set<DiagnosticFlag> defaultErrorFlags;
68 /** Create a new diagnostic factory. */
69 protected Factory(Context context) {
70 this(JavacMessages.instance(context), "compiler");
71 context.put(diagnosticFactoryKey, this);
73 Options options = Options.instance(context);
74 if (options.isSet("onlySyntaxErrorsUnrecoverable"))
75 defaultErrorFlags.add(DiagnosticFlag.RECOVERABLE);
76 }
78 /** Create a new diagnostic factory. */
79 public Factory(JavacMessages messages, String prefix) {
80 this.prefix = prefix;
81 this.formatter = new BasicDiagnosticFormatter(messages);
82 defaultErrorFlags = EnumSet.of(DiagnosticFlag.MANDATORY);
83 }
85 /**
86 * Create an error diagnostic.
87 * @param source The source of the compilation unit, if any, in which to report the error.
88 * @param pos The source position at which to report the error.
89 * @param key The key for the localized error message.
90 * @param args Fields of the error message.
91 */
92 public JCDiagnostic error(
93 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
94 return create(ERROR, null, defaultErrorFlags, source, pos, key, args);
95 }
97 /**
98 * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
99 * @param source The source of the compilation unit, if any, in which to report the warning.
100 * @param pos The source position at which to report the warning.
101 * @param key The key for the localized warning message.
102 * @param args Fields of the warning message.
103 * @see MandatoryWarningHandler
104 */
105 public JCDiagnostic mandatoryWarning(
106 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
107 return create(WARNING, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
108 }
110 /**
111 * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
112 * @param lc The lint category for the diagnostic
113 * @param source The source of the compilation unit, if any, in which to report the warning.
114 * @param pos The source position at which to report the warning.
115 * @param key The key for the localized warning message.
116 * @param args Fields of the warning message.
117 * @see MandatoryWarningHandler
118 */
119 public JCDiagnostic mandatoryWarning(
120 LintCategory lc,
121 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
122 return create(WARNING, lc, EnumSet.of(DiagnosticFlag.MANDATORY), source, pos, key, args);
123 }
125 /**
126 * Create a warning diagnostic.
127 * @param lc The lint category for the diagnostic
128 * @param key The key for the localized error message.
129 * @param args Fields of the warning message.
130 * @see MandatoryWarningHandler
131 */
132 public JCDiagnostic warning(
133 LintCategory lc, String key, Object... args) {
134 return create(WARNING, lc, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
135 }
137 /**
138 * Create a warning diagnostic.
139 * @param source The source of the compilation unit, if any, in which to report the warning.
140 * @param pos The source position at which to report the warning.
141 * @param key The key for the localized warning message.
142 * @param args Fields of the warning message.
143 */
144 public JCDiagnostic warning(
145 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
146 return create(WARNING, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
147 }
149 /**
150 * Create a warning diagnostic.
151 * @param lc The lint category for the diagnostic
152 * @param source The source of the compilation unit, if any, in which to report the warning.
153 * @param pos The source position at which to report the warning.
154 * @param key The key for the localized warning message.
155 * @param args Fields of the warning message.
156 * @see MandatoryWarningHandler
157 */
158 public JCDiagnostic warning(
159 LintCategory lc, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
160 return create(WARNING, lc, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
161 }
163 /**
164 * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
165 * @param key The key for the localized message.
166 * @param args Fields of the message.
167 * @see MandatoryWarningHandler
168 */
169 public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
170 return create(NOTE, null, EnumSet.of(DiagnosticFlag.MANDATORY), source, null, key, args);
171 }
173 /**
174 * Create a note diagnostic.
175 * @param key The key for the localized error message.
176 * @param args Fields of the message.
177 */
178 public JCDiagnostic note(String key, Object... args) {
179 return create(NOTE, null, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
180 }
182 /**
183 * Create a note diagnostic.
184 * @param source The source of the compilation unit, if any, in which to report the note.
185 * @param pos The source position at which to report the note.
186 * @param key The key for the localized message.
187 * @param args Fields of the message.
188 */
189 public JCDiagnostic note(
190 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
191 return create(NOTE, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
192 }
194 /**
195 * Create a fragment diagnostic, for use as an argument in other diagnostics
196 * @param key The key for the localized message.
197 * @param args Fields of the message.
198 */
199 public JCDiagnostic fragment(String key, Object... args) {
200 return create(FRAGMENT, null, EnumSet.noneOf(DiagnosticFlag.class), null, null, key, args);
201 }
203 /**
204 * Create a new diagnostic of the given kind, which is not mandatory and which has
205 * no lint category.
206 * @param kind The diagnostic kind
207 * @param ls The lint category, if applicable, or null
208 * @param source The source of the compilation unit, if any, in which to report the message.
209 * @param pos The source position at which to report the message.
210 * @param key The key for the localized message.
211 * @param args Fields of the message.
212 */
213 public JCDiagnostic create(
214 DiagnosticType kind, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
215 return create(kind, null, EnumSet.noneOf(DiagnosticFlag.class), source, pos, key, args);
216 }
218 /**
219 * Create a new diagnostic of the given kind.
220 * @param kind The diagnostic kind
221 * @param lc The lint category, if applicable, or null
222 * @param isMandatory is diagnostic mandatory?
223 * @param source The source of the compilation unit, if any, in which to report the message.
224 * @param pos The source position at which to report the message.
225 * @param key The key for the localized message.
226 * @param args Fields of the message.
227 */
228 public JCDiagnostic create(
229 DiagnosticType kind, LintCategory lc, Set<DiagnosticFlag> flags, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
230 return new JCDiagnostic(formatter, kind, lc, flags, source, pos, qualify(kind, key), args);
231 }
233 protected String qualify(DiagnosticType t, String key) {
234 return prefix + "." + t.key + "." + key;
235 }
236 }
240 /**
241 * Create a fragment diagnostic, for use as an argument in other diagnostics
242 * @param key The key for the localized error message.
243 * @param args Fields of the error message.
244 *
245 */
246 @Deprecated
247 public static JCDiagnostic fragment(String key, Object... args) {
248 return new JCDiagnostic(getFragmentFormatter(),
249 FRAGMENT,
250 null,
251 EnumSet.noneOf(DiagnosticFlag.class),
252 null,
253 null,
254 "compiler." + FRAGMENT.key + "." + key,
255 args);
256 }
257 //where
258 @Deprecated
259 public static DiagnosticFormatter<JCDiagnostic> getFragmentFormatter() {
260 if (fragmentFormatter == null) {
261 fragmentFormatter = new BasicDiagnosticFormatter(JavacMessages.getDefaultMessages());
262 }
263 return fragmentFormatter;
264 }
266 /**
267 * A DiagnosticType defines the type of the diagnostic.
268 **/
269 public enum DiagnosticType {
270 /** A fragment of an enclosing diagnostic. */
271 FRAGMENT("misc"),
272 /** A note: similar to, but less serious than, a warning. */
273 NOTE("note"),
274 /** A warning. */
275 WARNING("warn"),
276 /** An error. */
277 ERROR("err");
279 final String key;
281 /** Create a DiagnosticType.
282 * @param key A string used to create the resource key for the diagnostic.
283 */
284 DiagnosticType(String key) {
285 this.key = key;
286 }
287 };
289 /**
290 * A DiagnosticPosition provides information about the positions in a file
291 * that gave rise to a diagnostic. It always defines a "preferred" position
292 * that most accurately defines the location of the diagnostic, it may also
293 * provide a related tree node that spans that location.
294 */
295 public static interface DiagnosticPosition {
296 /** Gets the tree node, if any, to which the diagnostic applies. */
297 JCTree getTree();
298 /** If there is a tree node, get the start position of the tree node.
299 * Otherwise, just returns the same as getPreferredPosition(). */
300 int getStartPosition();
301 /** Get the position within the file that most accurately defines the
302 * location for the diagnostic. */
303 int getPreferredPosition();
304 /** If there is a tree node, and if endPositions are available, get
305 * the end position of the tree node. Otherwise, just returns the
306 * same as getPreferredPosition(). */
307 int getEndPosition(Map<JCTree, Integer> endPosTable);
308 }
310 /**
311 * A DiagnosticPosition that simply identifies a position, but no related
312 * tree node, as the location for a diagnostic. Used for scanner and parser
313 * diagnostics. */
314 public static class SimpleDiagnosticPosition implements DiagnosticPosition {
315 public SimpleDiagnosticPosition(int pos) {
316 this.pos = pos;
317 }
319 public JCTree getTree() {
320 return null;
321 }
323 public int getStartPosition() {
324 return pos;
325 }
327 public int getPreferredPosition() {
328 return pos;
329 }
331 public int getEndPosition(Map<JCTree, Integer> endPosTable) {
332 return pos;
333 }
335 private final int pos;
336 }
338 public enum DiagnosticFlag {
339 MANDATORY,
340 RESOLVE_ERROR,
341 SYNTAX,
342 RECOVERABLE
343 }
345 private final DiagnosticType type;
346 private final DiagnosticSource source;
347 private final DiagnosticPosition position;
348 private final int line;
349 private final int column;
350 private final String key;
351 protected final Object[] args;
352 private final Set<DiagnosticFlag> flags;
353 private final LintCategory lintCategory;
355 /**
356 * Create a diagnostic object.
357 * @param fomatter the formatter to use for the diagnostic
358 * @param dt the type of diagnostic
359 * @param lc the lint category for the diagnostic
360 * @param source the name of the source file, or null if none.
361 * @param pos the character offset within the source file, if given.
362 * @param key a resource key to identify the text of the diagnostic
363 * @param args arguments to be included in the text of the diagnostic
364 */
365 protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
366 DiagnosticType dt,
367 LintCategory lc,
368 Set<DiagnosticFlag> flags,
369 DiagnosticSource source,
370 DiagnosticPosition pos,
371 String key,
372 Object... args) {
373 if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
374 throw new IllegalArgumentException();
376 this.defaultFormatter = formatter;
377 this.type = dt;
378 this.lintCategory = lc;
379 this.flags = flags;
380 this.source = source;
381 this.position = pos;
382 this.key = key;
383 this.args = args;
385 int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
386 if (n == Position.NOPOS || source == null)
387 line = column = -1;
388 else {
389 line = source.getLineNumber(n);
390 column = source.getColumnNumber(n, true);
391 }
392 }
394 /**
395 * Get the type of this diagnostic.
396 * @return the type of this diagnostic
397 */
398 public DiagnosticType getType() {
399 return type;
400 }
402 /**
403 * Get the subdiagnostic list
404 * @return subdiagnostic list
405 */
406 public List<JCDiagnostic> getSubdiagnostics() {
407 return List.nil();
408 }
410 public boolean isMultiline() {
411 return false;
412 }
414 /**
415 * Check whether or not this diagnostic is required to be shown.
416 * @return true if this diagnostic is required to be shown.
417 */
418 public boolean isMandatory() {
419 return flags.contains(DiagnosticFlag.MANDATORY);
420 }
422 /**
423 * Check whether this diagnostic has an associated lint category.
424 */
425 public boolean hasLintCategory() {
426 return (lintCategory != null);
427 }
429 /**
430 * Get the associated lint category, or null if none.
431 */
432 public LintCategory getLintCategory() {
433 return lintCategory;
434 }
436 /**
437 * Get the name of the source file referred to by this diagnostic.
438 * @return the name of the source referred to with this diagnostic, or null if none
439 */
440 public JavaFileObject getSource() {
441 if (source == null)
442 return null;
443 else
444 return source.getFile();
445 }
447 /**
448 * Get the source referred to by this diagnostic.
449 * @return the source referred to with this diagnostic, or null if none
450 */
451 public DiagnosticSource getDiagnosticSource() {
452 return source;
453 }
455 protected int getIntStartPosition() {
456 return (position == null ? Position.NOPOS : position.getStartPosition());
457 }
459 protected int getIntPosition() {
460 return (position == null ? Position.NOPOS : position.getPreferredPosition());
461 }
463 protected int getIntEndPosition() {
464 return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
465 }
467 public long getStartPosition() {
468 return getIntStartPosition();
469 }
471 public long getPosition() {
472 return getIntPosition();
473 }
475 public long getEndPosition() {
476 return getIntEndPosition();
477 }
479 /**
480 * Get the line number within the source referred to by this diagnostic.
481 * @return the line number within the source referred to by this diagnostic
482 */
483 public long getLineNumber() {
484 return line;
485 }
487 /**
488 * Get the column number within the line of source referred to by this diagnostic.
489 * @return the column number within the line of source referred to by this diagnostic
490 */
491 public long getColumnNumber() {
492 return column;
493 }
495 /**
496 * Get the arguments to be included in the text of the diagnostic.
497 * @return the arguments to be included in the text of the diagnostic
498 */
499 public Object[] getArgs() {
500 return args;
501 }
503 /**
504 * Get the prefix string associated with this type of diagnostic.
505 * @return the prefix string associated with this type of diagnostic
506 */
507 public String getPrefix() {
508 return getPrefix(type);
509 }
511 /**
512 * Get the prefix string associated with a particular type of diagnostic.
513 * @return the prefix string associated with a particular type of diagnostic
514 */
515 public String getPrefix(DiagnosticType dt) {
516 return defaultFormatter.formatKind(this, Locale.getDefault());
517 }
519 /**
520 * Return the standard presentation of this diagnostic.
521 */
522 @Override
523 public String toString() {
524 return defaultFormatter.format(this,Locale.getDefault());
525 }
527 private DiagnosticFormatter<JCDiagnostic> defaultFormatter;
528 @Deprecated
529 private static DiagnosticFormatter<JCDiagnostic> fragmentFormatter;
531 // Methods for javax.tools.Diagnostic
533 public Diagnostic.Kind getKind() {
534 switch (type) {
535 case NOTE:
536 return Diagnostic.Kind.NOTE;
537 case WARNING:
538 return flags.contains(DiagnosticFlag.MANDATORY)
539 ? Diagnostic.Kind.MANDATORY_WARNING
540 : Diagnostic.Kind.WARNING;
541 case ERROR:
542 return Diagnostic.Kind.ERROR;
543 default:
544 return Diagnostic.Kind.OTHER;
545 }
546 }
548 public String getCode() {
549 return key;
550 }
552 public String getMessage(Locale locale) {
553 return defaultFormatter.formatMessage(this, locale);
554 }
556 public void setFlag(DiagnosticFlag flag) {
557 flags.add(flag);
559 if (type == DiagnosticType.ERROR) {
560 switch (flag) {
561 case SYNTAX:
562 flags.remove(DiagnosticFlag.RECOVERABLE);
563 break;
564 case RESOLVE_ERROR:
565 flags.add(DiagnosticFlag.RECOVERABLE);
566 break;
567 }
568 }
569 }
571 public boolean isFlagSet(DiagnosticFlag flag) {
572 return flags.contains(flag);
573 }
575 public static class MultilineDiagnostic extends JCDiagnostic {
577 private final List<JCDiagnostic> subdiagnostics;
579 public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) {
580 super(other.defaultFormatter,
581 other.getType(),
582 other.getLintCategory(),
583 other.flags,
584 other.getDiagnosticSource(),
585 other.position,
586 other.getCode(),
587 other.getArgs());
588 this.subdiagnostics = subdiagnostics;
589 }
591 @Override
592 public List<JCDiagnostic> getSubdiagnostics() {
593 return subdiagnostics;
594 }
596 @Override
597 public boolean isMultiline() {
598 return true;
599 }
600 }
601 }