提交 7c768328 编写于 作者: M mcimadamore

6735840: Need a type/symbol visitor printer

Summary: Added type/symbol visitor printer with support for localization
Reviewed-by: jjg
上级 a581de43
......@@ -132,6 +132,10 @@ public abstract class Symbol implements Element {
throw new AssertionError();
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitSymbol(this, p);
}
/** The Java source which this symbol represents.
* A description of this symbol; overrides Object.
*/
......@@ -477,6 +481,10 @@ public abstract class Symbol implements Element {
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return other.accept(v, p);
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitSymbol(other, p);
}
}
/** A class for type symbols. Type variables are represented by instances
......@@ -570,6 +578,10 @@ public abstract class Symbol implements Element {
return v.visitTypeParameter(this, p);
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitTypeSymbol(this, p);
}
public List<Type> getBounds() {
TypeVar t = (TypeVar)type;
Type bound = t.getUpperBound();
......@@ -653,6 +665,10 @@ public abstract class Symbol implements Element {
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitPackage(this, p);
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitPackageSymbol(this, p);
}
}
/** A class for class symbols
......@@ -843,6 +859,10 @@ public abstract class Symbol implements Element {
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitType(this, p);
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitClassSymbol(this, p);
}
}
......@@ -969,6 +989,10 @@ public abstract class Symbol implements Element {
assert !(data instanceof Env<?>) : this;
this.data = data;
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitVarSymbol(this, p);
}
}
/** A class for method symbols.
......@@ -1232,6 +1256,10 @@ public abstract class Symbol implements Element {
return v.visitExecutable(this, p);
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitMethodSymbol(this, p);
}
public Type getReturnType() {
return asType().getReturnType();
}
......@@ -1251,6 +1279,10 @@ public abstract class Symbol implements Element {
super(PUBLIC | STATIC, name, type, owner);
this.opcode = opcode;
}
public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
return v.visitOperatorSymbol(this, p);
}
}
/** Symbol completer interface.
......@@ -1308,4 +1340,28 @@ public abstract class Symbol implements Element {
}
}
/**
* A visitor for symbols. A visitor is used to implement operations
* (or relations) on symbols. Most common operations on types are
* binary relations and this interface is designed for binary
* relations, that is, operations on the form
* Symbol&nbsp;&times;&nbsp;P&nbsp;&rarr;&nbsp;R.
* <!-- In plain text: Type x P -> R -->
*
* @param <R> the return type of the operation implemented by this
* visitor; use Void if no return type is needed.
* @param <P> 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 interface Visitor<R,P> {
R visitClassSymbol(ClassSymbol s, P arg);
R visitMethodSymbol(MethodSymbol s, P arg);
R visitPackageSymbol(PackageSymbol s, P arg);
R visitOperatorSymbol(OperatorSymbol s, P arg);
R visitVarSymbol(VarSymbol s, P arg);
R visitTypeSymbol(TypeSymbol s, P arg);
R visitSymbol(Symbol s, P arg);
}
}
......@@ -67,6 +67,7 @@ public class Types {
new Context.Key<Types>();
final Symtab syms;
final Messages messages;
final Names names;
final boolean allowBoxing;
final ClassReader reader;
......@@ -92,6 +93,7 @@ public class Types {
source = Source.instance(context);
chk = Check.instance(context);
capturedName = names.fromString("<captured wildcard>");
messages = Messages.instance(context);
}
// </editor-fold>
......@@ -1589,10 +1591,10 @@ public class Types {
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 @@ public class Types {
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="printType">
/**
* 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<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
* 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<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">
/**
* 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;
......@@ -3235,6 +3461,28 @@ public class Types {
public R visitErrorType(ErrorType t, S s) { return visitType(t, s); }
}
/**
* 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 <R> the return type of the operation implemented by this
* visitor; use Void if no return type is needed.
* @param <S> 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<R,S> implements Symbol.Visitor<R,S> {
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 <em>simple</em> visitor for types. This visitor is simple as
* captured wildcards, for-all types (generic methods), and
......
......@@ -823,6 +823,12 @@ compiler.err.orphaned=\
compiler.misc.anonymous.class=\
<anonymous {0}>
compiler.misc.type.captureof=\
capture#{0} of {1}
compiler.misc.type.none=\
<none>
compiler.misc.unnamed.package=\
unnamed package
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册