001 /* 002 * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Sun designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Sun in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 022 * CA 95054 USA or visit www.sun.com if you need additional information or 023 * have any questions. 024 */ 025 026 package com.sun.tools.javadoc; 027 028 import com.sun.javadoc.*; 029 030 import static com.sun.javadoc.LanguageVersion.*; 031 032 import com.sun.tools.javac.code.Symbol; 033 import com.sun.tools.javac.code.Symbol.ClassSymbol; 034 import com.sun.tools.javac.code.Type; 035 import com.sun.tools.javac.code.Type.ClassType; 036 import com.sun.tools.javac.code.Type.TypeVar; 037 import com.sun.tools.javac.code.Type.ArrayType; 038 import com.sun.tools.javac.code.Types; 039 import com.sun.tools.javac.util.List; 040 041 import static com.sun.tools.javac.code.TypeTags.*; 042 043 044 public class TypeMaker { 045 046 public static com.sun.javadoc.Type getType(DocEnv env, Type t) { 047 return getType(env, t, true); 048 } 049 050 /** 051 * @param errToClassDoc if true, ERROR type results in a ClassDoc; 052 * false preserves legacy behavior 053 */ 054 @SuppressWarnings("fallthrough") 055 public static com.sun.javadoc.Type getType(DocEnv env, Type t, 056 boolean errToClassDoc) { 057 if (env.legacyDoclet) { 058 t = env.types.erasure(t); 059 } 060 switch (t.tag) { 061 case CLASS: 062 if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) { 063 return env.getParameterizedType((ClassType)t); 064 } else { 065 return env.getClassDoc((ClassSymbol)t.tsym); 066 } 067 case WILDCARD: 068 Type.WildcardType a = (Type.WildcardType)t; 069 return new WildcardTypeImpl(env, a); 070 case TYPEVAR: return new TypeVariableImpl(env, (TypeVar)t); 071 case ARRAY: return new ArrayTypeImpl(env, t); 072 case BYTE: return PrimitiveType.byteType; 073 case CHAR: return PrimitiveType.charType; 074 case SHORT: return PrimitiveType.shortType; 075 case INT: return PrimitiveType.intType; 076 case LONG: return PrimitiveType.longType; 077 case FLOAT: return PrimitiveType.floatType; 078 case DOUBLE: return PrimitiveType.doubleType; 079 case BOOLEAN: return PrimitiveType.booleanType; 080 case VOID: return PrimitiveType.voidType; 081 case ERROR: 082 if (errToClassDoc) 083 return env.getClassDoc((ClassSymbol)t.tsym); 084 // FALLTHRU 085 default: 086 return new PrimitiveType(t.tsym.getQualifiedName().toString()); 087 } 088 } 089 090 /** 091 * Convert a list of javac types into an array of javadoc types. 092 */ 093 public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts) { 094 return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]); 095 } 096 097 /** 098 * Like the above version, but use and return the array given. 099 */ 100 public static com.sun.javadoc.Type[] getTypes(DocEnv env, List<Type> ts, 101 com.sun.javadoc.Type res[]) { 102 int i = 0; 103 for (Type t : ts) { 104 res[i++] = getType(env, t); 105 } 106 return res; 107 } 108 109 public static String getTypeName(Type t, boolean full) { 110 switch (t.tag) { 111 case ARRAY: 112 StringBuffer dimension = new StringBuffer(); 113 while (t.tag == ARRAY) { 114 dimension = dimension.append("[]"); 115 t = ((ArrayType)t).elemtype; 116 } 117 return getTypeName(t, full) + dimension; 118 case CLASS: 119 return ClassDocImpl.getClassName((ClassSymbol)t.tsym, full); 120 default: 121 return t.tsym.getQualifiedName().toString(); 122 } 123 } 124 125 /** 126 * Return the string representation of a type use. Bounds of type 127 * variables are not included; bounds of wildcard types are. 128 * Class names are qualified if "full" is true. 129 */ 130 static String getTypeString(DocEnv env, Type t, boolean full) { 131 switch (t.tag) { 132 case ARRAY: 133 StringBuffer dimension = new StringBuffer(); 134 while (t.tag == ARRAY) { 135 dimension = dimension.append("[]"); 136 t = env.types.elemtype(t); 137 } 138 return getTypeString(env, t, full) + dimension; 139 case CLASS: 140 return ParameterizedTypeImpl. 141 parameterizedTypeToString(env, (ClassType)t, full); 142 case WILDCARD: 143 Type.WildcardType a = (Type.WildcardType)t; 144 return WildcardTypeImpl.wildcardTypeToString(env, a, full); 145 default: 146 return t.tsym.getQualifiedName().toString(); 147 } 148 } 149 150 /** 151 * Return the formal type parameters of a class or method as an 152 * angle-bracketed string. Each parameter is a type variable with 153 * optional bounds. Class names are qualified if "full" is true. 154 * Return "" if there are no type parameters or we're hiding generics. 155 */ 156 static String typeParametersString(DocEnv env, Symbol sym, boolean full) { 157 if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) { 158 return ""; 159 } 160 StringBuffer s = new StringBuffer(); 161 for (Type t : sym.type.getTypeArguments()) { 162 s.append(s.length() == 0 ? "<" : ", "); 163 s.append(TypeVariableImpl.typeVarToString(env, (TypeVar)t, full)); 164 } 165 s.append(">"); 166 return s.toString(); 167 } 168 169 /** 170 * Return the actual type arguments of a parameterized type as an 171 * angle-bracketed string. Class name are qualified if "full" is true. 172 * Return "" if there are no type arguments or we're hiding generics. 173 */ 174 static String typeArgumentsString(DocEnv env, ClassType cl, boolean full) { 175 if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) { 176 return ""; 177 } 178 StringBuffer s = new StringBuffer(); 179 for (Type t : cl.getTypeArguments()) { 180 s.append(s.length() == 0 ? "<" : ", "); 181 s.append(getTypeString(env, t, full)); 182 } 183 s.append(">"); 184 return s.toString(); 185 } 186 187 188 private static class ArrayTypeImpl implements com.sun.javadoc.Type { 189 190 Type arrayType; 191 192 DocEnv env; 193 194 ArrayTypeImpl(DocEnv env, Type arrayType) { 195 this.env = env; 196 this.arrayType = arrayType; 197 } 198 199 private com.sun.javadoc.Type skipArraysCache = null; 200 201 private com.sun.javadoc.Type skipArrays() { 202 if (skipArraysCache == null) { 203 Type t; 204 for (t = arrayType; t.tag == ARRAY; t = env.types.elemtype(t)) { } 205 skipArraysCache = TypeMaker.getType(env, t); 206 } 207 return skipArraysCache; 208 } 209 210 /** 211 * Return the type's dimension information, as a string. 212 * <p> 213 * For example, a two dimensional array of String returns '[][]'. 214 */ 215 public String dimension() { 216 StringBuffer dimension = new StringBuffer(); 217 for (Type t = arrayType; t.tag == ARRAY; t = env.types.elemtype(t)) { 218 dimension = dimension.append("[]"); 219 } 220 return dimension.toString(); 221 } 222 223 /** 224 * Return unqualified name of type excluding any dimension information. 225 * <p> 226 * For example, a two dimensional array of String returns 'String'. 227 */ 228 public String typeName() { 229 return skipArrays().typeName(); 230 } 231 232 /** 233 * Return qualified name of type excluding any dimension information. 234 *<p> 235 * For example, a two dimensional array of String 236 * returns 'java.lang.String'. 237 */ 238 public String qualifiedTypeName() { 239 return skipArrays().qualifiedTypeName(); 240 } 241 242 /** 243 * Return the simple name of this type excluding any dimension information. 244 */ 245 public String simpleTypeName() { 246 return skipArrays().simpleTypeName(); 247 } 248 249 /** 250 * Return this type as a class. Array dimensions are ignored. 251 * 252 * @return a ClassDocImpl if the type is a Class. 253 * Return null if it is a primitive type.. 254 */ 255 public ClassDoc asClassDoc() { 256 return skipArrays().asClassDoc(); 257 } 258 259 /** 260 * Return this type as a <code>ParameterizedType</code> if it 261 * represents a parameterized type. Array dimensions are ignored. 262 */ 263 public ParameterizedType asParameterizedType() { 264 return skipArrays().asParameterizedType(); 265 } 266 267 /** 268 * Return this type as a <code>TypeVariable</code> if it represents 269 * a type variable. Array dimensions are ignored. 270 */ 271 public TypeVariable asTypeVariable() { 272 return skipArrays().asTypeVariable(); 273 } 274 275 /** 276 * Return null, as there are no arrays of wildcard types. 277 */ 278 public WildcardType asWildcardType() { 279 return null; 280 } 281 282 /** 283 * Return this type as an <code>AnnotationTypeDoc</code> if it 284 * represents an annotation type. Array dimensions are ignored. 285 */ 286 public AnnotationTypeDoc asAnnotationTypeDoc() { 287 return skipArrays().asAnnotationTypeDoc(); 288 } 289 290 /** 291 * Return true if this is an array of a primitive type. 292 */ 293 public boolean isPrimitive() { 294 return skipArrays().isPrimitive(); 295 } 296 297 /** 298 * Return a string representation of the type. 299 * 300 * Return name of type including any dimension information. 301 * <p> 302 * For example, a two dimensional array of String returns 303 * <code>String[][]</code>. 304 * 305 * @return name of type including any dimension information. 306 */ 307 public String toString() { 308 return qualifiedTypeName() + dimension(); 309 } 310 } 311 }