changeset 79:5c9cdeb740f2

6717241: some diagnostic argument is prematurely converted into a String object Summary: removed early toString() conversions applied to diagnostic arguments Reviewed-by: jjg
author mcimadamore
date Thu, 24 Jul 2008 19:06:57 +0100
parents 36df13bde238
children 8973372aedf8
files src/share/classes/com/sun/tools/javac/api/Formattable.java src/share/classes/com/sun/tools/javac/code/Flags.java src/share/classes/com/sun/tools/javac/code/Kinds.java src/share/classes/com/sun/tools/javac/code/Symbol.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/comp/MemberEnter.java src/share/classes/com/sun/tools/javac/comp/Resolve.java src/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/share/classes/com/sun/tools/javac/parser/Keywords.java src/share/classes/com/sun/tools/javac/parser/Parser.java src/share/classes/com/sun/tools/javac/parser/Token.java src/share/classes/com/sun/tools/javac/resources/compiler.properties src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java test/tools/javac/5045412/out test/tools/javac/6330920/T6330920.out test/tools/javac/6717241/T6717241a.java test/tools/javac/6717241/T6717241a.out test/tools/javac/6717241/T6717241b.java test/tools/javac/6717241/T6717241b.out test/tools/javac/ExtendsAccess/ExtendsAccess.out test/tools/javac/NonStaticFieldExpr1.out test/tools/javac/NonStaticFieldExpr2.out test/tools/javac/NonStaticFieldExpr3.out test/tools/javac/T6247324.out test/tools/javac/annotations/6365854/test1.out test/tools/javac/generics/inference/6611449/T6611449.out test/tools/javac/policy/byfile.ABD.out test/tools/javac/policy/bytodo.ABD.out test/tools/javac/policy/simple.ABD.out
diffstat 31 files changed, 595 insertions(+), 329 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/com/sun/tools/javac/api/Formattable.java	Thu Jul 24 19:06:57 2008 +0100
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 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.api;
+
+import java.util.ResourceBundle;
+
+/**
+ * This interface must be implemented by any javac class that has non-trivial
+ * formatting needs (e.g. where toString() does not apply because of localization).
+ *
+ * @author Maurizio Cimadamore
+ */
+public interface Formattable {
+
+    /**
+     * Used to obtain a localized String representing the object accordingly
+     * to a given locale
+     *
+     * @param bundle resource bundle class used for localization
+     * @return a locale-dependent string representing the object
+     */
+    public String toString(ResourceBundle bundle);
+    /**
+     * Retrieve a pretty name of this object's kind
+     * @return a string representing the object's kind
+     */
+    String getKind();
+}
--- a/src/share/classes/com/sun/tools/javac/code/Flags.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Flags.java	Thu Jul 24 19:06:57 2008 +0100
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.code;
 
+import java.util.EnumSet;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -43,38 +44,49 @@
 
     public static String toString(long flags) {
         StringBuffer buf = new StringBuffer();
-        if ((flags&PUBLIC) != 0) buf.append("public ");
-        if ((flags&PRIVATE) != 0) buf.append("private ");
-        if ((flags&PROTECTED) != 0) buf.append("protected ");
-        if ((flags&STATIC) != 0) buf.append("static ");
-        if ((flags&FINAL) != 0) buf.append("final ");
-        if ((flags&SYNCHRONIZED) != 0) buf.append("synchronized ");
-        if ((flags&VOLATILE) != 0) buf.append("volatile ");
-        if ((flags&TRANSIENT) != 0) buf.append("transient ");
-        if ((flags&NATIVE) != 0) buf.append("native ");
-        if ((flags&INTERFACE) != 0) buf.append("interface ");
-        if ((flags&ABSTRACT) != 0) buf.append("abstract ");
-        if ((flags&STRICTFP) != 0) buf.append("strictfp ");
-        if ((flags&BRIDGE) != 0) buf.append("bridge ");
-        if ((flags&SYNTHETIC) != 0) buf.append("synthetic ");
-        if ((flags&DEPRECATED) != 0) buf.append("deprecated ");
-        if ((flags&HASINIT) != 0) buf.append("hasinit ");
-        if ((flags&ENUM) != 0) buf.append("enum ");
-        if ((flags&IPROXY) != 0) buf.append("iproxy ");
-        if ((flags&NOOUTERTHIS) != 0) buf.append("noouterthis ");
-        if ((flags&EXISTS) != 0) buf.append("exists ");
-        if ((flags&COMPOUND) != 0) buf.append("compound ");
-        if ((flags&CLASS_SEEN) != 0) buf.append("class_seen ");
-        if ((flags&SOURCE_SEEN) != 0) buf.append("source_seen ");
-        if ((flags&LOCKED) != 0) buf.append("locked ");
-        if ((flags&UNATTRIBUTED) != 0) buf.append("unattributed ");
-        if ((flags&ANONCONSTR) != 0) buf.append("anonconstr ");
-        if ((flags&ACYCLIC) != 0) buf.append("acyclic ");
-        if ((flags&PARAMETER) != 0) buf.append("parameter ");
-        if ((flags&VARARGS) != 0) buf.append("varargs ");
+        String sep = "";
+        for (Flag s : asFlagSet(flags)) {
+            buf.append(sep);
+            buf.append(s);
+            sep = " ";
+        }
         return buf.toString();
     }
 
+    public static EnumSet<Flag> asFlagSet(long mask) {
+        EnumSet<Flag> flags = EnumSet.noneOf(Flag.class);
+        if ((mask&PUBLIC) != 0) flags.add(Flag.PUBLIC);
+        if ((mask&PRIVATE) != 0) flags.add(Flag.PRIVATE);
+        if ((mask&PROTECTED) != 0) flags.add(Flag.PROTECTED);
+        if ((mask&STATIC) != 0) flags.add(Flag.STATIC);
+        if ((mask&FINAL) != 0) flags.add(Flag.FINAL);
+        if ((mask&SYNCHRONIZED) != 0) flags.add(Flag.SYNCHRONIZED);
+        if ((mask&VOLATILE) != 0) flags.add(Flag.VOLATILE);
+        if ((mask&TRANSIENT) != 0) flags.add(Flag.TRANSIENT);
+        if ((mask&NATIVE) != 0) flags.add(Flag.NATIVE);
+        if ((mask&INTERFACE) != 0) flags.add(Flag.INTERFACE);
+        if ((mask&ABSTRACT) != 0) flags.add(Flag.ABSTRACT);
+        if ((mask&STRICTFP) != 0) flags.add(Flag.STRICTFP);
+        if ((mask&BRIDGE) != 0) flags.add(Flag.BRIDGE);
+        if ((mask&SYNTHETIC) != 0) flags.add(Flag.SYNTHETIC);
+        if ((mask&DEPRECATED) != 0) flags.add(Flag.DEPRECATED);
+        if ((mask&HASINIT) != 0) flags.add(Flag.HASINIT);
+        if ((mask&ENUM) != 0) flags.add(Flag.ENUM);
+        if ((mask&IPROXY) != 0) flags.add(Flag.IPROXY);
+        if ((mask&NOOUTERTHIS) != 0) flags.add(Flag.NOOUTERTHIS);
+        if ((mask&EXISTS) != 0) flags.add(Flag.EXISTS);
+        if ((mask&COMPOUND) != 0) flags.add(Flag.COMPOUND);
+        if ((mask&CLASS_SEEN) != 0) flags.add(Flag.CLASS_SEEN);
+        if ((mask&SOURCE_SEEN) != 0) flags.add(Flag.SOURCE_SEEN);
+        if ((mask&LOCKED) != 0) flags.add(Flag.LOCKED);
+        if ((mask&UNATTRIBUTED) != 0) flags.add(Flag.UNATTRIBUTED);
+        if ((mask&ANONCONSTR) != 0) flags.add(Flag.ANONCONSTR);
+        if ((mask&ACYCLIC) != 0) flags.add(Flag.ACYCLIC);
+        if ((mask&PARAMETER) != 0) flags.add(Flag.PARAMETER);
+        if ((mask&VARARGS) != 0) flags.add(Flag.VARARGS);
+        return flags;
+    }
+
     /* Standard Java flags.
      */
     public static final int PUBLIC       = 1<<0;
@@ -271,4 +283,48 @@
     public static boolean isConstant(Symbol.VarSymbol symbol) {
         return symbol.getConstValue() != null;
     }
+
+    public enum Flag {
+
+        PUBLIC("public"),
+        PRIVATE("private"),
+        PROTECTED("protected"),
+        STATIC("static"),
+        FINAL("final"),
+        SYNCHRONIZED("synchronized"),
+        VOLATILE("volatile"),
+        TRANSIENT("transient"),
+        NATIVE("native"),
+        INTERFACE("interface"),
+        ABSTRACT("abstract"),
+        STRICTFP("strictfp"),
+        BRIDGE("bridge"),
+        SYNTHETIC("synthetic"),
+        DEPRECATED("deprecated"),
+        HASINIT("hasinit"),
+        ENUM("enum"),
+        IPROXY("iproxy"),
+        NOOUTERTHIS("noouterthis"),
+        EXISTS("exists"),
+        COMPOUND("compound"),
+        CLASS_SEEN("class_seen"),
+        SOURCE_SEEN("source_seen"),
+        LOCKED("locked"),
+        UNATTRIBUTED("unattributed"),
+        ANONCONSTR("anonconstr"),
+        ACYCLIC("acyclic"),
+        PARAMETER("parameter"),
+        VARARGS("varargs"),
+        PACKAGE("package");
+
+        String name;
+
+        Flag(String name) {
+            this.name = name;
+        }
+
+        public String toString() {
+            return name;
+        }
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Kinds.java	Thu Jul 24 19:06:57 2008 +0100
@@ -25,6 +25,13 @@
 
 package com.sun.tools.javac.code;
 
+import java.util.EnumSet;
+import java.util.ResourceBundle;
+
+import com.sun.tools.javac.api.Formattable;
+
+import static com.sun.tools.javac.code.TypeTags.*;
+import static com.sun.tools.javac.code.Flags.*;
 
 /** Internal symbol kinds, which distinguish between elements of
  *  different subclasses of Symbol. Symbol kinds are organized so they can be
@@ -82,4 +89,133 @@
     public static final int WRONG_MTH    = ERRONEOUS+6; // one method with wrong arguments
     public static final int ABSENT_MTH   = ERRONEOUS+7; // missing method
     public static final int ABSENT_TYP   = ERRONEOUS+8; // missing type
+
+    public enum KindName implements Formattable {
+        ANNOTATION("kindname.interface"),
+        CONSTRUCTOR("kindname.constructor"),
+        INTERFACE("kindname.interface"),
+        STATIC("kindname.static"),
+        TYPEVAR("kindname.type.variable"),
+        BOUND("kindname.type.variable.bound"),
+        VAR("kindname.variable"),
+        VAL("kindname.value"),
+        METHOD("kindname.method"),
+        CLASS("kindname.class"),
+        PACKAGE("kindname.package");
+
+        private String name;
+
+        KindName(String name) {
+            this.name = name;
+        }
+
+        public String toString() {
+            return name;
+        }
+
+        public String getKind() {
+            return "Kindname";
+        }
+
+        public String toString(ResourceBundle bundle) {
+            String s = toString();
+            return bundle.getString("compiler.misc." + s);
+        }
+    }
+
+    /** A KindName representing a given symbol kind
+     */
+    public static KindName kindName(int kind) {
+        switch (kind) {
+        case PCK: return KindName.PACKAGE;
+        case TYP: return KindName.CLASS;
+        case VAR: return KindName.VAR;
+        case VAL: return KindName.VAL;
+        case MTH: return KindName.METHOD;
+            default : throw new AssertionError("Unexpected kind: "+kind);
+        }
+    }
+
+    /** A KindName representing a given symbol
+     */
+    public static KindName kindName(Symbol sym) {
+        switch (sym.getKind()) {
+        case PACKAGE:
+            return KindName.PACKAGE;
+
+        case ENUM:
+        case ANNOTATION_TYPE:
+        case INTERFACE:
+        case CLASS:
+            return KindName.CLASS;
+
+        case TYPE_PARAMETER:
+            return KindName.TYPEVAR;
+
+        case ENUM_CONSTANT:
+        case FIELD:
+        case PARAMETER:
+        case LOCAL_VARIABLE:
+        case EXCEPTION_PARAMETER:
+            return KindName.VAR;
+
+        case METHOD:
+        case CONSTRUCTOR:
+        case STATIC_INIT:
+        case INSTANCE_INIT:
+            return KindName.METHOD;
+
+        default:
+            if (sym.kind == VAL)
+                // I don't think this can happen but it can't harm
+                // playing it safe --ahe
+                return KindName.VAL;
+            else
+                throw new AssertionError("Unexpected kind: "+sym.getKind());
+        }
+    }
+
+    /** A set of KindName(s) representing a set of symbol's kinds.
+     */
+    public static EnumSet<KindName> kindNames(int kind) {
+        EnumSet<KindName> kinds = EnumSet.noneOf(KindName.class);
+        if ((kind & VAL) != 0)
+            kinds.add(((kind & VAL) == VAR) ? KindName.VAR : KindName.VAL);
+        if ((kind & MTH) != 0) kinds.add(KindName.METHOD);
+        if ((kind & TYP) != 0) kinds.add(KindName.CLASS);
+        if ((kind & PCK) != 0) kinds.add(KindName.PACKAGE);
+        return kinds;
+    }
+
+    /** A KindName representing the kind of a given class/interface type.
+     */
+    public static KindName typeKindName(Type t) {
+        if (t.tag == TYPEVAR ||
+            t.tag == CLASS && (t.tsym.flags() & COMPOUND) != 0)
+            return KindName.BOUND;
+        else if (t.tag == PACKAGE)
+            return KindName.PACKAGE;
+        else if ((t.tsym.flags_field & ANNOTATION) != 0)
+            return KindName.ANNOTATION;
+        else if ((t.tsym.flags_field & INTERFACE) != 0)
+            return KindName.INTERFACE;
+        else
+            return KindName.CLASS;
+    }
+
+    /** A KindName representing the kind of a a missing symbol, given an
+     *  error kind.
+     * */
+    public static KindName absentKind(int kind) {
+        switch (kind) {
+        case ABSENT_VAR:
+            return KindName.VAR;
+        case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH:
+            return KindName.METHOD;
+        case ABSENT_TYP:
+            return KindName.CLASS;
+        default:
+            throw new AssertionError("Unexpected kind: "+kind);
+        }
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Thu Jul 24 19:06:57 2008 +0100
@@ -140,25 +140,27 @@
     }
 
     /** A Java source description of the location of this symbol; used for
-     *  error reporting.  Use of this method may result in the loss of the
-     *  symbol's description.
+     *  error reporting.
+     *
+     * @return null if the symbol is a package or a toplevel class defined in
+     * the default package; otherwise, the owner symbol is returned
      */
-    public String location() {
+    public Symbol location() {
         if (owner.name == null || (owner.name.len == 0 && owner.kind != PCK)) {
-            return "";
+            return null;
         }
-        return owner.toString();
+        return owner;
     }
 
-    public String location(Type site, Types types) {
+    public Symbol location(Type site, Types types) {
         if (owner.name == null || owner.name.len == 0) {
             return location();
         }
         if (owner.type.tag == CLASS) {
             Type ownertype = types.asOuterSuper(site, owner);
-            if (ownertype != null) return ownertype.toString();
+            if (ownertype != null) return ownertype.tsym;
         }
-        return owner.toString();
+        return owner;
     }
 
     /** The symbol's erased type.
@@ -451,8 +453,8 @@
             this.other = other;
         }
         public String toString() { return other.toString(); }
-        public String location() { return other.location(); }
-        public String location(Type site, Types types) { return other.location(site, types); }
+        public Symbol location() { return other.location(); }
+        public Symbol location(Type site, Types types) { return other.location(site, types); }
         public Type erasure(Types types) { return other.erasure(types); }
         public Type externalType(Types types) { return other.externalType(types); }
         public boolean isLocal() { return other.isLocal(); }
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Jul 24 19:06:57 2008 +0100
@@ -172,8 +172,8 @@
                 owntype = chk.checkType(tree.pos(), owntype, pt);
             } else {
                 log.error(tree.pos(), "unexpected.type",
-                          Resolve.kindNames(pkind),
-                          Resolve.kindName(ownkind));
+                          kindNames(pkind),
+                          kindName(ownkind));
                 owntype = syms.errType;
             }
         }
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Thu Jul 24 19:06:57 2008 +0100
@@ -576,8 +576,8 @@
         if ((flags & set1) != 0 && (flags & set2) != 0) {
             log.error(pos,
                       "illegal.combination.of.modifiers",
-                      TreeInfo.flagNames(TreeInfo.firstFlag(flags & set1)),
-                      TreeInfo.flagNames(TreeInfo.firstFlag(flags & set2)));
+                      asFlagSet(TreeInfo.firstFlag(flags & set1)),
+                      asFlagSet(TreeInfo.firstFlag(flags & set2)));
             return false;
         } else
             return true;
@@ -670,7 +670,7 @@
             }
             else {
                 log.error(pos,
-                          "mod.not.allowed.here", TreeInfo.flagNames(illegal));
+                          "mod.not.allowed.here", asFlagSet(illegal));
             }
         }
         else if ((sym.kind == TYP ||
@@ -1023,14 +1023,6 @@
         }
     }
 
-    /** A string describing the access permission given by a flag set.
-     *  This always returns a space-separated list of Java Keywords.
-     */
-    private static String protectionString(long flags) {
-        long flags1 = flags & AccessFlags;
-        return (flags1 == 0) ? "package" : TreeInfo.flagNames(flags1);
-    }
-
     /** A customized "cannot override" error message.
      *  @param m      The overriding method.
      *  @param other  The overridden method.
@@ -1124,7 +1116,7 @@
                  (other.flags() & STATIC) != 0) {
             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.meth",
                       cannotOverride(m, other),
-                      TreeInfo.flagNames(other.flags() & (FINAL | STATIC)));
+                      asFlagSet(other.flags() & (FINAL | STATIC)));
             return;
         }
 
@@ -1138,9 +1130,10 @@
                  protection(m.flags()) > protection(other.flags())) {
             log.error(TreeInfo.diagnosticPositionFor(m, tree), "override.weaker.access",
                       cannotOverride(m, other),
-                      protectionString(other.flags()));
+                      other.flags() == 0 ?
+                          Flag.PACKAGE :
+                          asFlagSet(other.flags() & AccessFlags));
             return;
-
         }
 
         Type mt = types.memberType(origin.type, m);
@@ -2035,7 +2028,7 @@
             log.error(pos,
                       "operator.cant.be.applied",
                       treeinfo.operatorName(tag),
-                      left + "," + right);
+                      List.of(left, right));
         }
         return operator.opcode;
     }
--- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Thu Jul 24 19:06:57 2008 +0100
@@ -317,8 +317,9 @@
                     importFrom(tsym);
                     if (!found) {
                         log.error(pos, "cant.resolve.location",
-                                  JCDiagnostic.fragment("kindname.static"),
-                                  name, "", "", Resolve.typeKindName(tsym.type),
+                                  KindName.STATIC,
+                                  name, List.<Type>nil(), List.<Type>nil(),
+                                  typeKindName(tsym.type),
                                   tsym.type);
                     }
                 } finally {
@@ -719,7 +720,7 @@
                             annotations.nonEmpty())
                             log.error(annotations.head.pos,
                                       "already.annotated",
-                                      Resolve.kindName(s), s);
+                                      kindName(s), s);
                         enterAnnotations(annotations, localEnv, s);
                     } finally {
                         log.useSource(prev);
--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Jul 24 19:06:57 2008 +0100
@@ -1442,107 +1442,6 @@
     }
 
 /* ***************************************************************************
- *  Methods related to kinds
- ****************************************************************************/
-
-    /** A localized string describing a given kind.
-     */
-    static JCDiagnostic kindName(int kind) {
-        switch (kind) {
-        case PCK: return JCDiagnostic.fragment("kindname.package");
-        case TYP: return JCDiagnostic.fragment("kindname.class");
-        case VAR: return JCDiagnostic.fragment("kindname.variable");
-        case VAL: return JCDiagnostic.fragment("kindname.value");
-        case MTH: return JCDiagnostic.fragment("kindname.method");
-        default : return JCDiagnostic.fragment("kindname",
-                                               Integer.toString(kind)); //debug
-        }
-    }
-
-    static JCDiagnostic kindName(Symbol sym) {
-        switch (sym.getKind()) {
-        case PACKAGE:
-            return JCDiagnostic.fragment("kindname.package");
-
-        case ENUM:
-        case ANNOTATION_TYPE:
-        case INTERFACE:
-        case CLASS:
-            return JCDiagnostic.fragment("kindname.class");
-
-        case TYPE_PARAMETER:
-            return JCDiagnostic.fragment("kindname.type.variable");
-
-        case ENUM_CONSTANT:
-        case FIELD:
-        case PARAMETER:
-        case LOCAL_VARIABLE:
-        case EXCEPTION_PARAMETER:
-            return JCDiagnostic.fragment("kindname.variable");
-
-        case METHOD:
-        case CONSTRUCTOR:
-        case STATIC_INIT:
-        case INSTANCE_INIT:
-            return JCDiagnostic.fragment("kindname.method");
-
-        default:
-            if (sym.kind == VAL)
-                // I don't think this can happen but it can't harm
-                // playing it safe --ahe
-                return JCDiagnostic.fragment("kindname.value");
-            else
-                return JCDiagnostic.fragment("kindname", sym.getKind()); // debug
-        }
-    }
-
-    /** A localized string describing a given set of kinds.
-     */
-    static JCDiagnostic kindNames(int kind) {
-        StringBuffer key = new StringBuffer();
-        key.append("kindname");
-        if ((kind & VAL) != 0)
-            key.append(((kind & VAL) == VAR) ? ".variable" : ".value");
-        if ((kind & MTH) != 0) key.append(".method");
-        if ((kind & TYP) != 0) key.append(".class");
-        if ((kind & PCK) != 0) key.append(".package");
-        return JCDiagnostic.fragment(key.toString(), kind);
-    }
-
-    /** A localized string describing the kind -- either class or interface --
-     *  of a given type.
-     */
-    static JCDiagnostic typeKindName(Type t) {
-        if (t.tag == TYPEVAR ||
-            t.tag == CLASS && (t.tsym.flags() & COMPOUND) != 0)
-            return JCDiagnostic.fragment("kindname.type.variable.bound");
-        else if (t.tag == PACKAGE)
-            return JCDiagnostic.fragment("kindname.package");
-        else if ((t.tsym.flags_field & ANNOTATION) != 0)
-            return JCDiagnostic.fragment("kindname.annotation");
-        else if ((t.tsym.flags_field & INTERFACE) != 0)
-            return JCDiagnostic.fragment("kindname.interface");
-        else
-            return JCDiagnostic.fragment("kindname.class");
-    }
-
-    /** A localized string describing the kind of a missing symbol, given an
-     *  error kind.
-     */
-    static JCDiagnostic absentKindName(int kind) {
-        switch (kind) {
-        case ABSENT_VAR:
-            return JCDiagnostic.fragment("kindname.variable");
-        case WRONG_MTHS: case WRONG_MTH: case ABSENT_MTH:
-            return JCDiagnostic.fragment("kindname.method");
-        case ABSENT_TYP:
-            return JCDiagnostic.fragment("kindname.class");
-        default:
-            return JCDiagnostic.fragment("kindname", kind);
-        }
-    }
-
-/* ***************************************************************************
  *  ResolveError classes, indicating error situations when accessing symbols
  ****************************************************************************/
 
@@ -1633,55 +1532,77 @@
          */
         void report(Log log, DiagnosticPosition pos, Type site, Name name,
                     List<Type> argtypes, List<Type> typeargtypes) {
+            if (argtypes == null)
+                argtypes = List.nil();
+            if (typeargtypes == null)
+                typeargtypes = List.nil();
             if (name != name.table.error) {
-                JCDiagnostic kindname = absentKindName(kind);
-                String idname = name.toString();
-                String args = "";
-                String typeargs = "";
+                KindName kindname = absentKind(kind);
+                Name idname = name;
                 if (kind >= WRONG_MTHS && kind <= ABSENT_MTH) {
                     if (isOperator(name)) {
                         log.error(pos, "operator.cant.be.applied",
-                                  name, Type.toString(argtypes));
+                                  name, argtypes);
                         return;
                     }
                     if (name == name.table.init) {
-                        kindname = JCDiagnostic.fragment("kindname.constructor");
-                        idname = site.tsym.name.toString();
+                        kindname = KindName.CONSTRUCTOR;
+                        idname = site.tsym.name;
                     }
-                    args = "(" + Type.toString(argtypes) + ")";
-                    if (typeargtypes != null && typeargtypes.nonEmpty())
-                        typeargs = "<" + Type.toString(typeargtypes) + ">";
                 }
                 if (kind == WRONG_MTH) {
+                    Symbol ws = wrongSym.asMemberOf(site, types);
                     log.error(pos,
                               "cant.apply.symbol" + (explanation != null ? ".1" : ""),
-                              wrongSym.asMemberOf(site, types),
-                              wrongSym.location(site, types),
-                              typeargs,
-                              Type.toString(argtypes),
+                              kindname,
+                              ws.name == names.init ? ws.owner.name : ws.name,
+                              ws.type.getParameterTypes(),
+                              argtypes,
+                              kindName(ws.owner),
+                              ws.owner.type,
                               explanation);
                 } else if (site.tsym.name.len != 0) {
                     if (site.tsym.kind == PCK && !site.tsym.exists())
                         log.error(pos, "doesnt.exist", site.tsym);
-                    else
-                        log.error(pos, "cant.resolve.location",
-                                  kindname, idname, args, typeargs,
-                                  typeKindName(site), site);
+                    else {
+                        String errKey = getErrorKey("cant.resolve.location",
+                                                    argtypes, typeargtypes,
+                                                    kindname);
+                        log.error(pos, errKey, kindname, idname, //symbol kindname, name
+                                  typeargtypes, argtypes, //type parameters and arguments (if any)
+                                  typeKindName(site), site); //location kindname, type
+                    }
                 } else {
-                    log.error(pos, "cant.resolve", kindname, idname, args, typeargs);
+                    String errKey = getErrorKey("cant.resolve",
+                                                argtypes, typeargtypes,
+                                                kindname);
+                    log.error(pos, errKey, kindname, idname, //symbol kindname, name
+                              typeargtypes, argtypes); //type parameters and arguments (if any)
                 }
             }
         }
-//where
-            /** A name designates an operator if it consists
-             *  of a non-empty sequence of operator symbols +-~!/*%&|^<>=
-             */
-            boolean isOperator(Name name) {
-                int i = 0;
-                while (i < name.len &&
-                       "+-~!*/%&|^<>=".indexOf(name.byteAt(i)) >= 0) i++;
-                return i > 0 && i == name.len;
+        //where
+        String getErrorKey(String key, List<Type> argtypes, List<Type> typeargtypes, KindName kindname) {
+            String suffix = "";
+            switch (kindname) {
+                case METHOD:
+                case CONSTRUCTOR: {
+                    suffix += ".args";
+                    suffix += typeargtypes.nonEmpty() ? ".params" : "";
+                }
             }
+            return key + suffix;
+        }
+
+        /** A name designates an operator if it consists
+         *  of a non-empty sequence of operator symbols +-~!/*%&|^<>=
+         */
+        boolean isOperator(Name name) {
+            int i = 0;
+            while (i < name.len &&
+                   "+-~!*/%&|^<>=".indexOf(name.byteAt(i)) >= 0) i++;
+            return i > 0 && i == name.len;
+        }
     }
 
     /** Resolve error class indicating that a symbol is not accessible.
@@ -1726,7 +1647,7 @@
                         sym, sym.location());
                 else if ((sym.flags() & (PRIVATE | PROTECTED)) != 0)
                     log.error(pos, "report.access", sym,
-                              TreeInfo.flagNames(sym.flags() & (PRIVATE | PROTECTED)),
+                              asFlagSet(sym.flags() & (PRIVATE | PROTECTED)),
                               sym.location());
                 else
                     log.error(pos, "not.def.public.cant.access",
@@ -1759,11 +1680,11 @@
                     Name name,
                     List<Type> argtypes,
                     List<Type> typeargtypes) {
-            String symstr = ((sym.kind == TYP && sym.type.tag == CLASS)
-                ? types.erasure(sym.type)
-                : sym).toString();
+            Symbol errSym = ((sym.kind == TYP && sym.type.tag == CLASS)
+                ? types.erasure(sym.type).tsym
+                : sym);
             log.error(pos, "non-static.cant.be.ref",
-                      kindName(sym), symstr);
+                      kindName(sym), errSym);
         }
     }
 
--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Thu Jul 24 19:06:57 2008 +0100
@@ -1331,7 +1331,7 @@
                     log.warning("annotation.method.not.found.reason",
                                 container,
                                 name,
-                                failure.getMessage());
+                                failure.getDetailValue());//diagnostic, if present
                 }
             } finally {
                 log.useSource(prevSource);
--- a/src/share/classes/com/sun/tools/javac/parser/Keywords.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/parser/Keywords.java	Thu Jul 24 19:06:57 2008 +0100
@@ -91,34 +91,6 @@
      */
     private Name[] tokenName = new Name[Token.values().length];
 
-    public String token2string(Token token) {
-        switch (token) {
-        case IDENTIFIER:
-            return log.getLocalizedString("token.identifier");
-        case CHARLITERAL:
-            return log.getLocalizedString("token.character");
-        case STRINGLITERAL:
-            return log.getLocalizedString("token.string");
-        case INTLITERAL:
-            return log.getLocalizedString("token.integer");
-        case LONGLITERAL:
-            return log.getLocalizedString("token.long-integer");
-        case FLOATLITERAL:
-            return log.getLocalizedString("token.float");
-        case DOUBLELITERAL:
-            return log.getLocalizedString("token.double");
-        case ERROR:
-            return log.getLocalizedString("token.bad-symbol");
-        case EOF:
-            return log.getLocalizedString("token.end-of-input");
-        case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
-        case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
-            return "'" + token.name + "'";
-        default:
-            return token.name;
-        }
-    }
-
     private void enterKeyword(String s, Token token) {
         Name n = names.fromString(s);
         tokenName[token.ordinal()] = n;
--- a/src/share/classes/com/sun/tools/javac/parser/Parser.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/parser/Parser.java	Thu Jul 24 19:06:57 2008 +0100
@@ -272,13 +272,13 @@
         }
     }
 
-    private JCErroneous syntaxError(int pos, String key, Object... arg) {
-        return syntaxError(pos, null, key, arg);
+    private JCErroneous syntaxError(int pos, String key, Token... args) {
+        return syntaxError(pos, null, key, args);
     }
 
-    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Object... arg) {
+    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
         setErrorEndPos(pos);
-        reportSyntaxError(pos, key, arg);
+        reportSyntaxError(pos, key, (Object[])args);
         return toP(F.at(pos).Erroneous(errs));
     }
 
@@ -287,12 +287,12 @@
      * Report a syntax error at given position using the given
      * argument unless one was already reported at the same position.
      */
-    private void reportSyntaxError(int pos, String key, Object... arg) {
+    private void reportSyntaxError(int pos, String key, Object... args) {
         if (pos > S.errPos() || pos == Position.NOPOS) {
             if (S.token() == EOF)
                 log.error(pos, "premature.eof");
             else
-                log.error(pos, key, arg);
+                log.error(pos, key, args);
         }
         S.errPos(pos);
         if (S.pos() == errorPos)
@@ -311,7 +311,7 @@
     /** Generate a syntax error at current position unless one was
      *  already reported at the same position.
      */
-    private JCErroneous syntaxError(String key, String arg) {
+    private JCErroneous syntaxError(String key, Token arg) {
         return syntaxError(S.pos(), key, arg);
     }
 
@@ -323,7 +323,7 @@
             S.nextToken();
         } else {
             setErrorEndPos(S.pos());
-            reportSyntaxError(S.prevEndPos(), "expected", keywords.token2string(token));
+            reportSyntaxError(S.prevEndPos(), "expected", token);
         }
     }
 
@@ -349,7 +349,7 @@
         if (mods != 0) {
             long lowestMod = mods & -mods;
             log.error(S.pos(), "mod.not.allowed.here",
-                      Flags.toString(lowestMod).trim());
+                      Flags.asFlagSet(lowestMod));
         }
     }
 
@@ -1180,7 +1180,7 @@
             }
             accept(RPAREN);
         } else {
-            syntaxError(S.pos(), "expected", keywords.token2string(LPAREN));
+            syntaxError(S.pos(), "expected", LPAREN);
         }
         return args.toList();
     }
@@ -1253,7 +1253,7 @@
                 break;
             }
         } else {
-            syntaxError(S.pos(), "expected", keywords.token2string(LT));
+            syntaxError(S.pos(), "expected", LT);
         }
         return args.toList();
     }
@@ -1278,9 +1278,7 @@
         } else if (S.token() == IDENTIFIER) {
             //error recovery
             reportSyntaxError(S.prevEndPos(), "expected3",
-                    keywords.token2string(GT),
-                    keywords.token2string(EXTENDS),
-                    keywords.token2string(SUPER));
+                    GT, EXTENDS, SUPER);
             TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
             JCExpression wc = toP(F.at(pos).Wildcard(t, null));
             JCIdent id = toP(F.at(S.pos()).Ident(ident()));
@@ -1392,8 +1390,7 @@
             return classCreatorRest(newpos, null, typeArgs, t);
         } else {
             reportSyntaxError(S.pos(), "expected2",
-                               keywords.token2string(LPAREN),
-                               keywords.token2string(LBRACKET));
+                               LPAREN, LBRACKET);
             t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
             return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
         }
@@ -1500,7 +1497,7 @@
         List<JCStatement> stats = blockStatements();
         JCBlock t = F.at(pos).Block(flags, stats);
         while (S.token() == CASE || S.token() == DEFAULT) {
-            syntaxError("orphaned", keywords.token2string(S.token()));
+            syntaxError("orphaned", S.token());
             switchBlockStatementGroups();
         }
         // the Block node has a field "endpos" for first char of last token, which is
@@ -1842,9 +1839,7 @@
             default:
                 S.nextToken(); // to ensure progress
                 syntaxError(pos, "expected3",
-                    keywords.token2string(CASE),
-                    keywords.token2string(DEFAULT),
-                    keywords.token2string(RBRACE));
+                    CASE, DEFAULT, RBRACE);
             }
         }
     }
@@ -2110,7 +2105,7 @@
             S.nextToken();
             init = variableInitializer();
         }
-        else if (reqInit) syntaxError(S.pos(), "expected", keywords.token2string(EQ));
+        else if (reqInit) syntaxError(S.pos(), "expected", EQ);
         JCVariableDecl result =
             toP(F.at(pos).VarDef(mods, name, type, init));
         attach(result, dc);
@@ -2241,9 +2236,7 @@
                     errs = List.<JCTree>of(mods);
                 }
                 return toP(F.Exec(syntaxError(pos, errs, "expected3",
-                                              keywords.token2string(CLASS),
-                                              keywords.token2string(INTERFACE),
-                                              keywords.token2string(ENUM))));
+                                              CLASS, INTERFACE, ENUM)));
             }
         } else {
             if (S.token() == ENUM) {
@@ -2260,8 +2253,7 @@
                 errs = List.<JCTree>of(mods);
             }
             return toP(F.Exec(syntaxError(pos, errs, "expected2",
-                                          keywords.token2string(CLASS),
-                                          keywords.token2string(INTERFACE))));
+                                          CLASS, INTERFACE)));
         }
     }
 
@@ -2360,9 +2352,7 @@
             }
             if (S.token() != SEMI && S.token() != RBRACE) {
                 defs.append(syntaxError(S.pos(), "expected3",
-                                keywords.token2string(COMMA),
-                                keywords.token2string(RBRACE),
-                                keywords.token2string(SEMI)));
+                                COMMA, RBRACE, SEMI));
                 S.nextToken();
             }
         }
@@ -2531,7 +2521,7 @@
                             ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
                                 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
                             : null;
-                        return List.<JCTree>of(syntaxError(S.pos(), err, "expected", keywords.token2string(LPAREN)));
+                        return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
                     }
                 }
             }
--- a/src/share/classes/com/sun/tools/javac/parser/Token.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/parser/Token.java	Thu Jul 24 19:06:57 2008 +0100
@@ -25,6 +25,9 @@
 
 package com.sun.tools.javac.parser;
 
+import java.util.ResourceBundle;
+
+import com.sun.tools.javac.api.Formattable;
 
 /** An interface that defines codes for Java source tokens
  *  returned from lexical analysis.
@@ -34,7 +37,7 @@
  *  This code and its internal interfaces are subject to change or
  *  deletion without notice.</b>
  */
-public enum Token {
+public enum Token implements Formattable {
     EOF,
     ERROR,
     IDENTIFIER,
@@ -155,4 +158,41 @@
     }
 
     public final String name;
+
+    public String toString() {
+        switch (this) {
+        case IDENTIFIER:
+            return "token.identifier";
+        case CHARLITERAL:
+            return "token.character";
+        case STRINGLITERAL:
+            return "token.string";
+        case INTLITERAL:
+            return "token.integer";
+        case LONGLITERAL:
+            return "token.long-integer";
+        case FLOATLITERAL:
+            return "token.float";
+        case DOUBLELITERAL:
+            return "token.double";
+        case ERROR:
+            return "token.bad-symbol";
+        case EOF:
+            return "token.end-of-input";
+        case DOT: case COMMA: case SEMI: case LPAREN: case RPAREN:
+        case LBRACKET: case RBRACKET: case LBRACE: case RBRACE:
+            return "'" + name + "'";
+        default:
+            return name;
+        }
+    }
+
+    public String getKind() {
+        return "Token";
+    }
+
+    public String toString(ResourceBundle bundle) {
+        String s = toString();
+        return s.startsWith("token.") ? bundle.getString("compiler.misc." + s) : s;
+    }
 }
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Jul 24 19:06:57 2008 +0100
@@ -81,9 +81,14 @@
 compiler.err.call.must.be.first.stmt.in.ctor=\
     call to {0} must be first statement in constructor
 compiler.err.cant.apply.symbol=\
-    {0} in {1} cannot be applied to {2}({3})
-compiler.err.cant.apply.symbol.1=\
-    {0} in {1} cannot be applied to {2}({3}); {4}
+    {0} {1} in {4} {5} cannot be applied to given types\n\
+    required: {2}\n\
+    found: {3}
+ compiler.err.cant.apply.symbol.1=\
+    {0} {1} in {4} {5} cannot be applied to given types;\n\
+    required: {2}\n\
+    found: {3}\n\
+    reason: {6}
 compiler.err.cant.assign.val.to.final.var=\
     cannot assign a value to final variable {0}
 compiler.err.cant.deref=\
@@ -940,7 +945,7 @@
 compiler.misc.type.req.exact=\
     class or interface without bounds
 compiler.misc.type.parameter=\
-    type parameter {0} 
+    type parameter {0}
 
 #####
 
@@ -980,16 +985,39 @@
 required: {0}\n\
 found   : {1}
 
-## The first argument ({0}) is a "kindname".
+## The first argument {0} is a "kindname" (e.g. 'constructor', 'field', etc.)
+## The second argument {1} is the non-resolved symbol
+## The third argument {2} is a list of type parameters (non-empty if {1} is a method)
+## The fourth argument {3} is a list of argument types (non-empty if {1} is a method)
 compiler.err.cant.resolve=\
-cannot find symbol\n\
-symbol: {0} {3}{1}{2}
+    cannot find symbol\n\
+    symbol: {0} {1}
 
-## The first argument ({0}) and fifth argument ({4}) are "kindname"s.
+compiler.err.cant.resolve.args=\
+    cannot find symbol\n\
+    symbol: {0} {1}({3})
+
+compiler.err.cant.resolve.args.params=\
+    cannot find symbol\n\
+    symbol: {0} <{2}>{1}({3})
+
+## arguments from {0} to {3} have the same meaning as above
+## The fifth argument {4} is the location "kindname" (e.g. 'constructor', 'field', etc.)
+## The sixth argument {5} is the location type
 compiler.err.cant.resolve.location=\
-cannot find symbol\n\
-symbol  : {0} {3}{1}{2}\n\
-location: {4} {5}
+    cannot find symbol\n\
+    symbol  : {0} {1}\n\
+    location: {4} {5}
+
+compiler.err.cant.resolve.location.args=\
+    cannot find symbol\n\
+    symbol  : {0} {1}({3})\n\
+    location: {4} {5}
+
+compiler.err.cant.resolve.location.args.params=\
+    cannot find symbol\n\
+    symbol  : {0} <{2}>{1}({3})\n\
+    location: {4} {5}
 
 ## The following are all possible string for "kindname".
 ## They should be called whatever the JLS calls them after it been translated
@@ -1008,55 +1036,16 @@
     type variable
 compiler.misc.kindname.type.variable.bound=\
     bound of type variable
-compiler.misc.kindname=\
-    identifier({0})
 compiler.misc.kindname.variable=\
     variable
 compiler.misc.kindname.value=\
     value
 compiler.misc.kindname.method=\
     method
-compiler.misc.kindname.variable.method=\
-    variable, method
-compiler.misc.kindname.value.method=\
-    value, method
 compiler.misc.kindname.class=\
     class
-compiler.misc.kindname.variable.class=\
-    variable, class
-compiler.misc.kindname.value.class=\
-    value, class
-compiler.misc.kindname.method.class=\
-    method, class
-compiler.misc.kindname.variable.method.class=\
-    variable, method, class
-compiler.misc.kindname.value.method.class=\
-    value, method, class
 compiler.misc.kindname.package=\
     package
-compiler.misc.kindname.variable.package=\
-    variable, package
-compiler.misc.kindname.value.package=\
-    value, package
-compiler.misc.kindname.method.package=\
-    method, package
-compiler.misc.kindname.variable.method.package=\
-    variable, method, package
-compiler.misc.kindname.value.method.package=\
-    value, method, package
-compiler.misc.kindname.class.package=\
-    class, package
-compiler.misc.kindname.variable.class.package=\
-    variable, class, package
-compiler.misc.kindname.value.class.package=\
-    value, class, package
-compiler.misc.kindname.method.class.package=\
-    method, class, package
-compiler.misc.kindname.variable.method.class.package=\
-    variable, method, class, package
-compiler.misc.kindname.value.method.class.package=\
-    value, method, class, package
-
 #####
 
 compiler.err.override.static=\
--- a/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/DiagnosticFormatter.java	Thu Jul 24 19:06:57 2008 +0100
@@ -25,6 +25,7 @@
 
 package com.sun.tools.javac.util;
 
+import java.util.Collection;
 import javax.tools.JavaFileObject;
 
 import com.sun.tools.javac.file.JavacFileManager;
@@ -145,6 +146,8 @@
             }
             else if (arg instanceof JavaFileObject)
                 sb.append(JavacFileManager.getJavacBaseFileName((JavaFileObject) arg));
+            else if (arg instanceof Collection<?>)
+                sb.append(convert((Collection<?>)arg));
             else
                 sb.append(arg);
             sep = ", ";
@@ -152,6 +155,18 @@
         return sb.toString();
     }
 
+    static <T> List<T> convert(Collection<T> c) {
+        if (c instanceof List<?>)
+            return (List<T>)c;
+        else {
+            List<T> l = List.<T>nil();
+            for (T t : c) {
+                l = l.prepend(t);
+            }
+            return l.reverse();
+        }
+    }
+
     private String format_std(JCDiagnostic d) {
         DiagnosticSource source = d.getDiagnosticSource();
         DiagnosticType type = d.getType();
--- a/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Thu Jul 24 11:12:41 2008 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/JCDiagnostic.java	Thu Jul 24 19:06:57 2008 +0100
@@ -25,12 +25,15 @@
 
 package com.sun.tools.javac.util;
 
+import java.util.ResourceBundle;
+import java.util.Collection;
 import java.util.Locale;
 import java.util.Map;
 
 import javax.tools.Diagnostic;
 import javax.tools.JavaFileObject;
 
+import com.sun.tools.javac.api.Formattable;
 import com.sun.tools.javac.file.JavacFileManager;
 import com.sun.tools.javac.tree.JCTree;
 
@@ -431,6 +434,12 @@
                 strings[i] = null;
             else if (arg instanceof JCDiagnostic)
                 strings[i] = ((JCDiagnostic) arg).getMessage(null);
+            else if (arg instanceof Collection<?>)
+                strings[i] = DiagnosticFormatter.convert((Collection<?>)arg).toString();
+            else if (arg instanceof Formattable) {
+                ResourceBundle rb = ResourceBundle.getBundle(messageBundleName);
+                strings[i] = ((Formattable)arg).toString(rb);
+            }
             else
                 strings[i] = arg.toString();
         }
--- a/test/tools/javac/5045412/out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/5045412/out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-Bar.java:13:29: compiler.err.cant.resolve.location: (- compiler.misc.kindname.class), Serializable, , , (- compiler.misc.kindname.package), java.io
+Bar.java:13:29: compiler.err.cant.resolve.location: kindname.class, Serializable, , , kindname.package, java.io
 1 error
--- a/test/tools/javac/6330920/T6330920.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/6330920/T6330920.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-T6330920.java:11:22: compiler.err.cant.resolve.location: (- compiler.misc.kindname.class), T6330920Missing, , , (- compiler.misc.kindname.class), T6330920
+T6330920.java:11:22: compiler.err.cant.resolve.location: kindname.class, T6330920Missing, , , kindname.class, T6330920
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/6717241/T6717241a.java	Thu Jul 24 19:06:57 2008 +0100
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 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     6717241
+ * @summary some diagnostic argument is prematurely converted into a String object
+ * @author  Maurizio Cimadamore
+ * @compile/fail/ref=T6717241a.out -XDstdout -XDrawDiagnostics T6717241a.java
+ */
+
+class T6717241a<X extends Object & java.io.Serializable> {
+    X x;
+    void test() {
+        //this will generate a 'cant.resolve'
+        Object o = x.v;
+        //this will generate a 'cant.resolve.args'
+        x.m1(1, "");
+        //this will generate a 'cant.resolve.args.params'
+        x.<Integer,Double>m2(1, "");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/6717241/T6717241a.out	Thu Jul 24 19:06:57 2008 +0100
@@ -0,0 +1,4 @@
+T6717241a.java:36:21: compiler.err.cant.resolve: kindname.variable, v, , 
+T6717241a.java:38:10: compiler.err.cant.resolve.args: kindname.method, m1, , int,java.lang.String
+T6717241a.java:40:10: compiler.err.cant.resolve.args.params: kindname.method, m2, java.lang.Integer,java.lang.Double, int,java.lang.String
+3 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/6717241/T6717241b.java	Thu Jul 24 19:06:57 2008 +0100
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 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     6717241
+ * @summary some diagnostic argument is prematurely converted into a String object
+ * @author  Maurizio Cimadamore
+ * @compile/fail/ref=T6717241b.out -XDstdout -XDrawDiagnostics T6717241b.java
+ */
+
+class T6717241b {
+    void test() {
+        //this will generate a 'cant.resolve.location'
+        Object o = v;
+        //this will generate a 'cant.resolve.location.args'
+        m1(1, "");
+        //this will generate a 'cant.resolve.location.args.params'
+        T6717241b.<Integer,Double>m2(1, "");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/6717241/T6717241b.out	Thu Jul 24 19:06:57 2008 +0100
@@ -0,0 +1,4 @@
+T6717241b.java:35:20: compiler.err.cant.resolve.location: kindname.variable, v, , , kindname.class, T6717241b
+T6717241b.java:37:9: compiler.err.cant.resolve.location.args: kindname.method, m1, , int,java.lang.String, kindname.class, T6717241b
+T6717241b.java:39:18: compiler.err.cant.resolve.location.args.params: kindname.method, m2, java.lang.Integer,java.lang.Double, int,java.lang.String, kindname.class, T6717241b
+3 errors
--- a/test/tools/javac/ExtendsAccess/ExtendsAccess.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/ExtendsAccess/ExtendsAccess.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,7 +1,7 @@
-ExtendsAccess.java:31:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), publicClass, , 
-ExtendsAccess.java:32:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), defaultClass, , 
-ExtendsAccess.java:33:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), protectedClass, , 
-ExtendsAccess.java:34:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), privateClass, , 
+ExtendsAccess.java:31:32: compiler.err.cant.resolve: kindname.class, publicClass, , 
+ExtendsAccess.java:32:32: compiler.err.cant.resolve: kindname.class, defaultClass, , 
+ExtendsAccess.java:33:32: compiler.err.cant.resolve: kindname.class, protectedClass, , 
+ExtendsAccess.java:34:32: compiler.err.cant.resolve: kindname.class, privateClass, , 
 ExtendsAccess.java:39:46: compiler.err.report.access: ExtendsAccess.privateClass, private, ExtendsAccess
 ExtendsAccess.java:42:48: compiler.err.not.def.public.cant.access: p.ExtendsAccess.defaultClass, p.ExtendsAccess
 ExtendsAccess.java:43:48: compiler.err.report.access: p.ExtendsAccess.protectedClass, protected, p.ExtendsAccess
@@ -12,10 +12,10 @@
 ExtendsAccess.java:85:34: compiler.err.report.access: ExtendsAccess.privateClass, private, ExtendsAccess
 ExtendsAccess.java:92:36: compiler.err.not.def.public.cant.access: p.ExtendsAccess.defaultClass, p.ExtendsAccess
 ExtendsAccess.java:101:36: compiler.err.report.access: p.ExtendsAccess.privateClass, private, p.ExtendsAccess
-ExtendsAccess.java:104:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), publicStaticClass, , 
-ExtendsAccess.java:105:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), defaultStaticClass, , 
-ExtendsAccess.java:106:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), protectedStaticClass, , 
-ExtendsAccess.java:107:32: compiler.err.cant.resolve: (- compiler.misc.kindname.class), privateStaticClass, , 
+ExtendsAccess.java:104:32: compiler.err.cant.resolve: kindname.class, publicStaticClass, , 
+ExtendsAccess.java:105:32: compiler.err.cant.resolve: kindname.class, defaultStaticClass, , 
+ExtendsAccess.java:106:32: compiler.err.cant.resolve: kindname.class, protectedStaticClass, , 
+ExtendsAccess.java:107:32: compiler.err.cant.resolve: kindname.class, privateStaticClass, , 
 ExtendsAccess.java:112:46: compiler.err.report.access: ExtendsAccess.privateStaticClass, private, ExtendsAccess
 ExtendsAccess.java:115:48: compiler.err.not.def.public.cant.access: p.ExtendsAccess.defaultStaticClass, p.ExtendsAccess
 ExtendsAccess.java:116:48: compiler.err.report.access: p.ExtendsAccess.protectedStaticClass, protected, p.ExtendsAccess
@@ -26,10 +26,10 @@
 ExtendsAccess.java:158:34: compiler.err.report.access: ExtendsAccess.privateStaticClass, private, ExtendsAccess
 ExtendsAccess.java:165:36: compiler.err.not.def.public.cant.access: p.ExtendsAccess.defaultStaticClass, p.ExtendsAccess
 ExtendsAccess.java:174:36: compiler.err.report.access: p.ExtendsAccess.privateStaticClass, private, p.ExtendsAccess
-ExtendsAccess.java:177:57: compiler.err.cant.resolve: (- compiler.misc.kindname.class), publicInterface, , 
-ExtendsAccess.java:178:57: compiler.err.cant.resolve: (- compiler.misc.kindname.class), defaultInterface, , 
-ExtendsAccess.java:179:57: compiler.err.cant.resolve: (- compiler.misc.kindname.class), protectedInterface, , 
-ExtendsAccess.java:180:57: compiler.err.cant.resolve: (- compiler.misc.kindname.class), privateInterface, , 
+ExtendsAccess.java:177:57: compiler.err.cant.resolve: kindname.class, publicInterface, , 
+ExtendsAccess.java:178:57: compiler.err.cant.resolve: kindname.class, defaultInterface, , 
+ExtendsAccess.java:179:57: compiler.err.cant.resolve: kindname.class, protectedInterface, , 
+ExtendsAccess.java:180:57: compiler.err.cant.resolve: kindname.class, privateInterface, , 
 ExtendsAccess.java:186:33: compiler.err.report.access: ExtendsAccess.privateInterface, private, ExtendsAccess
 ExtendsAccess.java:191:35: compiler.err.not.def.public.cant.access: p.ExtendsAccess.defaultInterface, p.ExtendsAccess
 ExtendsAccess.java:193:35: compiler.err.report.access: p.ExtendsAccess.protectedInterface, protected, p.ExtendsAccess
--- a/test/tools/javac/NonStaticFieldExpr1.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/NonStaticFieldExpr1.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-NonStaticFieldExpr1.java:10:30: compiler.err.non-static.cant.be.ref: (- compiler.misc.kindname.variable), x
+NonStaticFieldExpr1.java:10:30: compiler.err.non-static.cant.be.ref: kindname.variable, x
 1 error
--- a/test/tools/javac/NonStaticFieldExpr2.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/NonStaticFieldExpr2.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-NonStaticFieldExpr2.java:14:33: compiler.err.non-static.cant.be.ref: (- compiler.misc.kindname.variable), x
+NonStaticFieldExpr2.java:14:33: compiler.err.non-static.cant.be.ref: kindname.variable, x
 1 error
--- a/test/tools/javac/NonStaticFieldExpr3.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/NonStaticFieldExpr3.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-NonStaticFieldExpr3.java:14:30: compiler.err.non-static.cant.be.ref: (- compiler.misc.kindname.variable), x
+NonStaticFieldExpr3.java:14:30: compiler.err.non-static.cant.be.ref: kindname.variable, x
 1 error
--- a/test/tools/javac/T6247324.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/T6247324.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-T6247324.java:18:6: compiler.err.cant.resolve.location: (- compiler.misc.kindname.class), Seetharam, , , (- compiler.misc.kindname.class), Pair<X,Y>
+T6247324.java:18:6: compiler.err.cant.resolve.location: kindname.class, Seetharam, , , kindname.class, Pair<X,Y>
 1 error
--- a/test/tools/javac/annotations/6365854/test1.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/annotations/6365854/test1.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,2 +1,2 @@
-- compiler.warn.annotation.method.not.found.reason: test.annotation.TestAnnotation, test, class file for test.annotation.TestAnnotation not found
+- compiler.warn.annotation.method.not.found.reason: test.annotation.TestAnnotation, test, (- compiler.misc.class.file.not.found: test.annotation.TestAnnotation)
 1 warning
--- a/test/tools/javac/generics/inference/6611449/T6611449.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/generics/inference/6611449/T6611449.out	Thu Jul 24 19:06:57 2008 +0100
@@ -1,5 +1,5 @@
-T6611449.java:41:9: compiler.err.cant.resolve.location: (- compiler.misc.kindname.constructor), T6611449, (int), , (- compiler.misc.kindname.class), T6611449<S>
-T6611449.java:42:9: compiler.err.cant.resolve.location: (- compiler.misc.kindname.constructor), T6611449, (int,int), , (- compiler.misc.kindname.class), T6611449<S>
-T6611449.java:43:9: compiler.err.cant.apply.symbol: <T>m1(T), T6611449<S>, , int, null
-T6611449.java:44:9: compiler.err.cant.apply.symbol: <T>m2(T,T), T6611449<S>, , int,int, null
+T6611449.java:41:9: compiler.err.cant.resolve.location.args: kindname.constructor, T6611449, , int, kindname.class, T6611449<S>
+T6611449.java:42:9: compiler.err.cant.resolve.location.args: kindname.constructor, T6611449, , int,int, kindname.class, T6611449<S>
+T6611449.java:43:9: compiler.err.cant.apply.symbol: kindname.method, m1, T, int, kindname.class, T6611449<S>, null
+T6611449.java:44:9: compiler.err.cant.apply.symbol: kindname.method, m2, T,T, int,int, kindname.class, T6611449<S>, null
 4 errors
--- a/test/tools/javac/policy/byfile.ABD.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/policy/byfile.ABD.out	Thu Jul 24 19:06:57 2008 +0100
@@ -3,7 +3,7 @@
 [attribute A2]
 [attribute B]
 [attribute B1]
-B.java:12:9: compiler.err.cant.resolve.location: (- compiler.misc.kindname.variable), x, , , (- compiler.misc.kindname.class), B1
+B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, B1
 [attribute B2]
 [attribute D]
 [attribute D1]
--- a/test/tools/javac/policy/bytodo.ABD.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/policy/bytodo.ABD.out	Thu Jul 24 19:06:57 2008 +0100
@@ -15,7 +15,7 @@
 [desugar B]
 [generate code B]
 [attribute B1]
-B.java:12:9: compiler.err.cant.resolve.location: (- compiler.misc.kindname.variable), x, , , (- compiler.misc.kindname.class), B1
+B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, B1
 [attribute B2]
 [attribute D]
 [attribute D1]
--- a/test/tools/javac/policy/simple.ABD.out	Thu Jul 24 11:12:41 2008 +0100
+++ b/test/tools/javac/policy/simple.ABD.out	Thu Jul 24 19:06:57 2008 +0100
@@ -3,7 +3,7 @@
 [attribute A2]
 [attribute B]
 [attribute B1]
-B.java:12:9: compiler.err.cant.resolve.location: (- compiler.misc.kindname.variable), x, , , (- compiler.misc.kindname.class), B1
+B.java:12:9: compiler.err.cant.resolve.location: kindname.variable, x, , , kindname.class, B1
 [attribute B2]
 [attribute D]
 [attribute D1]