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