diff -r ddd110646d21 -r 609fb59657b4 src/share/classes/com/sun/tools/javac/code/Types.java --- a/src/share/classes/com/sun/tools/javac/code/Types.java Mon Sep 29 11:34:43 2008 +0100 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java Mon Sep 29 11:48:09 2008 +0100 @@ -67,6 +67,7 @@ new Context.Key(); final Symtab syms; + final Messages messages; final Names names; final boolean allowBoxing; final ClassReader reader; @@ -92,6 +93,7 @@ source = Source.instance(context); chk = Check.instance(context); capturedName = names.fromString(""); + messages = Messages.instance(context); } // @@ -1589,10 +1591,10 @@ syms.noSymbol); if (bounds.head.tag == TYPEVAR) // error condition, recover - bc.erasure_field = syms.objectType; - else - bc.erasure_field = erasure(bounds.head); - bc.members_field = new Scope(bc); + bc.erasure_field = syms.objectType; + else + bc.erasure_field = erasure(bounds.head); + bc.members_field = new Scope(bc); ClassType bt = (ClassType)bc.type; bt.allparams_field = List.nil(); if (supertype != null) { @@ -2249,10 +2251,234 @@ } // + // + /** + * Visitor 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); + } + // where + private TypePrinter typePrinter = new TypePrinter(); + + public class TypePrinter extends DefaultTypeVisitor { + + public String visit(List ts, Locale locale) { + ListBuffer 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 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 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); + } + }; + // + + // + /** + * Visitor for generating a string representation of a given symbol + * accordingly to a given locale + */ + public String toString(Symbol t, Locale locale) { + return symbolPrinter.visit(t, locale); + } + // where + private SymbolPrinter symbolPrinter = new SymbolPrinter(); + + public class SymbolPrinter extends DefaultSymbolVisitor { + + @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 ts, Locale locale) { + ListBuffer 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); + } + }; + // + // /** * This toString is slightly more descriptive than the one on Type. + * + * @deprecated Types.toString(Type t, Locale l) provides better support + * for localization */ + @Deprecated public String toString(Type t) { if (t.tag == FORALL) { ForAll forAll = (ForAll)t; @@ -3236,6 +3462,28 @@ } /** + * A default visitor for symbols. All visitor methods except + * visitSymbol are implemented by delegating to visitSymbol. Concrete + * subclasses must provide an implementation of visitSymbol and can + * override other methods as needed. + * + * @param the return type of the operation implemented by this + * visitor; use Void if no return type is needed. + * @param the type of the second argument (the first being the + * symbol itself) of the operation implemented by this visitor; use + * Void if a second argument is not needed. + */ + public static abstract class DefaultSymbolVisitor implements Symbol.Visitor { + final public R visit(Symbol s, S arg) { return s.accept(this, arg); } + public R visitClassSymbol(ClassSymbol s, S arg) { return visitSymbol(s, arg); } + public R visitMethodSymbol(MethodSymbol s, S arg) { return visitSymbol(s, arg); } + public R visitOperatorSymbol(OperatorSymbol s, S arg) { return visitSymbol(s, arg); } + public R visitPackageSymbol(PackageSymbol s, S arg) { return visitSymbol(s, arg); } + public R visitTypeSymbol(TypeSymbol s, S arg) { return visitSymbol(s, arg); } + public R visitVarSymbol(VarSymbol s, S arg) { return visitSymbol(s, arg); } + } + + /** * A simple visitor for types. This visitor is simple as * captured wildcards, for-all types (generic methods), and * undetermined type variables (part of inference) are hidden.