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: public class TypeMaker {
044:
045: public static com.sun.javadoc.Type getType(DocEnv env, Type t) {
046: return getType(env, t, true);
047: }
048:
049: /**
050: * @param errToClassDoc if true, ERROR type results in a ClassDoc;
051: * false preserves legacy behavior
052: */
053: public static com.sun.javadoc.Type getType(DocEnv env, Type t,
054: boolean errToClassDoc) {
055: if (env.legacyDoclet) {
056: t = env.types.erasure(t);
057: }
058: switch (t.tag) {
059: case CLASS:
060: if (ClassDocImpl.isGeneric((ClassSymbol) t.tsym)) {
061: return env.getParameterizedType((ClassType) t);
062: } else {
063: return env.getClassDoc((ClassSymbol) t.tsym);
064: }
065: case WILDCARD:
066: Type.WildcardType a = (Type.WildcardType) t;
067: return new WildcardTypeImpl(env, a);
068: case TYPEVAR:
069: return new TypeVariableImpl(env, (TypeVar) t);
070: case ARRAY:
071: return new ArrayTypeImpl(env, t);
072: case BYTE:
073: return PrimitiveType.byteType;
074: case CHAR:
075: return PrimitiveType.charType;
076: case SHORT:
077: return PrimitiveType.shortType;
078: case INT:
079: return PrimitiveType.intType;
080: case LONG:
081: return PrimitiveType.longType;
082: case FLOAT:
083: return PrimitiveType.floatType;
084: case DOUBLE:
085: return PrimitiveType.doubleType;
086: case BOOLEAN:
087: return PrimitiveType.booleanType;
088: case VOID:
089: return PrimitiveType.voidType;
090: case ERROR:
091: if (errToClassDoc)
092: return env.getClassDoc((ClassSymbol) t.tsym);
093: // FALLTHRU
094: default:
095: return new PrimitiveType(t.tsym.getQualifiedName()
096: .toString());
097: }
098: }
099:
100: /**
101: * Convert a list of javac types into an array of javadoc types.
102: */
103: public static com.sun.javadoc.Type[] getTypes(DocEnv env,
104: List<Type> ts) {
105: return getTypes(env, ts, new com.sun.javadoc.Type[ts.length()]);
106: }
107:
108: /**
109: * Like the above version, but use and return the array given.
110: */
111: public static com.sun.javadoc.Type[] getTypes(DocEnv env,
112: List<Type> ts, com.sun.javadoc.Type res[]) {
113: int i = 0;
114: for (Type t : ts) {
115: res[i++] = getType(env, t);
116: }
117: return res;
118: }
119:
120: public static String getTypeName(Type t, boolean full) {
121: switch (t.tag) {
122: case ARRAY:
123: StringBuffer dimension = new StringBuffer();
124: while (t.tag == ARRAY) {
125: dimension = dimension.append("[]");
126: t = ((ArrayType) t).elemtype;
127: }
128: return getTypeName(t, full) + dimension;
129: case CLASS:
130: return ClassDocImpl
131: .getClassName((ClassSymbol) t.tsym, full);
132: default:
133: return t.tsym.getQualifiedName().toString();
134: }
135: }
136:
137: /**
138: * Return the string representation of a type use. Bounds of type
139: * variables are not included; bounds of wildcard types are.
140: * Class names are qualified if "full" is true.
141: */
142: static String getTypeString(DocEnv env, Type t, boolean full) {
143: switch (t.tag) {
144: case ARRAY:
145: StringBuffer dimension = new StringBuffer();
146: while (t.tag == ARRAY) {
147: dimension = dimension.append("[]");
148: t = env.types.elemtype(t);
149: }
150: return getTypeString(env, t, full) + dimension;
151: case CLASS:
152: return ParameterizedTypeImpl.parameterizedTypeToString(env,
153: (ClassType) t, full);
154: case WILDCARD:
155: Type.WildcardType a = (Type.WildcardType) t;
156: return WildcardTypeImpl.wildcardTypeToString(env, a, full);
157: default:
158: return t.tsym.getQualifiedName().toString();
159: }
160: }
161:
162: /**
163: * Return the formal type parameters of a class or method as an
164: * angle-bracketed string. Each parameter is a type variable with
165: * optional bounds. Class names are qualified if "full" is true.
166: * Return "" if there are no type parameters or we're hiding generics.
167: */
168: static String typeParametersString(DocEnv env, Symbol sym,
169: boolean full) {
170: if (env.legacyDoclet || sym.type.getTypeArguments().isEmpty()) {
171: return "";
172: }
173: StringBuffer s = new StringBuffer();
174: for (Type t : sym.type.getTypeArguments()) {
175: s.append(s.length() == 0 ? "<" : ", ");
176: s.append(TypeVariableImpl.typeVarToString(env, (TypeVar) t,
177: full));
178: }
179: s.append(">");
180: return s.toString();
181: }
182:
183: /**
184: * Return the actual type arguments of a parameterized type as an
185: * angle-bracketed string. Class name are qualified if "full" is true.
186: * Return "" if there are no type arguments or we're hiding generics.
187: */
188: static String typeArgumentsString(DocEnv env, ClassType cl,
189: boolean full) {
190: if (env.legacyDoclet || cl.getTypeArguments().isEmpty()) {
191: return "";
192: }
193: StringBuffer s = new StringBuffer();
194: for (Type t : cl.getTypeArguments()) {
195: s.append(s.length() == 0 ? "<" : ", ");
196: s.append(getTypeString(env, t, full));
197: }
198: s.append(">");
199: return s.toString();
200: }
201:
202: private static class ArrayTypeImpl implements com.sun.javadoc.Type {
203:
204: Type arrayType;
205:
206: DocEnv env;
207:
208: ArrayTypeImpl(DocEnv env, Type arrayType) {
209: this .env = env;
210: this .arrayType = arrayType;
211: }
212:
213: private com.sun.javadoc.Type skipArraysCache = null;
214:
215: private com.sun.javadoc.Type skipArrays() {
216: if (skipArraysCache == null) {
217: Type t;
218: for (t = arrayType; t.tag == ARRAY; t = env.types
219: .elemtype(t)) {
220: }
221: skipArraysCache = TypeMaker.getType(env, t);
222: }
223: return skipArraysCache;
224: }
225:
226: /**
227: * Return the type's dimension information, as a string.
228: * <p>
229: * For example, a two dimensional array of String returns '[][]'.
230: */
231: public String dimension() {
232: StringBuffer dimension = new StringBuffer();
233: for (Type t = arrayType; t.tag == ARRAY; t = env.types
234: .elemtype(t)) {
235: dimension = dimension.append("[]");
236: }
237: return dimension.toString();
238: }
239:
240: /**
241: * Return unqualified name of type excluding any dimension information.
242: * <p>
243: * For example, a two dimensional array of String returns 'String'.
244: */
245: public String typeName() {
246: return skipArrays().typeName();
247: }
248:
249: /**
250: * Return qualified name of type excluding any dimension information.
251: *<p>
252: * For example, a two dimensional array of String
253: * returns 'java.lang.String'.
254: */
255: public String qualifiedTypeName() {
256: return skipArrays().qualifiedTypeName();
257: }
258:
259: /**
260: * Return the simple name of this type excluding any dimension information.
261: */
262: public String simpleTypeName() {
263: return skipArrays().simpleTypeName();
264: }
265:
266: /**
267: * Return this type as a class. Array dimensions are ignored.
268: *
269: * @return a ClassDocImpl if the type is a Class.
270: * Return null if it is a primitive type..
271: */
272: public ClassDoc asClassDoc() {
273: return skipArrays().asClassDoc();
274: }
275:
276: /**
277: * Return this type as a <code>ParameterizedType</code> if it
278: * represents a parameterized type. Array dimensions are ignored.
279: */
280: public ParameterizedType asParameterizedType() {
281: return skipArrays().asParameterizedType();
282: }
283:
284: /**
285: * Return this type as a <code>TypeVariable</code> if it represents
286: * a type variable. Array dimensions are ignored.
287: */
288: public TypeVariable asTypeVariable() {
289: return skipArrays().asTypeVariable();
290: }
291:
292: /**
293: * Return null, as there are no arrays of wildcard types.
294: */
295: public WildcardType asWildcardType() {
296: return null;
297: }
298:
299: /**
300: * Return this type as an <code>AnnotationTypeDoc</code> if it
301: * represents an annotation type. Array dimensions are ignored.
302: */
303: public AnnotationTypeDoc asAnnotationTypeDoc() {
304: return skipArrays().asAnnotationTypeDoc();
305: }
306:
307: /**
308: * Return true if this is an array of a primitive type.
309: */
310: public boolean isPrimitive() {
311: return skipArrays().isPrimitive();
312: }
313:
314: /**
315: * Return a string representation of the type.
316: *
317: * Return name of type including any dimension information.
318: * <p>
319: * For example, a two dimensional array of String returns
320: * <code>String[][]</code>.
321: *
322: * @return name of type including any dimension information.
323: */
324: public String toString() {
325: return qualifiedTypeName() + dimension();
326: }
327: }
328: }
|