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

changeset 238
86b60aa941c6
child 288
d402db1005ad
equal deleted inserted replaced
237:9711a6c2db7e 238:86b60aa941c6
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 */
25
26 package com.sun.tools.javac.code;
27
28 import java.util.Locale;
29
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;
35
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.*;
39
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> {
45
46 /**
47 * This method should be overriden in order to provide proper i18n support.
48 *
49 * @param locale the locale in which the string is to be rendered
50 * @param key the key corresponding to the message to be displayed
51 * @param args a list of optional arguments
52 * @return localized string representation
53 */
54 protected abstract String localize(Locale locale, String key, Object... args);
55
56 /**
57 * Create a printer with default i18n support provided my Messages.
58 * @param messages Messages class to be used for i18n
59 * @return printer visitor instance
60 */
61 public static Printer createStandardPrinter(final Messages messages) {
62 return new Printer() {
63 @Override
64 protected String localize(Locale locale, String key, Object... args) {
65 return messages.getLocalizedString(locale, key, args);
66 }};
67 }
68
69 /**
70 * Get a localized string representation for all the types in the input list.
71 *
72 * @param ts types to be displayed
73 * @param locale the locale in which the string is to be rendered
74 * @return localized string representation
75 */
76 public String visitTypes(List<Type> ts, Locale locale) {
77 ListBuffer<String> sbuf = ListBuffer.lb();
78 for (Type t : ts) {
79 sbuf.append(visit(t, locale));
80 }
81 return sbuf.toList().toString();
82 }
83
84 /**
85 * * Get a localized string represenation for all the symbols in the input list.
86 *
87 * @param ts symbols to be displayed
88 * @param locale the locale in which the string is to be rendered
89 * @return localized string representation
90 */
91 public String visitSymbols(List<Symbol> ts, Locale locale) {
92 ListBuffer<String> sbuf = ListBuffer.lb();
93 for (Symbol t : ts) {
94 sbuf.append(visit(t, locale));
95 }
96 return sbuf.toList().toString();
97 }
98
99 /**
100 * Get a localized string represenation for a given type.
101 *
102 * @param ts type to be displayed
103 * @param locale the locale in which the string is to be rendered
104 * @return localized string representation
105 */
106 public String visit(Type t, Locale locale) {
107 return t.accept(this, locale);
108 }
109
110 /**
111 * Get a localized string represenation for a given symbol.
112 *
113 * @param ts symbol to be displayed
114 * @param locale the locale in which the string is to be rendered
115 * @return localized string representation
116 */
117 public String visit(Symbol s, Locale locale) {
118 return s.accept(this, locale);
119 }
120
121 @Override
122 public String visitCapturedType(CapturedType t, Locale locale) {
123 return localize(locale, "compiler.misc.type.captureof",
124 (t.hashCode() & 0xFFFFFFFFL) % Type.CapturedType.PRIME,
125 visit(t.wildcard, locale));
126 }
127
128 @Override
129 public String visitForAll(ForAll t, Locale locale) {
130 return "<" + visitTypes(t.tvars, locale) + ">" + visit(t.qtype, locale);
131 }
132
133 @Override
134 public String visitUndetVar(UndetVar t, Locale locale) {
135 if (t.inst != null) {
136 return visit(t.inst, locale);
137 } else {
138 return visit(t.qtype, locale) + "?";
139 }
140 }
141
142 @Override
143 public String visitArrayType(ArrayType t, Locale locale) {
144 return visit(t.elemtype, locale) + "[]";
145 }
146
147 @Override
148 public String visitClassType(ClassType t, Locale locale) {
149 StringBuffer buf = new StringBuffer();
150 if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
151 buf.append(visit(t.getEnclosingType(), locale));
152 buf.append(".");
153 buf.append(className(t, false, locale));
154 } else {
155 buf.append(className(t, true, locale));
156 }
157 if (t.getTypeArguments().nonEmpty()) {
158 buf.append('<');
159 buf.append(visitTypes(t.getTypeArguments(), locale));
160 buf.append(">");
161 }
162 return buf.toString();
163 }
164
165 @Override
166 public String visitMethodType(MethodType t, Locale locale) {
167 return "(" + printMethodArgs(t.argtypes, false, locale) + ")" + visit(t.restype, locale);
168 }
169
170 @Override
171 public String visitPackageType(PackageType t, Locale locale) {
172 return t.tsym.getQualifiedName().toString();
173 }
174
175 @Override
176 public String visitWildcardType(WildcardType t, Locale locale) {
177 StringBuffer s = new StringBuffer();
178 s.append(t.kind);
179 if (t.kind != UNBOUND) {
180 s.append(visit(t.type, locale));
181 }
182 return s.toString();
183 }
184
185 @Override
186 public String visitErrorType(ErrorType t, Locale locale) {
187 return visitType(t, locale);
188 }
189
190 @Override
191 public String visitTypeVar(TypeVar t, Locale locale) {
192 return visitType(t, locale);
193 }
194
195 public String visitType(Type t, Locale locale) {
196 String s = (t.tsym == null || t.tsym.name == null)
197 ? localize(locale, "compiler.misc.type.none")
198 : t.tsym.name.toString();
199 return s;
200 }
201
202 /**
203 * Converts a class name into a (possibly localized) string. Anonymous
204 * inner classes gets converted into a localized string.
205 *
206 * @param t the type of the class whose name is to be rendered
207 * @param longform if set, the class' fullname is displayed - if unset the
208 * short name is chosen (w/o package)
209 * @param locale the locale in which the string is to be rendered
210 * @return localized string representation
211 */
212 protected String className(ClassType t, boolean longform, Locale locale) {
213 Symbol sym = t.tsym;
214 if (sym.name.length() == 0 && (sym.flags() & COMPOUND) != 0) {
215 StringBuffer s = new StringBuffer(visit(t.supertype_field, locale));
216 for (List<Type> is = t.interfaces_field; is.nonEmpty(); is = is.tail) {
217 s.append("&");
218 s.append(visit(is.head, locale));
219 }
220 return s.toString();
221 } else if (sym.name.length() == 0) {
222 String s;
223 ClassType norm = (ClassType) t.tsym.type;
224 if (norm == null) {
225 s = localize(locale, "compiler.misc.anonymous.class", (Object) null);
226 } else if (norm.interfaces_field.nonEmpty()) {
227 s = localize(locale, "compiler.misc.anonymous.class",
228 visit(norm.interfaces_field.head, locale));
229 } else {
230 s = localize(locale, "compiler.misc.anonymous.class",
231 visit(norm.supertype_field, locale));
232 }
233 return s;
234 } else if (longform) {
235 return sym.getQualifiedName().toString();
236 } else {
237 return sym.name.toString();
238 }
239 }
240
241 /**
242 * Converts a set of method argument types into their corresponding
243 * localized string representation.
244 *
245 * @param args arguments to be rendered
246 * @param varArgs if true, the last method argument is regarded as a vararg
247 * @param locale the locale in which the string is to be rendered
248 * @return localized string representation
249 */
250 protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
251 if (!varArgs) {
252 return visitTypes(args, locale);
253 } else {
254 StringBuffer buf = new StringBuffer();
255 while (args.tail.nonEmpty()) {
256 buf.append(visit(args.head, locale));
257 args = args.tail;
258 buf.append(',');
259 }
260 if (args.head.tag == ARRAY) {
261 buf.append(visit(((ArrayType) args.head).elemtype, locale));
262 buf.append("...");
263 } else {
264 buf.append(visit(args.head, locale));
265 }
266 return buf.toString();
267 }
268 }
269
270 @Override
271 public String visitClassSymbol(ClassSymbol sym, Locale locale) {
272 return sym.name.isEmpty()
273 ? localize(locale, "compiler.misc.anonymous.class", sym.flatname)
274 : sym.fullname.toString();
275 }
276
277 @Override
278 public String visitMethodSymbol(MethodSymbol s, Locale locale) {
279 if ((s.flags() & BLOCK) != 0) {
280 return s.owner.name.toString();
281 } else {
282 String ms = (s.name == s.name.table.names.init)
283 ? s.owner.name.toString()
284 : s.name.toString();
285 if (s.type != null) {
286 if (s.type.tag == FORALL) {
287 ms = "<" + visitTypes(s.type.getTypeArguments(), locale) + ">" + ms;
288 }
289 ms += "(" + printMethodArgs(
290 s.type.getParameterTypes(),
291 (s.flags() & VARARGS) != 0,
292 locale) + ")";
293 }
294 return ms;
295 }
296 }
297
298 @Override
299 public String visitOperatorSymbol(OperatorSymbol s, Locale locale) {
300 return visitMethodSymbol(s, locale);
301 }
302
303 @Override
304 public String visitPackageSymbol(PackageSymbol s, Locale locale) {
305 return s.isUnnamed()
306 ? localize(locale, "compiler.misc.unnamed.package")
307 : s.fullname.toString();
308 }
309
310 @Override
311 public String visitTypeSymbol(TypeSymbol s, Locale locale) {
312 return visitSymbol(s, locale);
313 }
314
315 @Override
316 public String visitVarSymbol(VarSymbol s, Locale locale) {
317 return visitSymbol(s, locale);
318 }
319
320 @Override
321 public String visitSymbol(Symbol s, Locale locale) {
322 return s.name.toString();
323 }
324 }

mercurial