1.1 --- a/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Mon Mar 09 13:34:19 2009 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Mon Mar 09 23:53:41 2009 -0700 1.3 @@ -38,6 +38,10 @@ 1.4 import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.MultilineLimit; 1.5 import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind; 1.6 import com.sun.tools.javac.api.Formattable; 1.7 +import com.sun.tools.javac.code.Printer; 1.8 +import com.sun.tools.javac.code.Symbol; 1.9 +import com.sun.tools.javac.code.Type; 1.10 +import com.sun.tools.javac.code.Type.CapturedType; 1.11 import com.sun.tools.javac.file.JavacFileManager; 1.12 1.13 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*; 1.14 @@ -60,16 +64,31 @@ 1.15 * JavacMessages object used by this formatter for i18n. 1.16 */ 1.17 protected JavacMessages messages; 1.18 + 1.19 + /** 1.20 + * Configuration object used by this formatter 1.21 + */ 1.22 private SimpleConfiguration config; 1.23 + 1.24 + /** 1.25 + * Current depth level of the disgnostic being formatted 1.26 + * (!= 0 for subdiagnostics) 1.27 + */ 1.28 protected int depth = 0; 1.29 1.30 /** 1.31 + * Printer instance to be used for formatting types/symbol 1.32 + */ 1.33 + protected Printer printer; 1.34 + 1.35 + /** 1.36 * Initialize an AbstractDiagnosticFormatter by setting its JavacMessages object. 1.37 * @param messages 1.38 */ 1.39 protected AbstractDiagnosticFormatter(JavacMessages messages, SimpleConfiguration config) { 1.40 this.messages = messages; 1.41 this.config = config; 1.42 + this.printer = new FormatterPrinter(); 1.43 } 1.44 1.45 public String formatKind(JCDiagnostic d, Locale l) { 1.46 @@ -83,6 +102,14 @@ 1.47 } 1.48 } 1.49 1.50 + @Override 1.51 + public String format(JCDiagnostic d, Locale locale) { 1.52 + printer = new FormatterPrinter(); 1.53 + return formatDiagnostic(d, locale); 1.54 + } 1.55 + 1.56 + abstract String formatDiagnostic(JCDiagnostic d, Locale locale); 1.57 + 1.58 public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) { 1.59 assert (d.getPosition() != Position.NOPOS); 1.60 return String.valueOf(getPosition(d, pk)); 1.61 @@ -143,12 +170,21 @@ 1.62 else if (arg instanceof Iterable<?>) { 1.63 return formatIterable(d, (Iterable<?>)arg, l); 1.64 } 1.65 - else if (arg instanceof JavaFileObject) 1.66 + else if (arg instanceof Type) { 1.67 + return printer.visit((Type)arg, l); 1.68 + } 1.69 + else if (arg instanceof Symbol) { 1.70 + return printer.visit((Symbol)arg, l); 1.71 + } 1.72 + else if (arg instanceof JavaFileObject) { 1.73 return JavacFileManager.getJavacBaseFileName((JavaFileObject)arg); 1.74 - else if (arg instanceof Formattable) 1.75 + } 1.76 + else if (arg instanceof Formattable) { 1.77 return ((Formattable)arg).toString(l, messages); 1.78 - else 1.79 + } 1.80 + else { 1.81 return String.valueOf(arg); 1.82 + } 1.83 } 1.84 1.85 /** 1.86 @@ -404,4 +440,43 @@ 1.87 return caretEnabled; 1.88 } 1.89 } 1.90 + 1.91 + /** 1.92 + * An enhanced printer for formatting types/symbols used by 1.93 + * AbstractDiagnosticFormatter. Provides alternate numbering of captured 1.94 + * types (they are numbered starting from 1 on each new diagnostic, instead 1.95 + * of relying on the underlying hashcode() method which generates unstable 1.96 + * output). Also detects cycles in wildcard messages (e.g. if the wildcard 1.97 + * type referred by a given captured type C contains C itself) which might 1.98 + * lead to infinite loops. 1.99 + */ 1.100 + protected class FormatterPrinter extends Printer { 1.101 + 1.102 + List<Type> allCaptured = List.nil(); 1.103 + List<Type> seenCaptured = List.nil(); 1.104 + 1.105 + @Override 1.106 + protected String localize(Locale locale, String key, Object... args) { 1.107 + return AbstractDiagnosticFormatter.this.localize(locale, key, args); 1.108 + } 1.109 + 1.110 + @Override 1.111 + public String visitCapturedType(CapturedType t, Locale locale) { 1.112 + if (seenCaptured.contains(t)) 1.113 + return localize(locale, "compiler.misc.type.captureof.1", 1.114 + allCaptured.indexOf(t) + 1); 1.115 + else { 1.116 + try { 1.117 + seenCaptured = seenCaptured.prepend(t); 1.118 + allCaptured = allCaptured.append(t); 1.119 + return localize(locale, "compiler.misc.type.captureof", 1.120 + allCaptured.indexOf(t) + 1, 1.121 + visit(t.wildcard, locale)); 1.122 + } 1.123 + finally { 1.124 + seenCaptured = seenCaptured.tail; 1.125 + } 1.126 + } 1.127 + } 1.128 + } 1.129 }