Tue, 11 Aug 2009 01:13:14 +0100
6521805: Regression: JDK5/JDK6 javac allows write access to outer class reference
Summary: javac should warn/complain about identifiers with the same name as synthetic symbol
Reviewed-by: jjg
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.file.JavacFileManager;
36 import com.sun.tools.javac.tree.JCTree;
38 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
40 /** An abstraction of a diagnostic message generated by the compiler.
41 *
42 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
43 * you write code that depends on this, you do so at your own risk.
44 * This code and its internal interfaces are subject to change or
45 * deletion without notice.</b>
46 */
47 public class JCDiagnostic implements Diagnostic<JavaFileObject> {
48 /** A factory for creating diagnostic objects. */
49 public static class Factory {
50 /** The context key for the diagnostic factory. */
51 protected static final Context.Key<JCDiagnostic.Factory> diagnosticFactoryKey =
52 new Context.Key<JCDiagnostic.Factory>();
54 /** Get the Factory instance for this context. */
55 public static Factory instance(Context context) {
56 Factory instance = context.get(diagnosticFactoryKey);
57 if (instance == null)
58 instance = new Factory(context);
59 return instance;
60 }
62 DiagnosticFormatter<JCDiagnostic> formatter;
63 final String prefix;
65 /** Create a new diagnostic factory. */
66 protected Factory(Context context) {
67 this(JavacMessages.instance(context), "compiler");
68 context.put(diagnosticFactoryKey, this);
69 }
71 /** Create a new diagnostic factory. */
72 public Factory(JavacMessages messages, String prefix) {
73 this.prefix = prefix;
74 this.formatter = new BasicDiagnosticFormatter(messages);
75 }
77 /**
78 * Create an error diagnostic.
79 * @param source The source of the compilation unit, if any, in which to report the error.
80 * @param pos The source position at which to report the error.
81 * @param key The key for the localized error message.
82 * @param args Fields of the error message.
83 */
84 public JCDiagnostic error(
85 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
86 return create(ERROR, true, source, pos, key, args);
87 }
89 /**
90 * Create a warning diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
91 * @param source The source of the compilation unit, if any, in which to report the warning.
92 * @param pos The source position at which to report the warning.
93 * @param key The key for the localized error message.
94 * @param args Fields of the error message.
95 * @see MandatoryWarningHandler
96 */
97 public JCDiagnostic mandatoryWarning(
98 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
99 return create(WARNING, true, source, pos, key, args);
100 }
102 /**
103 * Create a warning diagnostic.
104 * @param source The source of the compilation unit, if any, in which to report the warning.
105 * @param pos The source position at which to report the warning.
106 * @param key The key for the localized error message.
107 * @param args Fields of the error message.
108 */
109 public JCDiagnostic warning(
110 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
111 return create(WARNING, false, source, pos, key, args);
112 }
114 /**
115 * Create a note diagnostic that will not be hidden by the -nowarn or -Xlint:none options.
116 * @param key The key for the localized error message.
117 * @param args Fields of the error message.
118 * @see MandatoryWarningHandler
119 */
120 public JCDiagnostic mandatoryNote(DiagnosticSource source, String key, Object... args) {
121 return create(NOTE, true, source, null, key, args);
122 }
124 /**
125 * Create a note diagnostic.
126 * @param key The key for the localized error message.
127 * @param args Fields of the error message.
128 */
129 public JCDiagnostic note(String key, Object... args) {
130 return create(NOTE, false, null, null, key, args);
131 }
133 /**
134 * Create a note diagnostic.
135 * @param source The source of the compilation unit, if any, in which to report the note.
136 * @param pos The source position at which to report the note.
137 * @param key The key for the localized error message.
138 * @param args Fields of the error message.
139 */
140 public JCDiagnostic note(
141 DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
142 return create(NOTE, false, source, pos, key, args);
143 }
145 /**
146 * Create a fragment diagnostic, for use as an argument in other diagnostics
147 * @param key The key for the localized error message.
148 * @param args Fields of the error message.
149 */
150 public JCDiagnostic fragment(String key, Object... args) {
151 return create(FRAGMENT, false, null, null, key, args);
152 }
154 /**
155 * Create a new diagnostic of the given kind.
156 * @param kind The diagnostic kind
157 * @param isMandatory is diagnostic mandatory?
158 * @param source The source of the compilation unit, if any, in which to report the note.
159 * @param pos The source position at which to report the note.
160 * @param key The key for the localized error message.
161 * @param args Fields of the error message.
162 */
163 public JCDiagnostic create(
164 DiagnosticType kind, boolean isMandatory, DiagnosticSource source, DiagnosticPosition pos, String key, Object... args) {
165 return new JCDiagnostic(formatter, kind, isMandatory, source, pos, qualify(kind, key), args);
166 }
168 protected String qualify(DiagnosticType t, String key) {
169 return prefix + "." + t.key + "." + key;
170 }
171 }
175 /**
176 * Create a fragment diagnostic, for use as an argument in other diagnostics
177 * @param key The key for the localized error message.
178 * @param args Fields of the error message.
179 *
180 */
181 @Deprecated
182 public static JCDiagnostic fragment(String key, Object... args) {
183 return new JCDiagnostic(getFragmentFormatter(),
184 FRAGMENT,
185 false,
186 null,
187 null,
188 "compiler." + FRAGMENT.key + "." + key,
189 args);
190 }
191 //where
192 @Deprecated
193 public static DiagnosticFormatter<JCDiagnostic> getFragmentFormatter() {
194 if (fragmentFormatter == null) {
195 fragmentFormatter = new BasicDiagnosticFormatter(JavacMessages.getDefaultMessages());
196 }
197 return fragmentFormatter;
198 }
200 /**
201 * A DiagnosticType defines the type of the diagnostic.
202 **/
203 public enum DiagnosticType {
204 /** A fragment of an enclosing diagnostic. */
205 FRAGMENT("misc"),
206 /** A note: similar to, but less serious than, a warning. */
207 NOTE("note"),
208 /** A warning. */
209 WARNING("warn"),
210 /** An error. */
211 ERROR("err");
213 final String key;
215 /** Create a DiagnosticType.
216 * @param key A string used to create the resource key for the diagnostic.
217 */
218 DiagnosticType(String key) {
219 this.key = key;
220 }
221 };
223 /**
224 * A DiagnosticPosition provides information about the positions in a file
225 * that gave rise to a diagnostic. It always defines a "preferred" position
226 * that most accurately defines the location of the diagnostic, it may also
227 * provide a related tree node that spans that location.
228 */
229 public static interface DiagnosticPosition {
230 /** Gets the tree node, if any, to which the diagnostic applies. */
231 JCTree getTree();
232 /** If there is a tree node, get the start position of the tree node.
233 * Otherwise, just returns the same as getPreferredPosition(). */
234 int getStartPosition();
235 /** Get the position within the file that most accurately defines the
236 * location for the diagnostic. */
237 int getPreferredPosition();
238 /** If there is a tree node, and if endPositions are available, get
239 * the end position of the tree node. Otherwise, just returns the
240 * same as getPreferredPosition(). */
241 int getEndPosition(Map<JCTree, Integer> endPosTable);
242 }
244 /**
245 * A DiagnosticPosition that simply identifies a position, but no related
246 * tree node, as the location for a diagnostic. Used for scanner and parser
247 * diagnostics. */
248 public static class SimpleDiagnosticPosition implements DiagnosticPosition {
249 public SimpleDiagnosticPosition(int pos) {
250 this.pos = pos;
251 }
253 public JCTree getTree() {
254 return null;
255 }
257 public int getStartPosition() {
258 return pos;
259 }
261 public int getPreferredPosition() {
262 return pos;
263 }
265 public int getEndPosition(Map<JCTree, Integer> endPosTable) {
266 return pos;
267 }
269 private final int pos;
270 }
272 private final DiagnosticType type;
273 private final DiagnosticSource source;
274 private final DiagnosticPosition position;
275 private final int line;
276 private final int column;
277 private final String key;
278 protected Object[] args;
279 private boolean mandatory;
281 /**
282 * Create a diagnostic object.
283 * @param messages the resource for localized messages
284 * @param dt the type of diagnostic
285 * @param name the name of the source file, or null if none.
286 * @param pos the character offset within the source file, if given.
287 * @param key a resource key to identify the text of the diagnostic
288 * @param args arguments to be included in the text of the diagnostic
289 */
290 protected JCDiagnostic(DiagnosticFormatter<JCDiagnostic> formatter,
291 DiagnosticType dt,
292 boolean mandatory,
293 DiagnosticSource source,
294 DiagnosticPosition pos,
295 String key,
296 Object ... args) {
297 if (source == null && pos != null && pos.getPreferredPosition() != Position.NOPOS)
298 throw new IllegalArgumentException();
300 this.defaultFormatter = formatter;
301 this.type = dt;
302 this.mandatory = mandatory;
303 this.source = source;
304 this.position = pos;
305 this.key = key;
306 this.args = args;
308 int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
309 if (n == Position.NOPOS || source == null)
310 line = column = -1;
311 else {
312 line = source.getLineNumber(n);
313 column = source.getColumnNumber(n, true);
314 }
315 }
317 /**
318 * Get the type of this diagnostic.
319 * @return the type of this diagnostic
320 */
321 public DiagnosticType getType() {
322 return type;
323 }
325 /**
326 * Get the subdiagnostic list
327 * @return subdiagnostic list
328 */
329 public List<JCDiagnostic> getSubdiagnostics() {
330 return List.nil();
331 }
333 public boolean isMultiline() {
334 return false;
335 }
337 /**
338 * Check whether or not this diagnostic is required to be shown.
339 * @return true if this diagnostic is required to be shown.
340 */
341 public boolean isMandatory() {
342 return mandatory;
343 }
345 /**
346 * Get the name of the source file referred to by this diagnostic.
347 * @return the name of the source referred to with this diagnostic, or null if none
348 */
349 public JavaFileObject getSource() {
350 if (source == null)
351 return null;
352 else
353 return source.getFile();
354 }
356 /**
357 * Get the name of the source file referred to by this diagnostic.
358 * @return the name of the source referred to with this diagnostic, or null if none
359 */
360 public String getSourceName() {
361 JavaFileObject s = getSource();
362 return s == null ? null : JavacFileManager.getJavacFileName(s);
363 }
365 /**
366 * Get the source referred to by this diagnostic.
367 * @return the source referred to with this diagnostic, or null if none
368 */
369 public DiagnosticSource getDiagnosticSource() {
370 return source;
371 }
373 protected int getIntStartPosition() {
374 return (position == null ? Position.NOPOS : position.getStartPosition());
375 }
377 protected int getIntPosition() {
378 return (position == null ? Position.NOPOS : position.getPreferredPosition());
379 }
381 protected int getIntEndPosition() {
382 return (position == null ? Position.NOPOS : position.getEndPosition(source.getEndPosTable()));
383 }
385 public long getStartPosition() {
386 return getIntStartPosition();
387 }
389 public long getPosition() {
390 return getIntPosition();
391 }
393 public long getEndPosition() {
394 return getIntEndPosition();
395 }
397 /**
398 * Get the line number within the source referred to by this diagnostic.
399 * @return the line number within the source referred to by this diagnostic
400 */
401 public long getLineNumber() {
402 return line;
403 }
405 /**
406 * Get the column number within the line of source referred to by this diagnostic.
407 * @return the column number within the line of source referred to by this diagnostic
408 */
409 public long getColumnNumber() {
410 return column;
411 }
413 /**
414 * Get the arguments to be included in the text of the diagnostic.
415 * @return the arguments to be included in the text of the diagnostic
416 */
417 public Object[] getArgs() {
418 return args;
419 }
421 /**
422 * Get the prefix string associated with this type of diagnostic.
423 * @return the prefix string associated with this type of diagnostic
424 */
425 public String getPrefix() {
426 return getPrefix(type);
427 }
429 /**
430 * Get the prefix string associated with a particular type of diagnostic.
431 * @return the prefix string associated with a particular type of diagnostic
432 */
433 public String getPrefix(DiagnosticType dt) {
434 return defaultFormatter.formatKind(this, Locale.getDefault());
435 }
437 /**
438 * Return the standard presentation of this diagnostic.
439 */
440 public String toString() {
441 return defaultFormatter.format(this,Locale.getDefault());
442 }
444 private DiagnosticFormatter<JCDiagnostic> defaultFormatter;
445 @Deprecated
446 private static DiagnosticFormatter<JCDiagnostic> fragmentFormatter;
448 // Methods for javax.tools.Diagnostic
450 public Diagnostic.Kind getKind() {
451 switch (type) {
452 case NOTE:
453 return Diagnostic.Kind.NOTE;
454 case WARNING:
455 return mandatory ? Diagnostic.Kind.MANDATORY_WARNING
456 : Diagnostic.Kind.WARNING;
457 case ERROR:
458 return Diagnostic.Kind.ERROR;
459 default:
460 return Diagnostic.Kind.OTHER;
461 }
462 }
464 public String getCode() {
465 return key;
466 }
468 public String getMessage(Locale locale) {
469 return defaultFormatter.formatMessage(this, locale);
470 }
472 public static class MultilineDiagnostic extends JCDiagnostic {
474 private final List<JCDiagnostic> subdiagnostics;
476 public MultilineDiagnostic(JCDiagnostic other, List<JCDiagnostic> subdiagnostics) {
477 super(other.defaultFormatter,
478 other.getType(),
479 other.isMandatory(),
480 other.getDiagnosticSource(),
481 other.position,
482 other.getCode(),
483 other.getArgs());
484 this.subdiagnostics = subdiagnostics;
485 }
487 @Override
488 public List<JCDiagnostic> getSubdiagnostics() {
489 return subdiagnostics;
490 }
492 @Override
493 public boolean isMultiline() {
494 return true;
495 }
496 }
497 }