mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-01 13:45:30 +00:00
6799605: Basic/Raw formatters should use type/symbol printer instead of toString()
Create new combo type/symbol visitor printer used by all diagnostic formatters Reviewed-by: jjg
This commit is contained in:
parent
938af6ca9f
commit
a46fd793cc
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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 @@ package com.sun.tools.javac.code;
|
||||
|
||||
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 @@ public class Types {
|
||||
return t;
|
||||
else
|
||||
return visit(t);
|
||||
}
|
||||
}
|
||||
|
||||
List<Type> subst(List<Type> ts) {
|
||||
if (from.tail == null)
|
||||
@ -2279,225 +2281,21 @@ public class Types {
|
||||
}
|
||||
// </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 @@ public class Types {
|
||||
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) {
|
||||
|
||||
@ -836,6 +836,9 @@ compiler.misc.anonymous.class=\
|
||||
compiler.misc.type.captureof=\
|
||||
capture#{0} of {1}
|
||||
|
||||
compiler.misc.type.captureof.1=\
|
||||
capture#{0}
|
||||
|
||||
compiler.misc.type.none=\
|
||||
<none>
|
||||
|
||||
|
||||
@ -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.DiagnosticPart;
|
||||
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,9 +64,23 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
* 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
|
||||
@ -70,6 +88,7 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
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 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
}
|
||||
}
|
||||
|
||||
@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 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
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 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ public class BasicDiagnosticFormatter extends AbstractDiagnosticFormatter {
|
||||
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);
|
||||
|
||||
@ -54,7 +54,7 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
|
||||
}
|
||||
|
||||
//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 final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
|
||||
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 @@ public final class RawDiagnosticFormatter extends AbstractDiagnosticFormatter {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
43
langtools/test/tools/javac/Diagnostics/6799605/T6799605.java
Normal file
43
langtools/test/tools/javac/Diagnostics/6799605/T6799605.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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()
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user