6735840: Need a type/symbol visitor printer

Mon, 29 Sep 2008 11:48:09 +0100

author
mcimadamore
date
Mon, 29 Sep 2008 11:48:09 +0100
changeset 121
609fb59657b4
parent 120
ddd110646d21
child 122
1a9276e7cb18

6735840: Need a type/symbol visitor printer
Summary: Added type/symbol visitor printer with support for localization
Reviewed-by: jjg

src/share/classes/com/sun/tools/javac/code/Symbol.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/code/Types.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/resources/compiler.properties file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 29 11:34:43 2008 +0100
     1.2 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 29 11:48:09 2008 +0100
     1.3 @@ -132,6 +132,10 @@
     1.4          throw new AssertionError();
     1.5      }
     1.6  
     1.7 +    public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
     1.8 +        return v.visitSymbol(this, p);
     1.9 +    }
    1.10 +
    1.11      /** The Java source which this symbol represents.
    1.12       *  A description of this symbol; overrides Object.
    1.13       */
    1.14 @@ -477,6 +481,10 @@
    1.15          public <R, P> R accept(ElementVisitor<R, P> v, P p) {
    1.16              return other.accept(v, p);
    1.17          }
    1.18 +
    1.19 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.20 +            return v.visitSymbol(other, p);
    1.21 +        }
    1.22      }
    1.23  
    1.24      /** A class for type symbols. Type variables are represented by instances
    1.25 @@ -570,6 +578,10 @@
    1.26              return v.visitTypeParameter(this, p);
    1.27          }
    1.28  
    1.29 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.30 +            return v.visitTypeSymbol(this, p);
    1.31 +        }
    1.32 +
    1.33          public List<Type> getBounds() {
    1.34              TypeVar t = (TypeVar)type;
    1.35              Type bound = t.getUpperBound();
    1.36 @@ -653,6 +665,10 @@
    1.37          public <R, P> R accept(ElementVisitor<R, P> v, P p) {
    1.38              return v.visitPackage(this, p);
    1.39          }
    1.40 +
    1.41 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.42 +            return v.visitPackageSymbol(this, p);
    1.43 +        }
    1.44      }
    1.45  
    1.46      /** A class for class symbols
    1.47 @@ -843,6 +859,10 @@
    1.48          public <R, P> R accept(ElementVisitor<R, P> v, P p) {
    1.49              return v.visitType(this, p);
    1.50          }
    1.51 +
    1.52 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.53 +            return v.visitClassSymbol(this, p);
    1.54 +        }
    1.55      }
    1.56  
    1.57  
    1.58 @@ -969,6 +989,10 @@
    1.59              assert !(data instanceof Env<?>) : this;
    1.60              this.data = data;
    1.61          }
    1.62 +
    1.63 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.64 +            return v.visitVarSymbol(this, p);
    1.65 +        }
    1.66      }
    1.67  
    1.68      /** A class for method symbols.
    1.69 @@ -1232,6 +1256,10 @@
    1.70              return v.visitExecutable(this, p);
    1.71          }
    1.72  
    1.73 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.74 +            return v.visitMethodSymbol(this, p);
    1.75 +        }
    1.76 +
    1.77          public Type getReturnType() {
    1.78              return asType().getReturnType();
    1.79          }
    1.80 @@ -1251,6 +1279,10 @@
    1.81              super(PUBLIC | STATIC, name, type, owner);
    1.82              this.opcode = opcode;
    1.83          }
    1.84 +
    1.85 +        public <R, P> R accept(Symbol.Visitor<R, P> v, P p) {
    1.86 +            return v.visitOperatorSymbol(this, p);
    1.87 +        }
    1.88      }
    1.89  
    1.90      /** Symbol completer interface.
    1.91 @@ -1308,4 +1340,28 @@
    1.92          }
    1.93  
    1.94      }
    1.95 +
    1.96 +    /**
    1.97 +     * A visitor for symbols.  A visitor is used to implement operations
    1.98 +     * (or relations) on symbols.  Most common operations on types are
    1.99 +     * binary relations and this interface is designed for binary
   1.100 +     * relations, that is, operations on the form
   1.101 +     * Symbol&nbsp;&times;&nbsp;P&nbsp;&rarr;&nbsp;R.
   1.102 +     * <!-- In plain text: Type x P -> R -->
   1.103 +     *
   1.104 +     * @param <R> the return type of the operation implemented by this
   1.105 +     * visitor; use Void if no return type is needed.
   1.106 +     * @param <P> the type of the second argument (the first being the
   1.107 +     * symbol itself) of the operation implemented by this visitor; use
   1.108 +     * Void if a second argument is not needed.
   1.109 +     */
   1.110 +    public interface Visitor<R,P> {
   1.111 +        R visitClassSymbol(ClassSymbol s, P arg);
   1.112 +        R visitMethodSymbol(MethodSymbol s, P arg);
   1.113 +        R visitPackageSymbol(PackageSymbol s, P arg);
   1.114 +        R visitOperatorSymbol(OperatorSymbol s, P arg);
   1.115 +        R visitVarSymbol(VarSymbol s, P arg);
   1.116 +        R visitTypeSymbol(TypeSymbol s, P arg);
   1.117 +        R visitSymbol(Symbol s, P arg);
   1.118 +    }
   1.119  }
     2.1 --- a/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Sep 29 11:34:43 2008 +0100
     2.2 +++ b/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Sep 29 11:48:09 2008 +0100
     2.3 @@ -67,6 +67,7 @@
     2.4          new Context.Key<Types>();
     2.5  
     2.6      final Symtab syms;
     2.7 +    final Messages messages;
     2.8      final Names names;
     2.9      final boolean allowBoxing;
    2.10      final ClassReader reader;
    2.11 @@ -92,6 +93,7 @@
    2.12          source = Source.instance(context);
    2.13          chk = Check.instance(context);
    2.14          capturedName = names.fromString("<captured wildcard>");
    2.15 +        messages = Messages.instance(context);
    2.16      }
    2.17      // </editor-fold>
    2.18  
    2.19 @@ -1589,10 +1591,10 @@
    2.20                              syms.noSymbol);
    2.21          if (bounds.head.tag == TYPEVAR)
    2.22              // error condition, recover
    2.23 -            bc.erasure_field = syms.objectType;
    2.24 -        else
    2.25 -            bc.erasure_field = erasure(bounds.head);
    2.26 -        bc.members_field = new Scope(bc);
    2.27 +                bc.erasure_field = syms.objectType;
    2.28 +            else
    2.29 +                bc.erasure_field = erasure(bounds.head);
    2.30 +            bc.members_field = new Scope(bc);
    2.31          ClassType bt = (ClassType)bc.type;
    2.32          bt.allparams_field = List.nil();
    2.33          if (supertype != null) {
    2.34 @@ -2249,10 +2251,234 @@
    2.35      }
    2.36      // </editor-fold>
    2.37  
    2.38 +    // <editor-fold defaultstate="collapsed" desc="printType">
    2.39 +    /**
    2.40 +     * Visitor for generating a string representation of a given type
    2.41 +     * accordingly to a given locale
    2.42 +     */
    2.43 +    public String toString(Type t, Locale locale) {
    2.44 +        return typePrinter.visit(t, locale);
    2.45 +    }
    2.46 +    // where
    2.47 +    private TypePrinter typePrinter = new TypePrinter();
    2.48 +
    2.49 +    public class TypePrinter extends DefaultTypeVisitor<String, Locale> {
    2.50 +
    2.51 +        public String visit(List<Type> ts, Locale locale) {
    2.52 +            ListBuffer<String> sbuf = lb();
    2.53 +            for (Type t : ts) {
    2.54 +                sbuf.append(visit(t, locale));
    2.55 +            }
    2.56 +            return sbuf.toList().toString();
    2.57 +        }
    2.58 +
    2.59 +        @Override
    2.60 +        public String visitCapturedType(CapturedType t, Locale locale) {
    2.61 +            return messages.getLocalizedString("compiler.misc.type.captureof",
    2.62 +                        (t.hashCode() & 0xFFFFFFFFL) % Type.CapturedType.PRIME,
    2.63 +                        visit(t.wildcard, locale));
    2.64 +        }
    2.65 +
    2.66 +        @Override
    2.67 +        public String visitForAll(ForAll t, Locale locale) {
    2.68 +            return "<" + visit(t.tvars, locale) + ">" + visit(t.qtype, locale);
    2.69 +        }
    2.70 +
    2.71 +        @Override
    2.72 +        public String visitUndetVar(UndetVar t, Locale locale) {
    2.73 +            if (t.inst != null) {
    2.74 +                return visit(t.inst, locale);
    2.75 +            } else {
    2.76 +                return visit(t.qtype, locale) + "?";
    2.77 +            }
    2.78 +        }
    2.79 +
    2.80 +        @Override
    2.81 +        public String visitArrayType(ArrayType t, Locale locale) {
    2.82 +            return visit(t.elemtype, locale) + "[]";
    2.83 +        }
    2.84 +
    2.85 +        @Override
    2.86 +        public String visitClassType(ClassType t, Locale locale) {
    2.87 +            StringBuffer buf = new StringBuffer();
    2.88 +            if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
    2.89 +                buf.append(visit(t.getEnclosingType(), locale));
    2.90 +                buf.append(".");
    2.91 +                buf.append(className(t, false, locale));
    2.92 +            } else {
    2.93 +                buf.append(className(t, true, locale));
    2.94 +            }
    2.95 +            if (t.getTypeArguments().nonEmpty()) {
    2.96 +                buf.append('<');
    2.97 +                buf.append(visit(t.getTypeArguments(), locale));
    2.98 +                buf.append(">");
    2.99 +            }
   2.100 +            return buf.toString();
   2.101 +        }
   2.102 +
   2.103 +        @Override
   2.104 +        public String visitMethodType(MethodType t, Locale locale) {
   2.105 +            return "(" + printMethodArgs(t.argtypes, false, locale) + ")" + visit(t.restype, locale);
   2.106 +        }
   2.107 +
   2.108 +        @Override
   2.109 +        public String visitPackageType(PackageType t, Locale locale) {
   2.110 +            return t.tsym.getQualifiedName().toString();
   2.111 +        }
   2.112 +
   2.113 +        @Override
   2.114 +        public String visitWildcardType(WildcardType t, Locale locale) {
   2.115 +            StringBuffer s = new StringBuffer();
   2.116 +            s.append(t.kind);
   2.117 +            if (t.kind != UNBOUND) {
   2.118 +                s.append(visit(t.type, locale));
   2.119 +            }
   2.120 +            return s.toString();
   2.121 +        }
   2.122 +
   2.123 +
   2.124 +        public String visitType(Type t, Locale locale) {
   2.125 +            String s = (t.tsym == null || t.tsym.name == null)
   2.126 +                    ? messages.getLocalizedString("compiler.misc.type.none")
   2.127 +                    : t.tsym.name.toString();
   2.128 +            return s;
   2.129 +        }
   2.130 +
   2.131 +        protected String className(ClassType t, boolean longform, Locale locale) {
   2.132 +            Symbol sym = t.tsym;
   2.133 +            if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
   2.134 +                StringBuffer s = new StringBuffer(visit(supertype(t), locale));
   2.135 +                for (List<Type> is = interfaces(t); is.nonEmpty(); is = is.tail) {
   2.136 +                    s.append("&");
   2.137 +                    s.append(visit(is.head, locale));
   2.138 +                }
   2.139 +                return s.toString();
   2.140 +            } else if (sym.name.length() == 0) {
   2.141 +                String s;
   2.142 +                ClassType norm = (ClassType) t.tsym.type;
   2.143 +                if (norm == null) {
   2.144 +                    s = getLocalizedString(locale, "compiler.misc.anonymous.class", (Object) null);
   2.145 +                } else if (interfaces(norm).nonEmpty()) {
   2.146 +                    s = getLocalizedString(locale, "compiler.misc.anonymous.class",
   2.147 +                            visit(interfaces(norm).head, locale));
   2.148 +                } else {
   2.149 +                    s = getLocalizedString(locale, "compiler.misc.anonymous.class",
   2.150 +                            visit(supertype(norm), locale));
   2.151 +                }
   2.152 +                return s;
   2.153 +            } else if (longform) {
   2.154 +                return sym.getQualifiedName().toString();
   2.155 +            } else {
   2.156 +                return sym.name.toString();
   2.157 +            }
   2.158 +        }
   2.159 +
   2.160 +        protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
   2.161 +            if (!varArgs) {
   2.162 +                return visit(args, locale);
   2.163 +            } else {
   2.164 +                StringBuffer buf = new StringBuffer();
   2.165 +                while (args.tail.nonEmpty()) {
   2.166 +                    buf.append(visit(args.head, locale));
   2.167 +                    args = args.tail;
   2.168 +                    buf.append(',');
   2.169 +                }
   2.170 +                if (args.head.tag == ARRAY) {
   2.171 +                    buf.append(visit(((ArrayType) args.head).elemtype, locale));
   2.172 +                    buf.append("...");
   2.173 +                } else {
   2.174 +                    buf.append(visit(args.head, locale));
   2.175 +                }
   2.176 +                return buf.toString();
   2.177 +            }
   2.178 +        }
   2.179 +
   2.180 +        protected String getLocalizedString(Locale locale, String key, Object... args) {
   2.181 +            return messages.getLocalizedString(key, args);
   2.182 +        }
   2.183 +    };
   2.184 +    // </editor-fold>
   2.185 +
   2.186 +    // <editor-fold defaultstate="collapsed" desc="printSymbol">
   2.187 +    /**
   2.188 +     * Visitor for generating a string representation of a given symbol
   2.189 +     * accordingly to a given locale
   2.190 +     */
   2.191 +    public String toString(Symbol t, Locale locale) {
   2.192 +        return symbolPrinter.visit(t, locale);
   2.193 +    }
   2.194 +    // where
   2.195 +    private SymbolPrinter symbolPrinter = new SymbolPrinter();
   2.196 +
   2.197 +    public class SymbolPrinter extends DefaultSymbolVisitor<String, Locale> {
   2.198 +
   2.199 +        @Override
   2.200 +        public String visitClassSymbol(ClassSymbol sym, Locale locale) {
   2.201 +            return sym.name.isEmpty()
   2.202 +                    ? getLocalizedString(locale, "compiler.misc.anonymous.class", sym.flatname)
   2.203 +                    : sym.fullname.toString();
   2.204 +        }
   2.205 +
   2.206 +        @Override
   2.207 +        public String visitMethodSymbol(MethodSymbol s, Locale locale) {
   2.208 +            if ((s.flags() & BLOCK) != 0) {
   2.209 +                return s.owner.name.toString();
   2.210 +            } else {
   2.211 +                String ms = (s.name == names.init)
   2.212 +                        ? s.owner.name.toString()
   2.213 +                        : s.name.toString();
   2.214 +                if (s.type != null) {
   2.215 +                    if (s.type.tag == FORALL) {
   2.216 +                        ms = "<" + typePrinter.visit(s.type.getTypeArguments(), locale) + ">" + ms;
   2.217 +                    }
   2.218 +                    ms += "(" + typePrinter.printMethodArgs(
   2.219 +                            s.type.getParameterTypes(),
   2.220 +                            (s.flags() & VARARGS) != 0,
   2.221 +                            locale) + ")";
   2.222 +                }
   2.223 +                return ms;
   2.224 +            }
   2.225 +        }
   2.226 +
   2.227 +        @Override
   2.228 +        public String visitOperatorSymbol(OperatorSymbol s, Locale locale) {
   2.229 +            return visitMethodSymbol(s, locale);
   2.230 +        }
   2.231 +
   2.232 +        @Override
   2.233 +        public String visitPackageSymbol(PackageSymbol s, Locale locale) {
   2.234 +            return s.name.isEmpty()
   2.235 +                    ? getLocalizedString(locale, "compiler.misc.unnamed.package")
   2.236 +                    : s.fullname.toString();
   2.237 +        }
   2.238 +
   2.239 +        @Override
   2.240 +        public String visitSymbol(Symbol s, Locale locale) {
   2.241 +            return s.name.toString();
   2.242 +        }
   2.243 +
   2.244 +        public String visit(List<Symbol> ts, Locale locale) {
   2.245 +            ListBuffer<String> sbuf = lb();
   2.246 +            for (Symbol t : ts) {
   2.247 +                sbuf.append(visit(t, locale));
   2.248 +            }
   2.249 +            return sbuf.toList().toString();
   2.250 +        }
   2.251 +
   2.252 +        protected String getLocalizedString(Locale locale, String key, Object... args) {
   2.253 +            return messages.getLocalizedString(key, args);
   2.254 +        }
   2.255 +    };
   2.256 +    // </editor-fold>
   2.257 +
   2.258      // <editor-fold defaultstate="collapsed" desc="toString">
   2.259      /**
   2.260       * This toString is slightly more descriptive than the one on Type.
   2.261 +     *
   2.262 +     * @deprecated Types.toString(Type t, Locale l) provides better support
   2.263 +     * for localization
   2.264       */
   2.265 +    @Deprecated
   2.266      public String toString(Type t) {
   2.267          if (t.tag == FORALL) {
   2.268              ForAll forAll = (ForAll)t;
   2.269 @@ -3236,6 +3462,28 @@
   2.270      }
   2.271  
   2.272      /**
   2.273 +     * A default visitor for symbols.  All visitor methods except
   2.274 +     * visitSymbol are implemented by delegating to visitSymbol.  Concrete
   2.275 +     * subclasses must provide an implementation of visitSymbol and can
   2.276 +     * override other methods as needed.
   2.277 +     *
   2.278 +     * @param <R> the return type of the operation implemented by this
   2.279 +     * visitor; use Void if no return type is needed.
   2.280 +     * @param <S> the type of the second argument (the first being the
   2.281 +     * symbol itself) of the operation implemented by this visitor; use
   2.282 +     * Void if a second argument is not needed.
   2.283 +     */
   2.284 +    public static abstract class DefaultSymbolVisitor<R,S> implements Symbol.Visitor<R,S> {
   2.285 +        final public R visit(Symbol s, S arg)                   { return s.accept(this, arg); }
   2.286 +        public R visitClassSymbol(ClassSymbol s, S arg)         { return visitSymbol(s, arg); }
   2.287 +        public R visitMethodSymbol(MethodSymbol s, S arg)       { return visitSymbol(s, arg); }
   2.288 +        public R visitOperatorSymbol(OperatorSymbol s, S arg)   { return visitSymbol(s, arg); }
   2.289 +        public R visitPackageSymbol(PackageSymbol s, S arg)     { return visitSymbol(s, arg); }
   2.290 +        public R visitTypeSymbol(TypeSymbol s, S arg)           { return visitSymbol(s, arg); }
   2.291 +        public R visitVarSymbol(VarSymbol s, S arg)             { return visitSymbol(s, arg); }
   2.292 +    }
   2.293 +
   2.294 +    /**
   2.295       * A <em>simple</em> visitor for types.  This visitor is simple as
   2.296       * captured wildcards, for-all types (generic methods), and
   2.297       * undetermined type variables (part of inference) are hidden.
     3.1 --- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Sep 29 11:34:43 2008 +0100
     3.2 +++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Sep 29 11:48:09 2008 +0100
     3.3 @@ -823,6 +823,12 @@
     3.4  compiler.misc.anonymous.class=\
     3.5      <anonymous {0}>
     3.6  
     3.7 +compiler.misc.type.captureof=\
     3.8 +    capture#{0} of {1}
     3.9 +
    3.10 +compiler.misc.type.none=\
    3.11 +    <none>
    3.12 +
    3.13  compiler.misc.unnamed.package=\
    3.14      unnamed package
    3.15  

mercurial