Thu, 18 Apr 2013 20:00:14 -0700
8012656: cache frequently used name strings for DocImpl classes
Reviewed-by: darcy
1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javadoc;
28 import javax.lang.model.type.TypeKind;
30 import com.sun.javadoc.*;
31 import com.sun.tools.javac.code.Symbol;
32 import com.sun.tools.javac.code.Symbol.ClassSymbol;
33 import com.sun.tools.javac.code.Type;
34 import com.sun.tools.javac.code.Type.ArrayType;
35 import com.sun.tools.javac.code.Type.ClassType;
36 import com.sun.tools.javac.code.Type.TypeVar;
37 import com.sun.tools.javac.util.List;
38 import static com.sun.tools.javac.code.TypeTag.ARRAY;
40 /**
41 * <p><b>This is NOT part of any supported API.
42 * If you write code that depends on this, you do so at your own risk.
43 * This code and its internal interfaces are subject to change or
44 * deletion without notice.</b>
45 */
46 public class TypeMaker {
48 public static com.sun.javadoc.Type getType(DocEnv env, Type t) {
49 return getType(env, t, true);
50 }
52 /**
53 * @param errToClassDoc if true, ERROR type results in a ClassDoc;
54 * false preserves legacy behavior
55 */
56 public static com.sun.javadoc.Type getType(DocEnv env, Type t,
57 boolean errorToClassDoc) {
58 return getType(env, t, errorToClassDoc, true);
59 }
61 @SuppressWarnings("fallthrough")
62 public static com.sun.javadoc.Type getType(DocEnv env, Type t,
63 boolean errToClassDoc, boolean considerAnnotations) {
64 if (env.legacyDoclet) {
65 t = env.types.erasure(t);
66 }
67 if (considerAnnotations
68 && t.isAnnotated()) {
69 return new AnnotatedTypeImpl(env, (com.sun.tools.javac.code.Type.AnnotatedType) t);
70 }
72 if (t.isAnnotated()) {
73 Type.AnnotatedType at = (Type.AnnotatedType) t;
74 return new AnnotatedTypeImpl(env, at);
75 }
77 switch (t.getTag()) {
78 case CLASS:
79 if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) {
80 return env.getParameterizedType((ClassType)t);
81 } else {
82 return env.getClassDoc((ClassSymbol)t.tsym);
83 }
84 case WILDCARD:
85 Type.WildcardType a = (Type.WildcardType)t;
86 return new WildcardTypeImpl(env, a);
87 case TYPEVAR: return new TypeVariableImpl(env, (TypeVar)t);
88 case ARRAY: return new ArrayTypeImpl(env, t);
89 case BYTE: return PrimitiveType.byteType;
90 case CHAR: return PrimitiveType.charType;
91 case SHORT: return PrimitiveType.shortType;
92 case INT: return PrimitiveType.intType;
93 case LONG: return PrimitiveType.longType;
94 case FLOAT: return PrimitiveType.floatType;
95 case DOUBLE: return PrimitiveType.doubleType;
96 case BOOLEAN: return PrimitiveType.booleanType;
97 case VOID: return PrimitiveType.voidType;
98 case ERROR:
99 if (errToClassDoc)
100 return env.getClassDoc((ClassSymbol)t.tsym);
101 // FALLTHRU
102 default:
103 return new PrimitiveType(t.tsym.getQualifiedName().toString());
104 }
105 }
107 /**
108 * Convert a list of javac types into an array of javadoc types.
109 */
110 public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts) {
111 return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]);
112 }
114 /**
115 * Like the above version, but use and return the array given.
116 */
117 public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts,
118 com.sun.javadoc.Type res[]) {
119 int i = 0;
120 for (Type t : ts) {
121 res[i++] = getType(env, t);
122 }
123 return res;
124 }
126 public static String getTypeName(Type t, boolean full) {
127 switch (t.getTag()) {
128 case ARRAY:
129 StringBuilder s = new StringBuilder();
130 while (t.hasTag(ARRAY)) {
131 s.append("[]");
132 t = ((ArrayType)t).elemtype;
133 }
134 s.insert(0, getTypeName(t, full));
135 return s.toString();
136 case CLASS:
137 return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full);
138 default:
139 return t.tsym.getQualifiedName().toString();
140 }
141 }
143 /**
144 * Return the string representation of a type use. Bounds of type
145 * variables are not included; bounds of wildcard types are.
146 * Class names are qualified if "full" is true.
147 */
148 static String getTypeString(DocEnv env, Type t, boolean full) {
149 // TODO: should annotations be included here?
150 if (t.isAnnotated()) {
151 Type.AnnotatedType at = (Type.AnnotatedType)t;
152 t = at.underlyingType;
153 }
154 switch (t.getTag()) {
155 case ARRAY:
156 StringBuilder s = new StringBuilder();
157 while (t.hasTag(ARRAY)) {
158 s.append("[]");
159 t = env.types.elemtype(t);
160 }
161 s.insert(0, getTypeString(env, t, full));
162 return s.toString();
163 case CLASS:
164 return ParameterizedTypeImpl.
165 parameterizedTypeToString(env, (ClassType)t, full);
166 case WILDCARD:
167 Type.WildcardType a = (Type.WildcardType)t;
168 return WildcardTypeImpl.wildcardTypeToString(env, a, full);
169 default:
170 return t.tsym.getQualifiedName().toString();
171 }
172 }
174 /**
175 * Return the formal type parameters of a class or method as an
176 * angle-bracketed string. Each parameter is a type variable with
177 * optional bounds. Class names are qualified if "full" is true.
178 * Return "" if there are no type parameters or we're hiding generics.
179 */
180 static String typeParametersString(DocEnv env, Symbol sym, boolean full) {
181 if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
182 return "";
183 }
184 StringBuilder s = new StringBuilder();
185 for (Type t : sym.type.getTypeArguments()) {
186 s.append(s.length() == 0 ? "<" : ", ");
187 s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full));
188 }
189 s.append(">");
190 return s.toString();
191 }
193 /**
194 * Return the actual type arguments of a parameterized type as an
195 * angle-bracketed string. Class name are qualified if "full" is true.
196 * Return "" if there are no type arguments or we're hiding generics.
197 */
198 static String typeArgumentsString(DocEnv env, ClassType cl, boolean full) {
199 if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) {
200 return "";
201 }
202 StringBuilder s = new StringBuilder();
203 for (Type t : cl.getTypeArguments()) {
204 s.append(s.length() == 0 ? "<" : ", ");
205 s.append(getTypeString(env, t, full));
206 }
207 s.append(">");
208 return s.toString();
209 }
212 private static class ArrayTypeImpl implements com.sun.javadoc.Type {
214 Type arrayType;
216 DocEnv env;
218 ArrayTypeImpl(DocEnv env, Type arrayType) {
219 this.env = env;
220 this.arrayType = arrayType;
221 }
223 private com.sun.javadoc.Type skipArraysCache = null;
225 public com.sun.javadoc.Type getElementType() {
226 return TypeMaker.getType(env, env.types.elemtype(arrayType));
227 }
229 private com.sun.javadoc.Type skipArrays() {
230 if (skipArraysCache == null) {
231 Type t;
232 for (t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) { }
233 skipArraysCache = TypeMaker.getType(env, t);
234 }
235 return skipArraysCache;
236 }
238 /**
239 * Return the type's dimension information, as a string.
240 * <p>
241 * For example, a two dimensional array of String returns '[][]'.
242 */
243 public String dimension() {
244 StringBuilder dimension = new StringBuilder();
245 for (Type t = arrayType; t.hasTag(ARRAY); t = env.types.elemtype(t)) {
246 dimension.append("[]");
247 }
248 return dimension.toString();
249 }
251 /**
252 * Return unqualified name of type excluding any dimension information.
253 * <p>
254 * For example, a two dimensional array of String returns 'String'.
255 */
256 public String typeName() {
257 return skipArrays().typeName();
258 }
260 /**
261 * Return qualified name of type excluding any dimension information.
262 *<p>
263 * For example, a two dimensional array of String
264 * returns 'java.lang.String'.
265 */
266 public String qualifiedTypeName() {
267 return skipArrays().qualifiedTypeName();
268 }
270 /**
271 * Return the simple name of this type excluding any dimension information.
272 */
273 public String simpleTypeName() {
274 return skipArrays().simpleTypeName();
275 }
277 /**
278 * Return this type as a class. Array dimensions are ignored.
279 *
280 * @return a ClassDocImpl if the type is a Class.
281 * Return null if it is a primitive type..
282 */
283 public ClassDoc asClassDoc() {
284 return skipArrays().asClassDoc();
285 }
287 /**
288 * Return this type as a <code>ParameterizedType</code> if it
289 * represents a parameterized type. Array dimensions are ignored.
290 */
291 public ParameterizedType asParameterizedType() {
292 return skipArrays().asParameterizedType();
293 }
295 /**
296 * Return this type as a <code>TypeVariable</code> if it represents
297 * a type variable. Array dimensions are ignored.
298 */
299 public TypeVariable asTypeVariable() {
300 return skipArrays().asTypeVariable();
301 }
303 /**
304 * Return null, as there are no arrays of wildcard types.
305 */
306 public WildcardType asWildcardType() {
307 return null;
308 }
310 /**
311 * Return null, as there are no annotations of the type
312 */
313 public AnnotatedType asAnnotatedType() {
314 return null;
315 }
317 /**
318 * Return this type as an <code>AnnotationTypeDoc</code> if it
319 * represents an annotation type. Array dimensions are ignored.
320 */
321 public AnnotationTypeDoc asAnnotationTypeDoc() {
322 return skipArrays().asAnnotationTypeDoc();
323 }
325 /**
326 * Return true if this is an array of a primitive type.
327 */
328 public boolean isPrimitive() {
329 return skipArrays().isPrimitive();
330 }
332 /**
333 * Return a string representation of the type.
334 *
335 * Return name of type including any dimension information.
336 * <p>
337 * For example, a two dimensional array of String returns
338 * <code>String[][]</code>.
339 *
340 * @return name of type including any dimension information.
341 */
342 @Override
343 public String toString() {
344 return qualifiedTypeName() + dimension();
345 }
346 }
347 }