src/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java

Mon, 15 Oct 2012 17:07:55 -0700

author
jjg
date
Mon, 15 Oct 2012 17:07:55 -0700
changeset 1364
8db45b13526e
parent 1359
25e14ad23cef
child 1985
0e6577980181
permissions
-rw-r--r--

8000666: javadoc should write directly to Writer instead of composing strings
Reviewed-by: bpatel

     1 /*
     2  * Copyright (c) 1998, 2012, 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.doclets.internal.toolkit.util;
    28 import java.util.*;
    30 import com.sun.javadoc.*;
    32 /**
    33  * Map all class uses for a given class.
    34  *
    35  *  <p><b>This is NOT part of any supported API.
    36  *  If you write code that depends on this, you do so at your own risk.
    37  *  This code and its internal interfaces are subject to change or
    38  *  deletion without notice.</b>
    39  *
    40  * @since 1.2
    41  * @author Robert G. Field
    42  */
    43 public class ClassUseMapper {
    45     private final ClassTree classtree;
    47     /**
    48      * Mapping of ClassDocs to set of PackageDoc used by that class.
    49      * Entries may be null.
    50      */
    51     public Map<String,Set<PackageDoc>> classToPackage = new HashMap<String,Set<PackageDoc>>();
    53     /**
    54      * Mapping of Annotations to set of PackageDoc that use the annotation.
    55      */
    56     public Map<String,List<PackageDoc>> classToPackageAnnotations = new HashMap<String,List<PackageDoc>>();
    58     /**
    59      * Mapping of ClassDocs to set of ClassDoc used by that class.
    60      * Entries may be null.
    61      */
    62     public Map<String,Set<ClassDoc>> classToClass = new HashMap<String,Set<ClassDoc>>();
    64     /**
    65      * Mapping of ClassDocs to list of ClassDoc which are direct or
    66      * indirect subclasses of that class.
    67      * Entries may be null.
    68      */
    69     public Map<String,List<ClassDoc>> classToSubclass = new HashMap<String,List<ClassDoc>>();
    71     /**
    72      * Mapping of ClassDocs to list of ClassDoc which are direct or
    73      * indirect subinterfaces of that interface.
    74      * Entries may be null.
    75      */
    76     public Map<String,List<ClassDoc>> classToSubinterface = new HashMap<String,List<ClassDoc>>();
    78     /**
    79      * Mapping of ClassDocs to list of ClassDoc which implement
    80      * this interface.
    81      * Entries may be null.
    82      */
    83     public Map<String,List<ClassDoc>> classToImplementingClass = new HashMap<String,List<ClassDoc>>();
    85     /**
    86      * Mapping of ClassDocs to list of FieldDoc declared as that class.
    87      * Entries may be null.
    88      */
    89     public Map<String,List<FieldDoc>> classToField = new HashMap<String,List<FieldDoc>>();
    91     /**
    92      * Mapping of ClassDocs to list of MethodDoc returning that class.
    93      * Entries may be null.
    94      */
    95     public Map<String,List<MethodDoc>> classToMethodReturn = new HashMap<String,List<MethodDoc>>();
    97     /**
    98      * Mapping of ClassDocs to list of MethodDoc having that class
    99      * as an arg.
   100      * Entries may be null.
   101      */
   102     public Map<String,List<ExecutableMemberDoc>> classToMethodArgs = new HashMap<String,List<ExecutableMemberDoc>>();
   104     /**
   105      * Mapping of ClassDocs to list of MethodDoc which throws that class.
   106      * Entries may be null.
   107      */
   108     public Map<String,List<ExecutableMemberDoc>> classToMethodThrows = new HashMap<String,List<ExecutableMemberDoc>>();
   110     /**
   111      * Mapping of ClassDocs to list of ConstructorDoc having that class
   112      * as an arg.
   113      * Entries may be null.
   114      */
   115     public Map<String,List<ExecutableMemberDoc>> classToConstructorArgs = new HashMap<String,List<ExecutableMemberDoc>>();
   117     /**
   118      * Mapping of ClassDocs to list of ConstructorDoc which throws that class.
   119      * Entries may be null.
   120      */
   121     public Map<String,List<ExecutableMemberDoc>> classToConstructorThrows = new HashMap<String,List<ExecutableMemberDoc>>();
   123     /**
   124      * The mapping of AnnotationTypeDocs to constructors that use them.
   125      */
   126     public Map<String,List<ConstructorDoc>> classToConstructorAnnotations = new HashMap<String,List<ConstructorDoc>>();
   128     /**
   129      * The mapping of AnnotationTypeDocs to Constructor parameters that use them.
   130      */
   131     public Map<String,List<ExecutableMemberDoc>> classToConstructorParamAnnotation = new HashMap<String,List<ExecutableMemberDoc>>();
   133     /**
   134      * The mapping of ClassDocs to Constructor arguments that use them as type parameters.
   135      */
   136     public Map<String,List<ExecutableMemberDoc>> classToConstructorDocArgTypeParam = new HashMap<String,List<ExecutableMemberDoc>>();
   138     /**
   139      * The mapping of ClassDocs to ClassDocs that use them as type parameters.
   140      */
   141     public Map<String,List<ClassDoc>> classToClassTypeParam = new HashMap<String,List<ClassDoc>>();
   143     /**
   144      * The mapping of AnnotationTypeDocs to ClassDocs that use them.
   145      */
   146     public Map<String,List<ClassDoc>> classToClassAnnotations = new HashMap<String,List<ClassDoc>>();
   148     /**
   149      * The mapping of ClassDocs to ExecutableMemberDocs that use them as type parameters.
   150      */
   151     public Map<String,List<MethodDoc>> classToExecMemberDocTypeParam = new HashMap<String,List<MethodDoc>>();
   153     /**
   154      * The mapping of ClassDocs to ExecutableMemberDocs arguments that use them as type parameters.
   155      */
   156     public Map<String,List<ExecutableMemberDoc>> classToExecMemberDocArgTypeParam = new HashMap<String,List<ExecutableMemberDoc>>();
   158     /**
   159      * The mapping of AnnotationTypeDocs to ExecutableMemberDocs that use them.
   160      */
   161     public Map<String,List<MethodDoc>> classToExecMemberDocAnnotations = new HashMap<String,List<MethodDoc>>();
   163     /**
   164      * The mapping of ClassDocs to ExecutableMemberDocs that have return type
   165      * with type parameters of that class.
   166      */
   167     public Map<String,List<MethodDoc>> classToExecMemberDocReturnTypeParam = new HashMap<String,List<MethodDoc>>();
   169     /**
   170      * The mapping of AnnotationTypeDocs to MethodDoc parameters that use them.
   171      */
   172     public Map<String,List<ExecutableMemberDoc>> classToExecMemberDocParamAnnotation = new HashMap<String,List<ExecutableMemberDoc>>();
   174     /**
   175      * The mapping of ClassDocs to FieldDocs that use them as type parameters.
   176      */
   177     public Map<String,List<FieldDoc>> classToFieldDocTypeParam = new HashMap<String,List<FieldDoc>>();
   179     /**
   180      * The mapping of AnnotationTypeDocs to FieldDocs that use them.
   181      */
   182     public Map<String,List<FieldDoc>> annotationToFieldDoc = new HashMap<String,List<FieldDoc>>();
   185     public ClassUseMapper(RootDoc root, ClassTree classtree) {
   186         this.classtree = classtree;
   188         // Map subclassing, subinterfacing implementing, ...
   189         for (Iterator<ClassDoc> it = classtree.baseclasses().iterator(); it.hasNext();) {
   190             subclasses(it.next());
   191         }
   192         for (Iterator<ClassDoc> it = classtree.baseinterfaces().iterator(); it.hasNext();) {
   193             // does subinterfacing as side-effect
   194             implementingClasses(it.next());
   195         }
   196         // Map methods, fields, constructors using a class.
   197         ClassDoc[] classes = root.classes();
   198         for (int i = 0; i < classes.length; i++) {
   199             PackageDoc pkg = classes[i].containingPackage();
   200             mapAnnotations(classToPackageAnnotations, pkg, pkg);
   201             ClassDoc cd = classes[i];
   202             mapTypeParameters(classToClassTypeParam, cd, cd);
   203             mapAnnotations(classToClassAnnotations, cd, cd);
   204             FieldDoc[] fields = cd.fields();
   205             for (int j = 0; j < fields.length; j++) {
   206                 FieldDoc fd = fields[j];
   207                 mapTypeParameters(classToFieldDocTypeParam, fd, fd);
   208                 mapAnnotations(annotationToFieldDoc, fd, fd);
   209                 if (! fd.type().isPrimitive()) {
   210                     add(classToField, fd.type().asClassDoc(), fd);
   211                 }
   212             }
   213             ConstructorDoc[] cons = cd.constructors();
   214             for (int j = 0; j < cons.length; j++) {
   215                 mapAnnotations(classToConstructorAnnotations, cons[j], cons[j]);
   216                 mapExecutable(cons[j]);
   217             }
   218             MethodDoc[] meths = cd.methods();
   219             for (int j = 0; j < meths.length; j++) {
   220                 MethodDoc md = meths[j];
   221                 mapExecutable(md);
   222                 mapTypeParameters(classToExecMemberDocTypeParam, md, md);
   223                 mapAnnotations(classToExecMemberDocAnnotations, md, md);
   224                 if (! (md.returnType().isPrimitive() || md.returnType() instanceof TypeVariable)) {
   225                     mapTypeParameters(classToExecMemberDocReturnTypeParam,
   226                         md.returnType(), md);
   227                     add(classToMethodReturn, md.returnType().asClassDoc(), md);
   228                 }
   229             }
   230         }
   231     }
   233     /**
   234      * Return all subclasses of a class AND fill-in classToSubclass map.
   235      */
   236     private Collection<ClassDoc> subclasses(ClassDoc cd) {
   237         Collection<ClassDoc> ret = classToSubclass.get(cd.qualifiedName());
   238         if (ret == null) {
   239             ret = new TreeSet<ClassDoc>();
   240             List<ClassDoc> subs = classtree.subclasses(cd);
   241             if (subs != null) {
   242                 ret.addAll(subs);
   243                 for (Iterator<ClassDoc> it = subs.iterator(); it.hasNext();) {
   244                     ret.addAll(subclasses(it.next()));
   245                 }
   246             }
   247             addAll(classToSubclass, cd, ret);
   248         }
   249         return ret;
   250     }
   252     /**
   253      * Return all subinterfaces of an interface AND fill-in classToSubinterface map.
   254      */
   255     private Collection<ClassDoc> subinterfaces(ClassDoc cd) {
   256         Collection<ClassDoc> ret = classToSubinterface.get(cd.qualifiedName());
   257         if (ret == null) {
   258             ret = new TreeSet<ClassDoc>();
   259             List<ClassDoc> subs = classtree.subinterfaces(cd);
   260             if (subs != null) {
   261                 ret.addAll(subs);
   262                 for (Iterator<ClassDoc> it = subs.iterator(); it.hasNext();) {
   263                     ret.addAll(subinterfaces(it.next()));
   264                 }
   265             }
   266             addAll(classToSubinterface, cd, ret);
   267         }
   268         return ret;
   269     }
   271     /**
   272      * Return all implementing classes of an interface (including
   273      * all subclasses of implementing classes and all classes
   274      * implementing subinterfaces) AND fill-in both classToImplementingClass
   275      * and classToSubinterface maps.
   276      */
   277     private Collection<ClassDoc> implementingClasses(ClassDoc cd) {
   278         Collection<ClassDoc> ret = classToImplementingClass.get(cd.qualifiedName());
   279         if (ret == null) {
   280             ret = new TreeSet<ClassDoc>();
   281             List<ClassDoc> impl = classtree.implementingclasses(cd);
   282             if (impl != null) {
   283                 ret.addAll(impl);
   284                 for (Iterator<ClassDoc> it = impl.iterator(); it.hasNext();) {
   285                     ret.addAll(subclasses(it.next()));
   286                 }
   287             }
   288             for (Iterator<ClassDoc> it = subinterfaces(cd).iterator(); it.hasNext();) {
   289                 ret.addAll(implementingClasses(it.next()));
   290             }
   291             addAll(classToImplementingClass, cd, ret);
   292         }
   293         return ret;
   294     }
   296     /**
   297      * Determine classes used by a method or constructor, so they can be
   298      * inverse mapped.
   299      */
   300     private void mapExecutable(ExecutableMemberDoc em) {
   301         Parameter[] params = em.parameters();
   302         boolean isConstructor = em.isConstructor();
   303         List<Type> classArgs = new ArrayList<Type>();
   304         for (int k = 0; k < params.length; k++) {
   305             Type pcd = params[k].type();
   306             // primitives don't get mapped, also avoid dups
   307             if ((! params[k].type().isPrimitive()) &&
   308                  ! classArgs.contains(pcd) &&
   309                  ! (pcd instanceof TypeVariable)) {
   310                 add(isConstructor? classToConstructorArgs :classToMethodArgs,
   311                         pcd.asClassDoc(), em);
   312                 classArgs.add(pcd);
   313                 mapTypeParameters(isConstructor?
   314                    classToConstructorDocArgTypeParam : classToExecMemberDocArgTypeParam,
   315                    pcd, em);
   316             }
   317             mapAnnotations(
   318                 isConstructor ?
   319                     classToConstructorParamAnnotation :
   320                     classToExecMemberDocParamAnnotation,
   321                 params[k], em);
   322         }
   323         ClassDoc[] thr = em.thrownExceptions();
   324         for (int k = 0; k < thr.length; k++) {
   325             add(isConstructor? classToConstructorThrows : classToMethodThrows,
   326                     thr[k], em);
   327         }
   328     }
   330     private <T> List<T> refList(Map<String,List<T>> map, ClassDoc cd) {
   331         List<T> list = map.get(cd.qualifiedName());
   332         if (list == null) {
   333             List<T> l = new ArrayList<T>();
   334             list = l;
   335             map.put(cd.qualifiedName(), list);
   336         }
   337         return list;
   338     }
   340     private Set<PackageDoc> packageSet(ClassDoc cd) {
   341         Set<PackageDoc> pkgSet = classToPackage.get(cd.qualifiedName());
   342         if (pkgSet == null) {
   343             pkgSet = new TreeSet<PackageDoc>();
   344             classToPackage.put(cd.qualifiedName(), pkgSet);
   345         }
   346         return pkgSet;
   347     }
   349     private Set<ClassDoc> classSet(ClassDoc cd) {
   350         Set<ClassDoc> clsSet = classToClass.get(cd.qualifiedName());
   351         if (clsSet == null) {
   352             Set<ClassDoc> s = new TreeSet<ClassDoc>();
   353             clsSet = s;
   354             classToClass.put(cd.qualifiedName(), clsSet);
   355         }
   356         return clsSet;
   357     }
   359     private <T extends ProgramElementDoc> void add(Map<String,List<T>> map, ClassDoc cd, T ref) {
   360         // add to specified map
   361         refList(map, cd).add(ref);
   363         // add ref's package to package map and class map
   364         packageSet(cd).add(ref.containingPackage());
   366         classSet(cd).add(ref instanceof MemberDoc?
   367                 ((MemberDoc)ref).containingClass() :
   368                     (ClassDoc)ref);
   369     }
   371     private void addAll(Map<String,List<ClassDoc>> map, ClassDoc cd, Collection<ClassDoc> refs) {
   372         if (refs == null) {
   373             return;
   374         }
   375         // add to specified map
   376         refList(map, cd).addAll(refs);
   378         Set<PackageDoc> pkgSet = packageSet(cd);
   379         Set<ClassDoc> clsSet = classSet(cd);
   380         // add ref's package to package map and class map
   381         for (Iterator<ClassDoc> it = refs.iterator(); it.hasNext();) {
   382             ClassDoc cls = it.next();
   383             pkgSet.add(cls.containingPackage());
   384             clsSet.add(cls);
   386         }
   387     }
   389     /**
   390      * Map the ClassDocs to the ProgramElementDocs that use them as
   391      * type parameters.
   392      *
   393      * @param map the map the insert the information into.
   394      * @param doc the doc whose type parameters are being checked.
   395      * @param holder the holder that owns the type parameters.
   396      */
   397     private <T extends ProgramElementDoc> void mapTypeParameters(Map<String,List<T>> map, Object doc,
   398             T holder) {
   399         TypeVariable[] typeVariables;
   400         if (doc instanceof ClassDoc) {
   401             typeVariables = ((ClassDoc) doc).typeParameters();
   402         } else if (doc instanceof WildcardType) {
   403             Type[] extendsBounds = ((WildcardType) doc).extendsBounds();
   404             for (int k = 0; k < extendsBounds.length; k++) {
   405                 addTypeParameterToMap(map, extendsBounds[k], holder);
   406             }
   407             Type[] superBounds = ((WildcardType) doc).superBounds();
   408             for (int k = 0; k < superBounds.length; k++) {
   409                 addTypeParameterToMap(map, superBounds[k], holder);
   410             }
   411             return;
   412         } else if (doc instanceof ParameterizedType) {
   413             Type[] typeArguments = ((ParameterizedType) doc).typeArguments();
   414             for (int k = 0; k < typeArguments.length; k++) {
   415                 addTypeParameterToMap(map, typeArguments[k], holder);
   416             }
   417             return;
   418         } else if (doc instanceof ExecutableMemberDoc) {
   419             typeVariables = ((ExecutableMemberDoc) doc).typeParameters();
   420         } else if (doc instanceof FieldDoc) {
   421             Type fieldType = ((FieldDoc) doc).type();
   422             mapTypeParameters(map, fieldType, holder);
   423             return;
   424         } else {
   425             return;
   426         }
   427         for (int i = 0; i < typeVariables.length; i++) {
   428             Type[] bounds = typeVariables[i].bounds();
   429             for (int j = 0; j < bounds.length; j++) {
   430                 addTypeParameterToMap(map, bounds[j], holder);
   431             }
   432         }
   433     }
   435     /**
   436      * Map the AnnotationType to the ProgramElementDocs that use them as
   437      * type parameters.
   438      *
   439      * @param map the map the insert the information into.
   440      * @param doc the doc whose type parameters are being checked.
   441      * @param holder the holder that owns the type parameters.
   442      */
   443     private <T extends ProgramElementDoc> void mapAnnotations(Map<String,List<T>> map, Object doc,
   444             T holder) {
   445         AnnotationDesc[] annotations;
   446         boolean isPackage = false;
   447         if (doc instanceof ProgramElementDoc) {
   448             annotations = ((ProgramElementDoc) doc).annotations();
   449         } else if (doc instanceof PackageDoc) {
   450             annotations = ((PackageDoc) doc).annotations();
   451             isPackage = true;
   452         } else if (doc instanceof Parameter) {
   453             annotations = ((Parameter) doc).annotations();
   454         } else {
   455             throw new DocletAbortException();
   456         }
   457         for (int i = 0; i < annotations.length; i++) {
   458             AnnotationTypeDoc annotationDoc = annotations[i].annotationType();
   459             if (isPackage)
   460                 refList(map, annotationDoc).add(holder);
   461             else
   462                 add(map, annotationDoc, holder);
   463         }
   464     }
   467     /**
   468      * Map the AnnotationType to the ProgramElementDocs that use them as
   469      * type parameters.
   470      *
   471      * @param map the map the insert the information into.
   472      * @param doc the doc whose type parameters are being checked.
   473      * @param holder the holder that owns the type parameters.
   474      */
   475     private <T extends PackageDoc> void mapAnnotations(Map<String,List<T>> map, PackageDoc doc,
   476             T holder) {
   477         AnnotationDesc[] annotations;
   478         annotations = doc.annotations();
   479         for (int i = 0; i < annotations.length; i++) {
   480             AnnotationTypeDoc annotationDoc = annotations[i].annotationType();
   481             refList(map, annotationDoc).add(holder);
   482         }
   483     }
   485     private <T extends ProgramElementDoc> void addTypeParameterToMap(Map<String,List<T>> map, Type type,
   486             T holder) {
   487         if (type instanceof ClassDoc) {
   488             add(map, (ClassDoc) type, holder);
   489         } else if (type instanceof ParameterizedType) {
   490             add(map, ((ParameterizedType) type).asClassDoc(), holder);
   491         }
   492         mapTypeParameters(map, type, holder);
   493     }
   494 }

mercurial