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