src/share/classes/com/sun/tools/javac/code/Printer.java

Fri, 26 Jun 2009 18:51:39 -0700

author
jjg
date
Fri, 26 Jun 2009 18:51:39 -0700
changeset 308
03944ee4fac4
parent 288
d402db1005ad
child 333
7c2d6da61646
permissions
-rw-r--r--

6843077: JSR 308: Annotations on types
Reviewed-by: jjg, mcimadamore, darcy
Contributed-by: mernst@cs.washington.edu, mali@csail.mit.edu, mpapi@csail.mit.edu

     1 /*
     2  * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Sun in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
    23  * have any questions.
    24  */
    26 package com.sun.tools.javac.code;
    28 import java.util.Locale;
    30 import com.sun.tools.javac.api.Messages;
    31 import com.sun.tools.javac.code.Type.*;
    32 import com.sun.tools.javac.code.Symbol.*;
    33 import com.sun.tools.javac.util.List;
    34 import com.sun.tools.javac.util.ListBuffer;
    36 import static com.sun.tools.javac.code.TypeTags.*;
    37 import static com.sun.tools.javac.code.BoundKind.*;
    38 import static com.sun.tools.javac.code.Flags.*;
    40 /**
    41  * A combined type/symbol visitor for generating non-trivial localized string
    42  * representation of types and symbols.
    43  */
    44 public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Visitor<String, Locale> {
    46     List<Type> seenCaptured = List.nil();
    47     static final int PRIME = 997;  // largest prime less than 1000
    49     /**
    50      * This method should be overriden in order to provide proper i18n support.
    51      *
    52      * @param locale the locale in which the string is to be rendered
    53      * @param key the key corresponding to the message to be displayed
    54      * @param args a list of optional arguments
    55      * @return localized string representation
    56      */
    57     protected abstract String localize(Locale locale, String key, Object... args);
    59     /**
    60      * Maps a captured type into an unique identifier.
    61      *
    62      * @param t the captured type for which an id is to be retrieved
    63      * @param locale locale settings
    64      * @return unique id representing this captured type
    65      */
    66     protected abstract String capturedVarId(CapturedType t, Locale locale);
    68     /**
    69      * Create a printer with default i18n support provided by Messages. By default,
    70      * captured types ids are generated using hashcode.
    71      *
    72      * @param messages Messages class to be used for i18n
    73      * @return printer visitor instance
    74      */
    75     public static Printer createStandardPrinter(final Messages messages) {
    76         return new Printer() {
    77             @Override
    78             protected String localize(Locale locale, String key, Object... args) {
    79                 return messages.getLocalizedString(locale, key, args);
    80             }
    82             @Override
    83             protected String capturedVarId(CapturedType t, Locale locale) {
    84                 return (t.hashCode() & 0xFFFFFFFFL) % PRIME + "";
    85         }};
    86     }
    88     /**
    89      * Get a localized string representation for all the types in the input list.
    90      *
    91      * @param ts types to be displayed
    92      * @param locale the locale in which the string is to be rendered
    93      * @return localized string representation
    94      */
    95     public String visitTypes(List<Type> ts, Locale locale) {
    96         ListBuffer<String> sbuf = ListBuffer.lb();
    97         for (Type t : ts) {
    98             sbuf.append(visit(t, locale));
    99         }
   100         return sbuf.toList().toString();
   101     }
   103     /**
   104      * * Get a localized string represenation for all the symbols in the input list.
   105      *
   106      * @param ts symbols to be displayed
   107      * @param locale the locale in which the string is to be rendered
   108      * @return localized string representation
   109      */
   110     public String visitSymbols(List<Symbol> ts, Locale locale) {
   111         ListBuffer<String> sbuf = ListBuffer.lb();
   112         for (Symbol t : ts) {
   113             sbuf.append(visit(t, locale));
   114         }
   115         return sbuf.toList().toString();
   116     }
   118     /**
   119      * Get a localized string represenation for a given type.
   120      *
   121      * @param ts type to be displayed
   122      * @param locale the locale in which the string is to be rendered
   123      * @return localized string representation
   124      */
   125     public String visit(Type t, Locale locale) {
   126         return t.accept(this, locale);
   127     }
   129     /**
   130      * Get a localized string represenation for a given symbol.
   131      *
   132      * @param ts symbol to be displayed
   133      * @param locale the locale in which the string is to be rendered
   134      * @return localized string representation
   135      */
   136     public String visit(Symbol s, Locale locale) {
   137         return s.accept(this, locale);
   138     }
   140     @Override
   141     public String visitCapturedType(CapturedType t, Locale locale) {
   142         if (seenCaptured.contains(t))
   143             return localize(locale, "compiler.misc.type.captureof.1",
   144                 capturedVarId(t, locale));
   145         else {
   146             try {
   147                 seenCaptured = seenCaptured.prepend(t);
   148                 return localize(locale, "compiler.misc.type.captureof",
   149                     capturedVarId(t, locale),
   150                     visit(t.wildcard, locale));
   151             }
   152             finally {
   153                 seenCaptured = seenCaptured.tail;
   154             }
   155         }
   156     }
   158     @Override
   159     public String visitForAll(ForAll t, Locale locale) {
   160         return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale);
   161     }
   163     @Override
   164     public String visitUndetVar(UndetVar t, Locale locale) {
   165         if (t.inst != null) {
   166             return visit(t.inst, locale);
   167         } else {
   168             return visit(t.qtype, locale) + "?";
   169         }
   170     }
   172     @Override
   173     public String visitArrayType(ArrayType t, Locale locale) {
   174         return visit(t.elemtype, locale) + "[]";
   175     }
   177     @Override
   178     public String visitClassType(ClassType t, Locale locale) {
   179         StringBuffer buf = new StringBuffer();
   180         if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
   181             buf.append(visit(t.getEnclosingType(), locale));
   182             buf.append(".");
   183             buf.append(className(t, false, locale));
   184         } else {
   185             buf.append(className(t, true, locale));
   186         }
   187         if (t.getTypeArguments().nonEmpty()) {
   188             buf.append('<');
   189             buf.append(visitTypes(t.getTypeArguments(), locale));
   190             buf.append(">");
   191         }
   192         return buf.toString();
   193     }
   195     @Override
   196     public String visitMethodType(MethodType t, Locale locale) {
   197         return "(" + printMethodArgs(t.argtypes, false, locale) + ")" + visit(t.restype, locale);
   198     }
   200     @Override
   201     public String visitPackageType(PackageType t, Locale locale) {
   202         return t.tsym.getQualifiedName().toString();
   203     }
   205     @Override
   206     public String visitWildcardType(WildcardType t, Locale locale) {
   207         StringBuffer s = new StringBuffer();
   208         s.append(t.kind);
   209         if (t.kind != UNBOUND) {
   210             s.append(visit(t.type, locale));
   211         }
   212         return s.toString();
   213     }
   215     @Override
   216     public String visitErrorType(ErrorType t, Locale locale) {
   217         return visitType(t, locale);
   218     }
   220     @Override
   221     public String visitTypeVar(TypeVar t, Locale locale) {
   222         return visitType(t, locale);
   223     }
   225     public String visitType(Type t, Locale locale) {
   226         String s = (t.tsym == null || t.tsym.name == null)
   227                 ? localize(locale, "compiler.misc.type.none")
   228                 : t.tsym.name.toString();
   229         return s;
   230     }
   232     /**
   233      * Converts a class name into a (possibly localized) string. Anonymous
   234      * inner classes gets converted into a localized string.
   235      *
   236      * @param t the type of the class whose name is to be rendered
   237      * @param longform if set, the class' fullname is displayed - if unset the
   238      * short name is chosen (w/o package)
   239      * @param locale the locale in which the string is to be rendered
   240      * @return localized string representation
   241      */
   242     protected String className(ClassType t, boolean longform, Locale locale) {
   243         Symbol sym = t.tsym;
   244         if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
   245             StringBuffer s = new StringBuffer(visit(t.supertype_field, locale));
   246             for (List<Type> is = t.interfaces_field; is.nonEmpty(); is = is.tail) {
   247                 s.append("&");
   248                 s.append(visit(is.head, locale));
   249             }
   250             return s.toString();
   251         } else if (sym.name.length() == 0) {
   252             String s;
   253             ClassType norm = (ClassType) t.tsym.type;
   254             if (norm == null) {
   255                 s = localize(locale, "compiler.misc.anonymous.class", (Object) null);
   256             } else if (norm.interfaces_field.nonEmpty()) {
   257                 s = localize(locale, "compiler.misc.anonymous.class",
   258                         visit(norm.interfaces_field.head, locale));
   259             } else {
   260                 s = localize(locale, "compiler.misc.anonymous.class",
   261                         visit(norm.supertype_field, locale));
   262             }
   263             return s;
   264         } else if (longform) {
   265             return sym.getQualifiedName().toString();
   266         } else {
   267             return sym.name.toString();
   268         }
   269     }
   271     /**
   272      * Converts a set of method argument types into their corresponding
   273      * localized string representation.
   274      *
   275      * @param args arguments to be rendered
   276      * @param varArgs if true, the last method argument is regarded as a vararg
   277      * @param locale the locale in which the string is to be rendered
   278      * @return localized string representation
   279      */
   280     protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
   281         if (!varArgs) {
   282             return visitTypes(args, locale);
   283         } else {
   284             StringBuffer buf = new StringBuffer();
   285             while (args.tail.nonEmpty()) {
   286                 buf.append(visit(args.head, locale));
   287                 args = args.tail;
   288                 buf.append(',');
   289             }
   290             if (args.head.tag == ARRAY) {
   291                 buf.append(visit(((ArrayType) args.head).elemtype, locale));
   292                 buf.append("...");
   293             } else {
   294                 buf.append(visit(args.head, locale));
   295             }
   296             return buf.toString();
   297         }
   298     }
   300     @Override
   301     public String visitClassSymbol(ClassSymbol sym, Locale locale) {
   302         return sym.name.isEmpty()
   303                 ? localize(locale, "compiler.misc.anonymous.class", sym.flatname)
   304                 : sym.fullname.toString();
   305     }
   307     @Override
   308     public String visitMethodSymbol(MethodSymbol s, Locale locale) {
   309         if ((s.flags() & BLOCK) != 0) {
   310             return s.owner.name.toString();
   311         } else {
   312             String ms = (s.name == s.name.table.names.init)
   313                     ? s.owner.name.toString()
   314                     : s.name.toString();
   315             if (s.type != null) {
   316                 if (s.type.tag == FORALL) {
   317                     ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
   318                 }
   319                 ms += "(" + printMethodArgs(
   320                         s.type.getParameterTypes(),
   321                         (s.flags() & VARARGS) != 0,
   322                         locale) + ")";
   323             }
   324             return ms;
   325         }
   326     }
   328     @Override
   329     public String visitOperatorSymbol(OperatorSymbol s, Locale locale) {
   330         return visitMethodSymbol(s, locale);
   331     }
   333     @Override
   334     public String visitPackageSymbol(PackageSymbol s, Locale locale) {
   335         return s.isUnnamed()
   336                 ? localize(locale, "compiler.misc.unnamed.package")
   337                 : s.fullname.toString();
   338     }
   340     @Override
   341     public String visitTypeSymbol(TypeSymbol s, Locale locale) {
   342         return visitSymbol(s, locale);
   343     }
   345     @Override
   346     public String visitVarSymbol(VarSymbol s, Locale locale) {
   347         return visitSymbol(s, locale);
   348     }
   350     @Override
   351     public String visitSymbol(Symbol s, Locale locale) {
   352         return s.name.toString();
   353     }
   354 }

mercurial