changeset 393:86b60aa941c6

6799605: Basic/Raw formatters should use type/symbol printer instead of toString() Summary: create new combo type/symbol visitor printer used by all diagnostic formatters Reviewed-by: jjg
author mcimadamore
date Thu, 05 Mar 2009 17:25:37 +0000
parents 9711a6c2db7e
children 6d00caa683b3
files src/share/classes/com/sun/tools/javac/code/Printer.java src/share/classes/com/sun/tools/javac/code/Types.java src/share/classes/com/sun/tools/javac/resources/compiler.properties src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java test/tools/javac/Diagnostics/6799605/T6799605.java test/tools/javac/Diagnostics/6799605/T6799605.out test/tools/javac/NestedInnerClassNames.out test/tools/javac/T6241723.out test/tools/javac/depDocComment/SuppressDeprecation.out test/tools/javac/mandatoryWarnings/deprecated/Test3.out test/tools/javac/mandatoryWarnings/deprecated/Test3b.out test/tools/javac/mandatoryWarnings/deprecated/Test4.out test/tools/javac/mandatoryWarnings/deprecated/Test4b.out test/tools/javac/mandatoryWarnings/deprecated/Test4c.out test/tools/javac/mandatoryWarnings/deprecated/Test4d.out test/tools/javac/positions/T6253161.out test/tools/javac/positions/T6253161a.out test/tools/javac/warnings/Deprecation.lintAll.out test/tools/javac/warnings/Deprecation.lintDeprecation.out
diffstat 21 files changed, 507 insertions(+), 253 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Printer.java	Thu Mar 05 17:25:37 2009 +0000
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.code;
+
+import java.util.Locale;
+
+import com.sun.tools.javac.api.Messages;
+import com.sun.tools.javac.code.Type.*;
+import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+
+import static com.sun.tools.javac.code.TypeTags.*;
+import static com.sun.tools.javac.code.BoundKind.*;
+import static com.sun.tools.javac.code.Flags.*;
+
+/**
+ * A combined type/symbol visitor for generating non-trivial localized string
+ * representation of types and symbols.
+ */
+public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Visitor<String, Locale> {
+
+    /**
+     * This method should be overriden in order to provide proper i18n support.
+     *
+     * @param locale the locale in which the string is to be rendered
+     * @param key the key corresponding to the message to be displayed
+     * @param args a list of optional arguments
+     * @return localized string representation
+     */
+    protected abstract String localize(Locale locale, String key, Object... args);
+
+    /**
+     * Create a printer with default i18n support provided my Messages.
+     * @param messages Messages class to be used for i18n
+     * @return printer visitor instance
+     */
+    public static Printer createStandardPrinter(final Messages messages) {
+        return new Printer() {
+            @Override
+            protected String localize(Locale locale, String key, Object... args) {
+                return messages.getLocalizedString(locale, key, args);
+        }};
+    }
+
+    /**
+     * Get a localized string representation for all the types in the input list.
+     *
+     * @param ts types to be displayed
+     * @param locale the locale in which the string is to be rendered
+     * @return localized string representation
+     */
+    public String visitTypes(List<Type> ts, Locale locale) {
+        ListBuffer<String> sbuf = ListBuffer.lb();
+        for (Type t : ts) {
+            sbuf.append(visit(t, locale));
+        }
+        return sbuf.toList().toString();
+    }
+
+    /**
+     * * Get a localized string represenation for all the symbols in the input list.
+     *
+     * @param ts symbols to be displayed
+     * @param locale the locale in which the string is to be rendered
+     * @return localized string representation
+     */
+    public String visitSymbols(List<Symbol> ts, Locale locale) {
+        ListBuffer<String> sbuf = ListBuffer.lb();
+        for (Symbol t : ts) {
+            sbuf.append(visit(t, locale));
+        }
+        return sbuf.toList().toString();
+    }
+
+    /**
+     * Get a localized string represenation for a given type.
+     *
+     * @param ts type to be displayed
+     * @param locale the locale in which the string is to be rendered
+     * @return localized string representation
+     */
+    public String visit(Type t, Locale locale) {
+        return t.accept(this, locale);
+    }
+
+    /**
+     * Get a localized string represenation for a given symbol.
+     *
+     * @param ts symbol to be displayed
+     * @param locale the locale in which the string is to be rendered
+     * @return localized string representation
+     */
+    public String visit(Symbol s, Locale locale) {
+        return s.accept(this, locale);
+    }
+
+    @Override
+    public String visitCapturedType(CapturedType t, Locale locale) {
+        return localize(locale, "compiler.misc.type.captureof",
+            (t.hashCode() & 0xFFFFFFFFL) % Type.CapturedType.PRIME,
+            visit(t.wildcard, locale));
+    }
+
+    @Override
+    public String visitForAll(ForAll t, Locale locale) {
+        return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale);
+    }
+
+    @Override
+    public String visitUndetVar(UndetVar t, Locale locale) {
+        if (t.inst != null) {
+            return visit(t.inst, locale);
+        } else {
+            return visit(t.qtype, locale) + "?";
+        }
+    }
+
+    @Override
+    public String visitArrayType(ArrayType t, Locale locale) {
+        return visit(t.elemtype, locale) + "[]";
+    }
+
+    @Override
+    public String visitClassType(ClassType t, Locale locale) {
+        StringBuffer buf = new StringBuffer();
+        if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
+            buf.append(visit(t.getEnclosingType(), locale));
+            buf.append(".");
+            buf.append(className(t, false, locale));
+        } else {
+            buf.append(className(t, true, locale));
+        }
+        if (t.getTypeArguments().nonEmpty()) {
+            buf.append('<');
+            buf.append(visitTypes(t.getTypeArguments(), locale));
+            buf.append(">");
+        }
+        return buf.toString();
+    }
+
+    @Override
+    public String visitMethodType(MethodType t, Locale locale) {
+        return "(" + printMethodArgs(t.argtypes, false, locale) + ")" + visit(t.restype, locale);
+    }
+
+    @Override
+    public String visitPackageType(PackageType t, Locale locale) {
+        return t.tsym.getQualifiedName().toString();
+    }
+
+    @Override
+    public String visitWildcardType(WildcardType t, Locale locale) {
+        StringBuffer s = new StringBuffer();
+        s.append(t.kind);
+        if (t.kind != UNBOUND) {
+            s.append(visit(t.type, locale));
+        }
+        return s.toString();
+    }
+
+    @Override
+    public String visitErrorType(ErrorType t, Locale locale) {
+        return visitType(t, locale);
+    }
+
+    @Override
+    public String visitTypeVar(TypeVar t, Locale locale) {
+        return visitType(t, locale);
+    }
+
+    public String visitType(Type t, Locale locale) {
+        String s = (t.tsym == null || t.tsym.name == null)
+                ? localize(locale, "compiler.misc.type.none")
+                : t.tsym.name.toString();
+        return s;
+    }
+
+    /**
+     * Converts a class name into a (possibly localized) string. Anonymous
+     * inner classes gets converted into a localized string.
+     *
+     * @param t the type of the class whose name is to be rendered
+     * @param longform if set, the class' fullname is displayed - if unset the
+     * short name is chosen (w/o package)
+     * @param locale the locale in which the string is to be rendered
+     * @return localized string representation
+     */
+    protected String className(ClassType t, boolean longform, Locale locale) {
+        Symbol sym = t.tsym;
+        if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
+            StringBuffer s = new StringBuffer(visit(t.supertype_field, locale));
+            for (List<Type> is = t.interfaces_field; is.nonEmpty(); is = is.tail) {
+                s.append("&");
+                s.append(visit(is.head, locale));
+            }
+            return s.toString();
+        } else if (sym.name.length() == 0) {
+            String s;
+            ClassType norm = (ClassType) t.tsym.type;
+            if (norm == null) {
+                s = localize(locale, "compiler.misc.anonymous.class", (Object) null);
+            } else if (norm.interfaces_field.nonEmpty()) {
+                s = localize(locale, "compiler.misc.anonymous.class",
+                        visit(norm.interfaces_field.head, locale));
+            } else {
+                s = localize(locale, "compiler.misc.anonymous.class",
+                        visit(norm.supertype_field, locale));
+            }
+            return s;
+        } else if (longform) {
+            return sym.getQualifiedName().toString();
+        } else {
+            return sym.name.toString();
+        }
+    }
+
+    /**
+     * Converts a set of method argument types into their corresponding
+     * localized string representation.
+     *
+     * @param args arguments to be rendered
+     * @param varArgs if true, the last method argument is regarded as a vararg
+     * @param locale the locale in which the string is to be rendered
+     * @return localized string representation
+     */
+    protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
+        if (!varArgs) {
+            return visitTypes(args, locale);
+        } else {
+            StringBuffer buf = new StringBuffer();
+            while (args.tail.nonEmpty()) {
+                buf.append(visit(args.head, locale));
+                args = args.tail;
+                buf.append(',');
+            }
+            if (args.head.tag == ARRAY) {
+                buf.append(visit(((ArrayType) args.head).elemtype, locale));
+                buf.append("...");
+            } else {
+                buf.append(visit(args.head, locale));
+            }
+            return buf.toString();
+        }
+    }
+
+    @Override
+    public String visitClassSymbol(ClassSymbol sym, Locale locale) {
+        return sym.name.isEmpty()
+                ? localize(locale, "compiler.misc.anonymous.class", sym.flatname)
+                : sym.fullname.toString();
+    }
+
+    @Override
+    public String visitMethodSymbol(MethodSymbol s, Locale locale) {
+        if ((s.flags() & BLOCK) != 0) {
+            return s.owner.name.toString();
+        } else {
+            String ms = (s.name == s.name.table.names.init)
+                    ? s.owner.name.toString()
+                    : s.name.toString();
+            if (s.type != null) {
+                if (s.type.tag == FORALL) {
+                    ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
+                }
+                ms += "(" + printMethodArgs(
+                        s.type.getParameterTypes(),
+                        (s.flags() & VARARGS) != 0,
+                        locale) + ")";
+            }
+            return ms;
+        }
+    }
+
+    @Override
+    public String visitOperatorSymbol(OperatorSymbol s, Locale locale) {
+        return visitMethodSymbol(s, locale);
+    }
+
+    @Override
+    public String visitPackageSymbol(PackageSymbol s, Locale locale) {
+        return s.isUnnamed()
+                ? localize(locale, "compiler.misc.unnamed.package")
+                : s.fullname.toString();
+    }
+
+    @Override
+    public String visitTypeSymbol(TypeSymbol s, Locale locale) {
+        return visitSymbol(s, locale);
+    }
+
+    @Override
+    public String visitVarSymbol(VarSymbol s, Locale locale) {
+        return visitSymbol(s, locale);
+    }
+
+    @Override
+    public String visitSymbol(Symbol s, Locale locale) {
+        return s.name.toString();
+    }
+}
--- a/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Mar 05 17:25:13 2009 +0000
+++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Thu Mar 05 17:25:37 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
 
 import java.util.*;
 
+import com.sun.tools.javac.api.Messages;
+
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.List;
 
@@ -2019,7 +2021,7 @@
                 return t;
             else
                 return visit(t);
-        }
+            }
 
         List<Type> subst(List<Type> ts) {
             if (from.tail == null)
@@ -2279,225 +2281,21 @@
     }
     // </editor-fold>
 
-    // <editor-fold defaultstate="collapsed" desc="printType">
     /**
-     * Visitor for generating a string representation of a given type
+     * Helper method for generating a string representation of a given type
      * accordingly to a given locale
      */
     public String toString(Type t, Locale locale) {
-        return typePrinter.visit(t, locale);
+        return Printer.createStandardPrinter(messages).visit(t, locale);
     }
-    // where
-    private TypePrinter typePrinter = new TypePrinter();
 
-    public class TypePrinter extends DefaultTypeVisitor<String, Locale> {
-
-        public String visit(List<Type> ts, Locale locale) {
-            ListBuffer<String> sbuf = lb();
-            for (Type t : ts) {
-                sbuf.append(visit(t, locale));
-            }
-            return sbuf.toList().toString();
-        }
-
-        @Override
-        public String visitCapturedType(CapturedType t, Locale locale) {
-            return messages.getLocalizedString("compiler.misc.type.captureof",
-                        (t.hashCode() & 0xFFFFFFFFL) % Type.CapturedType.PRIME,
-                        visit(t.wildcard, locale));
-        }
-
-        @Override
-        public String visitForAll(ForAll t, Locale locale) {
-            return "<" + visit(t.tvars, locale) + ">" + visit(t.qtype, locale);
-        }
-
-        @Override
-        public String visitUndetVar(UndetVar t, Locale locale) {
-            if (t.inst != null) {
-                return visit(t.inst, locale);
-            } else {
-                return visit(t.qtype, locale) + "?";
-            }
-        }
-
-        @Override
-        public String visitArrayType(ArrayType t, Locale locale) {
-            return visit(t.elemtype, locale) + "[]";
-        }
-
-        @Override
-        public String visitClassType(ClassType t, Locale locale) {
-            StringBuffer buf = new StringBuffer();
-            if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
-                buf.append(visit(t.getEnclosingType(), locale));
-                buf.append(".");
-                buf.append(className(t, false, locale));
-            } else {
-                buf.append(className(t, true, locale));
-            }
-            if (t.getTypeArguments().nonEmpty()) {
-                buf.append('<');
-                buf.append(visit(t.getTypeArguments(), locale));
-                buf.append(">");
-            }
-            return buf.toString();
-        }
-
-        @Override
-        public String visitMethodType(MethodType t, Locale locale) {
-            return "(" + printMethodArgs(t.argtypes, false, locale) + ")" + visit(t.restype, locale);
-        }
-
-        @Override
-        public String visitPackageType(PackageType t, Locale locale) {
-            return t.tsym.getQualifiedName().toString();
-        }
-
-        @Override
-        public String visitWildcardType(WildcardType t, Locale locale) {
-            StringBuffer s = new StringBuffer();
-            s.append(t.kind);
-            if (t.kind != UNBOUND) {
-                s.append(visit(t.type, locale));
-            }
-            return s.toString();
-        }
-
-
-        public String visitType(Type t, Locale locale) {
-            String s = (t.tsym == null || t.tsym.name == null)
-                    ? messages.getLocalizedString("compiler.misc.type.none")
-                    : t.tsym.name.toString();
-            return s;
-        }
-
-        protected String className(ClassType t, boolean longform, Locale locale) {
-            Symbol sym = t.tsym;
-            if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
-                StringBuffer s = new StringBuffer(visit(supertype(t), locale));
-                for (List<Type> is = interfaces(t); is.nonEmpty(); is = is.tail) {
-                    s.append("&");
-                    s.append(visit(is.head, locale));
-                }
-                return s.toString();
-            } else if (sym.name.length() == 0) {
-                String s;
-                ClassType norm = (ClassType) t.tsym.type;
-                if (norm == null) {
-                    s = getLocalizedString(locale, "compiler.misc.anonymous.class", (Object) null);
-                } else if (interfaces(norm).nonEmpty()) {
-                    s = getLocalizedString(locale, "compiler.misc.anonymous.class",
-                            visit(interfaces(norm).head, locale));
-                } else {
-                    s = getLocalizedString(locale, "compiler.misc.anonymous.class",
-                            visit(supertype(norm), locale));
-                }
-                return s;
-            } else if (longform) {
-                return sym.getQualifiedName().toString();
-            } else {
-                return sym.name.toString();
-            }
-        }
-
-        protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
-            if (!varArgs) {
-                return visit(args, locale);
-            } else {
-                StringBuffer buf = new StringBuffer();
-                while (args.tail.nonEmpty()) {
-                    buf.append(visit(args.head, locale));
-                    args = args.tail;
-                    buf.append(',');
-                }
-                if (args.head.tag == ARRAY) {
-                    buf.append(visit(((ArrayType) args.head).elemtype, locale));
-                    buf.append("...");
-                } else {
-                    buf.append(visit(args.head, locale));
-                }
-                return buf.toString();
-            }
-        }
-
-        protected String getLocalizedString(Locale locale, String key, Object... args) {
-            return messages.getLocalizedString(key, args);
-        }
-    };
-    // </editor-fold>
-
-    // <editor-fold defaultstate="collapsed" desc="printSymbol">
     /**
-     * Visitor for generating a string representation of a given symbol
+     * Helper method for generating a string representation of a given type
      * accordingly to a given locale
      */
     public String toString(Symbol t, Locale locale) {
-        return symbolPrinter.visit(t, locale);
+        return Printer.createStandardPrinter(messages).visit(t, locale);
     }
-    // where
-    private SymbolPrinter symbolPrinter = new SymbolPrinter();
-
-    public class SymbolPrinter extends DefaultSymbolVisitor<String, Locale> {
-
-        @Override
-        public String visitClassSymbol(ClassSymbol sym, Locale locale) {
-            return sym.name.isEmpty()
-                    ? getLocalizedString(locale, "compiler.misc.anonymous.class", sym.flatname)
-                    : sym.fullname.toString();
-        }
-
-        @Override
-        public String visitMethodSymbol(MethodSymbol s, Locale locale) {
-            if ((s.flags() & BLOCK) != 0) {
-                return s.owner.name.toString();
-            } else {
-                String ms = (s.name == names.init)
-                        ? s.owner.name.toString()
-                        : s.name.toString();
-                if (s.type != null) {
-                    if (s.type.tag == FORALL) {
-                        ms = "<" + typePrinter.visit(s.type.getTypeArguments(), locale) + ">" + ms;
-                    }
-                    ms += "(" + typePrinter.printMethodArgs(
-                            s.type.getParameterTypes(),
-                            (s.flags() & VARARGS) != 0,
-                            locale) + ")";
-                }
-                return ms;
-            }
-        }
-
-        @Override
-        public String visitOperatorSymbol(OperatorSymbol s, Locale locale) {
-            return visitMethodSymbol(s, locale);
-        }
-
-        @Override
-        public String visitPackageSymbol(PackageSymbol s, Locale locale) {
-            return s.name.isEmpty()
-                    ? getLocalizedString(locale, "compiler.misc.unnamed.package")
-                    : s.fullname.toString();
-        }
-
-        @Override
-        public String visitSymbol(Symbol s, Locale locale) {
-            return s.name.toString();
-        }
-
-        public String visit(List<Symbol> ts, Locale locale) {
-            ListBuffer<String> sbuf = lb();
-            for (Symbol t : ts) {
-                sbuf.append(visit(t, locale));
-            }
-            return sbuf.toList().toString();
-        }
-
-        protected String getLocalizedString(Locale locale, String key, Object... args) {
-            return messages.getLocalizedString(key, args);
-        }
-    };
-    // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="toString">
     /**
@@ -3128,7 +2926,7 @@
             return t;
     }
     // where
-        private List<Type> freshTypeVariables(List<Type> types) {
+        public List<Type> freshTypeVariables(List<Type> types) {
             ListBuffer<Type> result = lb();
             for (Type t : types) {
                 if (t.tag == WILDCARD) {
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Mar 05 17:25:13 2009 +0000
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Mar 05 17:25:37 2009 +0000
@@ -836,6 +836,9 @@
 compiler.misc.type.captureof=\
     capture#{0} of {1}
 
+compiler.misc.type.captureof.1=\
+    capture#{0}
+
 compiler.misc.type.none=\
     <none>
 
--- a/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Mar 05 17:25:13 2009 +0000
+++ b/src/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java	Thu Mar 05 17:25:37 2009 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2008-2009 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,10 @@
 import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.MultilineLimit;
 import com.sun.tools.javac.api.DiagnosticFormatter.PositionKind;
 import com.sun.tools.javac.api.Formattable;
+import com.sun.tools.javac.code.Printer;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.CapturedType;
 import com.sun.tools.javac.file.JavacFileManager;
 
 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
@@ -60,16 +64,31 @@
      * JavacMessages object used by this formatter for i18n.
      */
     protected JavacMessages messages;
+
+    /**
+     * Configuration object used by this formatter
+     */
     private SimpleConfiguration config;
+
+    /**
+     * Current depth level of the disgnostic being formatted
+     * (!= 0 for subdiagnostics)
+     */
     protected int depth = 0;
 
     /**
+     * Printer instance to be used for formatting types/symbol
+     */
+    protected Printer printer;
+
+    /**
      * Initialize an AbstractDiagnosticFormatter by setting its JavacMessages object.
      * @param messages
      */
     protected AbstractDiagnosticFormatter(JavacMessages messages, SimpleConfiguration config) {
         this.messages = messages;
         this.config = config;
+        this.printer = new FormatterPrinter();
     }
 
     public String formatKind(JCDiagnostic d, Locale l) {
@@ -83,6 +102,14 @@
         }
     }
 
+    @Override
+    public String format(JCDiagnostic d, Locale locale) {
+        printer = new FormatterPrinter();
+        return formatDiagnostic(d, locale);
+    }
+
+    abstract String formatDiagnostic(JCDiagnostic d, Locale locale);
+
     public String formatPosition(JCDiagnostic d, PositionKind pk,Locale l) {
         assert (d.getPosition() != Position.NOPOS);
         return String.valueOf(getPosition(d, pk));
@@ -143,12 +170,21 @@
         else if (arg instanceof Iterable<?>) {
             return formatIterable(d, (Iterable<?>)arg, l);
         }
-        else if (arg instanceof JavaFileObject)
+        else if (arg instanceof Type) {
+            return printer.visit((Type)arg, l);
+        }
+        else if (arg instanceof Symbol) {
+            return printer.visit((Symbol)arg, l);
+        }
+        else if (arg instanceof JavaFileObject) {
             return JavacFileManager.getJavacBaseFileName((JavaFileObject)arg);
-        else if (arg instanceof Formattable)
+        }
+        else if (arg instanceof Formattable) {
             return ((Formattable)arg).toString(l, messages);
-        else
+        }
+        else {
             return String.valueOf(arg);
+        }
     }
 
     /**
@@ -404,4 +440,43 @@
             return caretEnabled;
         }
     }
+
+    /**
+     * An enhanced printer for formatting types/symbols used by
+     * AbstractDiagnosticFormatter. Provides alternate numbering of captured
+     * types (they are numbered starting from 1 on each new diagnostic, instead
+     * of relying on the underlying hashcode() method which generates unstable
+     * output). Also detects cycles in wildcard messages (e.g. if the wildcard
+     * type referred by a given captured type C contains C itself) which might
+     * lead to infinite loops.
+     */
+    protected class FormatterPrinter extends Printer {
+
+        List<Type> allCaptured = List.nil();
+        List<Type> seenCaptured = List.nil();
+
+        @Override
+        protected String localize(Locale locale, String key, Object... args) {
+            return AbstractDiagnosticFormatter.this.localize(locale, key, args);
+        }
+
+        @Override
+        public String visitCapturedType(CapturedType t, Locale locale) {
+            if (seenCaptured.contains(t))
+                return localize(locale, "compiler.misc.type.captureof.1",
+                    allCaptured.indexOf(t) + 1);
+            else {
+                try {
+                    seenCaptured = seenCaptured.prepend(t);
+                    allCaptured = allCaptured.append(t);
+                    return localize(locale, "compiler.misc.type.captureof",
+                        allCaptured.indexOf(t) + 1,
+                        visit(t.wildcard, locale));
+                }
+                finally {
+                    seenCaptured = seenCaptured.tail;
+                }
+            }
+        }
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Thu Mar 05 17:25:13 2009 +0000
+++ b/src/share/classes/com/sun/tools/javac/util/BasicDiagnosticFormatter.java	Thu Mar 05 17:25:37 2009 +0000
@@ -82,7 +82,7 @@
         super(msgs, new BasicConfiguration());
     }
 
-    public String format(JCDiagnostic d, Locale l) {
+    public String formatDiagnostic(JCDiagnostic d, Locale l) {
         if (l == null)
             l = messages.getCurrentLocale();
         String format = selectFormat(d);
--- a/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Mar 05 17:25:13 2009 +0000
+++ b/src/share/classes/com/sun/tools/javac/util/RawDiagnosticFormatter.java	Thu Mar 05 17:25:37 2009 +0000
@@ -54,7 +54,7 @@
     }
 
     //provide common default formats
-    public String format(JCDiagnostic d, Locale l) {
+    public String formatDiagnostic(JCDiagnostic d, Locale l) {
         try {
             StringBuffer buf = new StringBuffer();
             if (d.getPosition() != Position.NOPOS) {
@@ -82,17 +82,11 @@
     public String formatMessage(JCDiagnostic d, Locale l) {
         StringBuilder buf = new StringBuilder();
         Collection<String> args = formatArguments(d, l);
-        buf.append(d.getCode());
-        String sep = ": ";
-        for (Object o : args) {
-            buf.append(sep);
-            buf.append(o);
-            sep = ", ";
-        }
+        buf.append(localize(null, d.getCode(), args.toArray()));
         if (d.isMultiline() && getConfiguration().getVisible().contains(DiagnosticPart.SUBDIAGNOSTICS)) {
             List<String> subDiags = formatSubdiagnostics(d, null);
             if (subDiags.nonEmpty()) {
-                sep = "";
+                String sep = "";
                 buf.append(",{");
                 for (String sub : formatSubdiagnostics(d, null)) {
                     buf.append(sep);
@@ -117,4 +111,17 @@
         else
             return s;
     }
+
+    @Override
+    protected String localize(Locale l, String key, Object... args) {
+        StringBuilder buf = new StringBuilder();
+        buf.append(key);
+        String sep = ": ";
+        for (Object o : args) {
+            buf.append(sep);
+            buf.append(o);
+            sep = ", ";
+        }
+        return buf.toString();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/Diagnostics/6799605/T6799605.java	Thu Mar 05 17:25:37 2009 +0000
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug     6799605
+ * @summary Basic/Raw formatters should use type/symbol printer instead of toString()
+ * @author  mcimadamore
+ * @compile/fail/ref=T6799605.out -XDrawDiagnostics  T6799605.java
+ */
+
+class T6799605<X> {
+
+    <T extends T6799605<T>> void m(T6799605<T> x1) {}
+    <T> void m(T6799605<T> x1, T6799605<T> x2) {}
+    <T> void m(T6799605<T> x1, T6799605<T> x2, T6799605<T> x3) {}
+
+    void test(T6799605<?> t) {
+        m(t);
+        m(t, t);
+        m(t, t, t);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/Diagnostics/6799605/T6799605.out	Thu Mar 05 17:25:37 2009 +0000
@@ -0,0 +1,4 @@
+T6799605.java:39:9: compiler.err.cant.resolve.location.args: kindname.method, m, , T6799605<compiler.misc.type.captureof: 1, ?>, kindname.class, T6799605<X>
+T6799605.java:40:9: compiler.err.cant.resolve.location.args: kindname.method, m, , T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>, kindname.class, T6799605<X>
+T6799605.java:41:9: compiler.err.cant.resolve.location.args: kindname.method, m, , T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,T6799605<compiler.misc.type.captureof: 3, ?>, kindname.class, T6799605<X>
+3 errors
--- a/test/tools/javac/NestedInnerClassNames.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/NestedInnerClassNames.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,15 +1,15 @@
-NestedInnerClassNames.java:16:5: compiler.err.already.defined: NestedInnerClassNames, unnamed package
+NestedInnerClassNames.java:16:5: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package
 NestedInnerClassNames.java:23:9: compiler.err.already.defined: NestedInnerClassNames.foo, NestedInnerClassNames
-NestedInnerClassNames.java:34:9: compiler.err.already.defined: NestedInnerClassNames, unnamed package
+NestedInnerClassNames.java:34:9: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package
 NestedInnerClassNames.java:45:9: compiler.err.already.defined: NestedInnerClassNames.baz, NestedInnerClassNames
 NestedInnerClassNames.java:46:13: compiler.err.already.defined: NestedInnerClassNames.baz.baz, NestedInnerClassNames.baz
 NestedInnerClassNames.java:59:9: compiler.err.already.defined: NestedInnerClassNames.foo$bar, NestedInnerClassNames
 NestedInnerClassNames.java:76:13: compiler.err.already.defined: NestedInnerClassNames.$bar, NestedInnerClassNames
 NestedInnerClassNames.java:90:13: compiler.err.already.defined: NestedInnerClassNames.bar$bar.bar, NestedInnerClassNames.bar$bar
 NestedInnerClassNames.java:109:5: compiler.err.duplicate.class: NestedInnerClassNames.foo.foo
-NestedInnerClassNames.java:19:9: compiler.err.already.defined: NestedInnerClassNames, unnamed package
+NestedInnerClassNames.java:19:9: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package
 NestedInnerClassNames.java:28:13: compiler.err.already.defined: foo, m2()
-NestedInnerClassNames.java:40:13: compiler.err.already.defined: NestedInnerClassNames, unnamed package
+NestedInnerClassNames.java:40:13: compiler.err.already.defined: NestedInnerClassNames, compiler.misc.unnamed.package
 NestedInnerClassNames.java:52:13: compiler.err.already.defined: baz, m4()
 NestedInnerClassNames.java:53:17: compiler.err.already.defined: baz.baz, baz
 NestedInnerClassNames.java:67:13: compiler.err.already.defined: foo$bar, m5()
--- a/test/tools/javac/T6241723.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/T6241723.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,6 +1,6 @@
-T6241723.java:21:5: compiler.warn.has.been.deprecated: A1, unnamed package
+T6241723.java:21:5: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
 T6241723.java:23:7: compiler.warn.has.been.deprecated: A2.A21, A2
-T6241723.java:26:5: compiler.warn.has.been.deprecated: Z1, unnamed package
+T6241723.java:26:5: compiler.warn.has.been.deprecated: Z1, compiler.misc.unnamed.package
 T6241723.java:28:7: compiler.warn.has.been.deprecated: Z2.Z21, Z2
 - compiler.err.warnings.and.werror
 1 error
--- a/test/tools/javac/depDocComment/SuppressDeprecation.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/depDocComment/SuppressDeprecation.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,4 +1,4 @@
-SuppressDeprecation.java:130:17: compiler.warn.has.been.deprecated: X, unnamed package
+SuppressDeprecation.java:130:17: compiler.warn.has.been.deprecated: X, compiler.misc.unnamed.package
 SuppressDeprecation.java:82:10: compiler.warn.has.been.deprecated: g(), T
 SuppressDeprecation.java:83:14: compiler.warn.has.been.deprecated: g(), T
 SuppressDeprecation.java:84:9: compiler.warn.has.been.deprecated: var, T
--- a/test/tools/javac/mandatoryWarnings/deprecated/Test3.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/mandatoryWarnings/deprecated/Test3.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,3 +1,3 @@
-A.java:10:9: compiler.warn.has.been.deprecated: A1, unnamed package
-A.java:10:21: compiler.warn.has.been.deprecated: A1, unnamed package
+A.java:10:9: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
+A.java:10:21: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
 2 warnings
--- a/test/tools/javac/mandatoryWarnings/deprecated/Test3b.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/mandatoryWarnings/deprecated/Test3b.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,3 +1,3 @@
-A.java:10:9: compiler.warn.has.been.deprecated: A1, unnamed package
+A.java:10:9: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
 - compiler.note.deprecated.filename.additional: A.java
 1 warning
--- a/test/tools/javac/mandatoryWarnings/deprecated/Test4.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/mandatoryWarnings/deprecated/Test4.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,7 +1,7 @@
-A.java:10:9: compiler.warn.has.been.deprecated: A1, unnamed package
-A.java:10:21: compiler.warn.has.been.deprecated: A1, unnamed package
-B.java:11:9: compiler.warn.has.been.deprecated: B1, unnamed package
-B.java:11:21: compiler.warn.has.been.deprecated: B1, unnamed package
-B.java:12:9: compiler.warn.has.been.deprecated: B1, unnamed package
-B.java:12:22: compiler.warn.has.been.deprecated: B1, unnamed package
+A.java:10:9: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
+A.java:10:21: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
+B.java:11:9: compiler.warn.has.been.deprecated: B1, compiler.misc.unnamed.package
+B.java:11:21: compiler.warn.has.been.deprecated: B1, compiler.misc.unnamed.package
+B.java:12:9: compiler.warn.has.been.deprecated: B1, compiler.misc.unnamed.package
+B.java:12:22: compiler.warn.has.been.deprecated: B1, compiler.misc.unnamed.package
 6 warnings
--- a/test/tools/javac/mandatoryWarnings/deprecated/Test4b.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/mandatoryWarnings/deprecated/Test4b.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,3 +1,3 @@
-A.java:10:9: compiler.warn.has.been.deprecated: A1, unnamed package
+A.java:10:9: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
 - compiler.note.deprecated.plural.additional
 1 warning
--- a/test/tools/javac/mandatoryWarnings/deprecated/Test4c.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/mandatoryWarnings/deprecated/Test4c.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,4 +1,4 @@
-A.java:10:9: compiler.warn.has.been.deprecated: A1, unnamed package
-A.java:10:21: compiler.warn.has.been.deprecated: A1, unnamed package
+A.java:10:9: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
+A.java:10:21: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
 - compiler.note.deprecated.filename: B.java
 2 warnings
--- a/test/tools/javac/mandatoryWarnings/deprecated/Test4d.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/mandatoryWarnings/deprecated/Test4d.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,5 +1,5 @@
-A.java:10:9: compiler.warn.has.been.deprecated: A1, unnamed package
-A.java:10:21: compiler.warn.has.been.deprecated: A1, unnamed package
-B.java:11:9: compiler.warn.has.been.deprecated: B1, unnamed package
+A.java:10:9: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
+A.java:10:21: compiler.warn.has.been.deprecated: A1, compiler.misc.unnamed.package
+B.java:11:9: compiler.warn.has.been.deprecated: B1, compiler.misc.unnamed.package
 - compiler.note.deprecated.filename.additional: B.java
 3 warnings
--- a/test/tools/javac/positions/T6253161.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/positions/T6253161.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,2 +1,2 @@
-T6253161.java:19:62: compiler.warn.missing.SVUID: <anonymous T6253161$1$1>
+T6253161.java:19:62: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6253161$1$1
 1 warning
--- a/test/tools/javac/positions/T6253161a.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/positions/T6253161a.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,2 +1,2 @@
-T6253161a.java:19:62: compiler.warn.missing.SVUID: <anonymous T6253161a$1$1>
+T6253161a.java:19:62: compiler.warn.missing.SVUID: compiler.misc.anonymous.class: T6253161a$1$1
 1 warning
--- a/test/tools/javac/warnings/Deprecation.lintAll.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/warnings/Deprecation.lintAll.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,3 +1,3 @@
-Deprecation.java:18:24: compiler.warn.has.been.deprecated: Deprecation, unnamed package
-Deprecation.java:55:24: compiler.warn.has.been.deprecated: Deprecation, unnamed package
+Deprecation.java:18:24: compiler.warn.has.been.deprecated: Deprecation, compiler.misc.unnamed.package
+Deprecation.java:55:24: compiler.warn.has.been.deprecated: Deprecation, compiler.misc.unnamed.package
 2 warnings
--- a/test/tools/javac/warnings/Deprecation.lintDeprecation.out	Thu Mar 05 17:25:13 2009 +0000
+++ b/test/tools/javac/warnings/Deprecation.lintDeprecation.out	Thu Mar 05 17:25:37 2009 +0000
@@ -1,3 +1,3 @@
-Deprecation.java:18:24: compiler.warn.has.been.deprecated: Deprecation, unnamed package
-Deprecation.java:55:24: compiler.warn.has.been.deprecated: Deprecation, unnamed package
+Deprecation.java:18:24: compiler.warn.has.been.deprecated: Deprecation, compiler.misc.unnamed.package
+Deprecation.java:55:24: compiler.warn.has.been.deprecated: Deprecation, compiler.misc.unnamed.package
 2 warnings