1 /*
   2  * Copyright (c) 1998, 2017, 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 package jdk.javadoc.internal.doclets.toolkit.util;
  26 
  27 import java.util.*;
  28 
  29 import javax.lang.model.element.AnnotationMirror;
  30 import javax.lang.model.element.Element;
  31 import javax.lang.model.element.ExecutableElement;
  32 import javax.lang.model.element.PackageElement;
  33 import javax.lang.model.element.TypeElement;
  34 import javax.lang.model.element.TypeParameterElement;
  35 import javax.lang.model.element.VariableElement;
  36 import javax.lang.model.type.ArrayType;
  37 import javax.lang.model.type.DeclaredType;
  38 import javax.lang.model.type.ErrorType;
  39 import javax.lang.model.type.TypeMirror;
  40 import javax.lang.model.type.TypeVariable;
  41 import javax.lang.model.type.WildcardType;
  42 import javax.lang.model.util.Elements;
  43 import javax.lang.model.util.SimpleElementVisitor9;
  44 import javax.lang.model.util.SimpleTypeVisitor9;
  45 import javax.lang.model.util.Types;
  46 
  47 import jdk.javadoc.doclet.DocletEnvironment;
  48 import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
  49 
  50 /**
  51  * Map all class uses for a given class.
  52  *
  53  * <p>
  54  * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
  55  * your own risk. This code and its internal interfaces are subject to change or deletion without
  56  * notice.</b>
  57  *
  58  * @author Robert G. Field
  59  */
  60 public class ClassUseMapper {
  61 
  62     private final ClassTree classtree;
  63 
  64     /**
  65      * Mapping of TypeElements to set of PackageElements used by that class.
  66      */
  67     public final Map<TypeElement, Set<PackageElement>> classToPackage;
  68 
  69     /**
  70      * Mapping of TypeElements representing annotations to a set of PackageElements that use the annotation.
  71      */
  72     public final Map<TypeElement, List<PackageElement>> classToPackageAnnotations = new HashMap<>();
  73 
  74     /**
  75      * Mapping of TypeElements to a set of TypeElements used by that class.
  76      */
  77     public final Map<TypeElement, Set<TypeElement>> classToClass = new HashMap<>();
  78 
  79     /**
  80      * Mapping of TypeElements to a list of TypeElements which are direct or indirect subClasses of
  81      * that class.
  82      */
  83     public final Map<TypeElement, List<TypeElement>> classToSubclass = new HashMap<>();
  84 
  85     /**
  86      * Mapping of TypeElements to list of TypeElements which are direct or indirect subInterfaces of
  87      * that interface.
  88      */
  89     public final Map<TypeElement, List<TypeElement>> classToSubinterface = new HashMap<>();
  90 
  91     /**
  92      * Mapping of TypeElements to list of TypeElements which implement this interface.
  93      */
  94     public Map<TypeElement, List<TypeElement>> classToImplementingClass = new HashMap<>();
  95 
  96     /**
  97      * Mapping of TypeElements to list of VariableElements declared as that class.
  98      */
  99     public final Map<TypeElement, List<VariableElement>> classToField = new HashMap<>();
 100 
 101     /**
 102      * Mapping of TypeElements to list of ExecutableElements returning that class.
 103      */
 104     public final Map<TypeElement, List<ExecutableElement>> classToMethodReturn = new HashMap<>();
 105 
 106     /**
 107      * Mapping of TypeElements to list of ExecutableElements having that class as an arg.
 108      */
 109     public final Map<TypeElement, List<ExecutableElement>> classToMethodArgs = new HashMap<>();
 110 
 111     /**
 112      * Mapping of TypeElements to list of ExecutableElements which throws that class.
 113      */
 114     public final Map<TypeElement, List<ExecutableElement>> classToMethodThrows = new HashMap<>();
 115 
 116     /**
 117      * Mapping of TypeElements to list of ExecutableElements (constructors) having that
 118      * class as an arg.
 119      */
 120     public final Map<TypeElement, List<ExecutableElement>> classToConstructorArgs = new HashMap<>();
 121 
 122     /**
 123      * Mapping of TypeElements to list of constructors which throws that class.
 124      */
 125     public final Map<TypeElement, List<ExecutableElement>> classToConstructorThrows = new HashMap<>();
 126 
 127     /**
 128      * The mapping of TypeElements representing annotations to constructors that use them.
 129      */
 130     public final Map<TypeElement, List<ExecutableElement>> classToConstructorAnnotations = new HashMap<>();
 131 
 132     /**
 133      * The mapping of TypeElement representing annotations to constructor parameters that use them.
 134      */
 135     public final Map<TypeElement, List<ExecutableElement>> classToConstructorParamAnnotation = new HashMap<>();
 136 
 137     /**
 138      * The mapping of TypeElements to constructor arguments that use them as type parameters.
 139      */
 140     public final Map<TypeElement, List<ExecutableElement>> classToConstructorArgTypeParam = new HashMap<>();
 141 
 142     /**
 143      * The mapping of TypeElement to TypeElement that use them as type parameters.
 144      */
 145     public final Map<TypeElement, List<TypeElement>> classToClassTypeParam = new HashMap<>();
 146 
 147     /**
 148      * The mapping of TypeElement representing annotation to TypeElements that use them.
 149      */
 150     public final Map<TypeElement, List<TypeElement>> classToClassAnnotations = new HashMap<>();
 151 
 152     /**
 153      * The mapping of TypeElement to methods that use them as type parameters.
 154      */
 155     public final Map<TypeElement, List<ExecutableElement>> classToMethodTypeParam = new HashMap<>();
 156 
 157     /**
 158      * The mapping of TypeElement to method arguments that use them as type parameters.
 159      */
 160     public final Map<TypeElement, List<ExecutableElement>> classToMethodArgTypeParam = new HashMap<>();
 161 
 162     /**
 163      * The mapping of TypeElement representing annotation to methods that use them.
 164      */
 165     public final Map<TypeElement, List<ExecutableElement>> classToMethodAnnotations = new HashMap<>();
 166 
 167     /**
 168      * The mapping of TypeElements to methods that have return type with type parameters
 169      * of that class.
 170      */
 171     public final Map<TypeElement, List<ExecutableElement>> classToMethodReturnTypeParam = new HashMap<>();
 172 
 173     /**
 174      * The mapping of TypeElements representing annotations to method parameters that use them.
 175      */
 176     public final Map<TypeElement, List<ExecutableElement>> classToMethodParamAnnotation = new HashMap<>();
 177 
 178     /**
 179      * The mapping of TypeElements to fields that use them as type parameters.
 180      */
 181     public final Map<TypeElement, List<VariableElement>> classToFieldTypeParam = new HashMap<>();
 182 
 183     /**
 184      * The mapping of TypeElements representing annotation to fields that use them.
 185      */
 186     public final Map<TypeElement, List<VariableElement>> annotationToField = new HashMap<>();
 187 
 188     private final DocletEnvironment docEnv;
 189     private final Elements elementUtils;
 190     private final Types typeUtils;
 191     private final Utils utils;
 192 
 193     public ClassUseMapper(HtmlConfiguration configuration, ClassTree classtree) {
 194         docEnv = configuration.docEnv;
 195         elementUtils = docEnv.getElementUtils();
 196         typeUtils = docEnv.getTypeUtils();
 197         utils = configuration.utils;
 198         this.classtree = classtree;
 199         classToPackage = new TreeMap<>(utils.makeClassUseComparator());
 200         // Map subclassing, subinterfacing implementing, ...
 201         for (TypeElement te : classtree.baseClasses()) {
 202             subclasses(te);
 203         }
 204         for (TypeElement intfc : classtree.baseInterfaces()) {
 205             // does subinterfacing as side-effect
 206             implementingClasses(intfc);
 207         }
 208         // Map methods, fields, constructors using a class.
 209         Set<TypeElement> classes = configuration.getIncludedTypeElements();
 210         for (TypeElement aClass : classes) {
 211             PackageElement pkg = elementUtils.getPackageOf(aClass);
 212             mapAnnotations(classToPackageAnnotations, pkg, pkg);
 213             mapTypeParameters(classToClassTypeParam, aClass, aClass);
 214             mapAnnotations(classToClassAnnotations, aClass, aClass);
 215             List<VariableElement> fields = utils.getFields(aClass);
 216             for (VariableElement fd : fields) {
 217                 mapTypeParameters(classToFieldTypeParam, fd, fd);
 218                 mapAnnotations(annotationToField, fd, fd);
 219                 SimpleTypeVisitor9<Void, VariableElement> stv = new SimpleTypeVisitor9<Void, VariableElement>() {
 220                     @Override
 221                     public Void visitArray(ArrayType t, VariableElement p) {
 222                         return visit(t.getComponentType(), p);
 223                     }
 224 
 225                     @Override
 226                     public Void visitDeclared(DeclaredType t, VariableElement p) {
 227                         add(classToField, (TypeElement) t.asElement(), p);
 228                         return null;
 229                     }
 230                     @Override
 231                     public Void visitTypeVariable(TypeVariable t, VariableElement p) {
 232                         return visit(typeUtils.erasure(t), p);
 233                     }
 234                 };
 235                 stv.visit(fd.asType(), fd);
 236             }
 237 
 238             List<ExecutableElement> ctors = utils.getConstructors(aClass);
 239             for (ExecutableElement ctor : ctors) {
 240                 mapAnnotations(classToConstructorAnnotations, ctor, ctor);
 241                 mapExecutable(ctor);
 242             }
 243 
 244             List<ExecutableElement> methods = utils.getMethods(aClass);
 245             for (ExecutableElement method : methods) {
 246                 mapExecutable(method);
 247                 mapTypeParameters(classToMethodTypeParam, method, method);
 248                 mapAnnotations(classToMethodAnnotations, method, method);
 249                 SimpleTypeVisitor9<Void, ExecutableElement> stv = new SimpleTypeVisitor9<Void, ExecutableElement>() {
 250                     @Override
 251                     public Void visitArray(ArrayType t, ExecutableElement p) {
 252                         TypeMirror componentType = t.getComponentType();
 253                         return visit(utils.isTypeVariable(componentType)
 254                                 ? typeUtils.erasure(componentType)
 255                                 : componentType, p);
 256                     }
 257 
 258                     @Override
 259                     public Void visitDeclared(DeclaredType t, ExecutableElement p) {
 260                         mapTypeParameters(classToMethodReturnTypeParam, t, p);
 261                         add(classToMethodReturn, (TypeElement) t.asElement(), p);
 262                         return null;
 263                     }
 264 
 265                     @Override
 266                     protected Void defaultAction(TypeMirror e, ExecutableElement p) {
 267                         return null;
 268                     }
 269                 };
 270                 stv.visit(method.getReturnType(), method);
 271             }
 272         }
 273     }
 274 
 275     /**
 276      * Return all subClasses of a class AND fill-in classToSubclass map.
 277      */
 278     private Collection<TypeElement> subclasses(TypeElement te) {
 279         Collection<TypeElement> ret = classToSubclass.get(te);
 280         if (ret == null) {
 281             ret = new TreeSet<>(utils.makeClassUseComparator());
 282             Set<TypeElement> subs = classtree.subClasses(te);
 283             if (subs != null) {
 284                 ret.addAll(subs);
 285                 for (TypeElement sub : subs) {
 286                     ret.addAll(subclasses(sub));
 287                 }
 288             }
 289             addAll(classToSubclass, te, ret);
 290         }
 291         return ret;
 292     }
 293 
 294     /**
 295      * Return all subInterfaces of an interface AND fill-in classToSubinterface map.
 296      */
 297     private Collection<TypeElement> subinterfaces(TypeElement te) {
 298         Collection<TypeElement> ret = classToSubinterface.get(te);
 299         if (ret == null) {
 300             ret = new TreeSet<>(utils.makeClassUseComparator());
 301             Set<TypeElement> subs = classtree.subInterfaces(te);
 302             if (subs != null) {
 303                 ret.addAll(subs);
 304                 for (TypeElement sub : subs) {
 305                     ret.addAll(subinterfaces(sub));
 306                 }
 307             }
 308             addAll(classToSubinterface, te, ret);
 309         }
 310         return ret;
 311     }
 312 
 313     /**
 314      * Return all implementing classes of an interface (including all subClasses of implementing
 315      * classes and all classes implementing subInterfaces) AND fill-in both classToImplementingClass
 316      * and classToSubinterface maps.
 317      */
 318     private Collection<TypeElement> implementingClasses(TypeElement te) {
 319         Collection<TypeElement> ret = classToImplementingClass.get(te);
 320         if (ret == null) {
 321             ret = new TreeSet<>(utils.makeClassUseComparator());
 322             Set<TypeElement> impl = classtree.implementingClasses(te);
 323             if (impl != null) {
 324                 ret.addAll(impl);
 325                 for (TypeElement anImpl : impl) {
 326                     ret.addAll(subclasses(anImpl));
 327                 }
 328             }
 329             for (TypeElement intfc : subinterfaces(te)) {
 330                 ret.addAll(implementingClasses(intfc));
 331             }
 332             addAll(classToImplementingClass, te, ret);
 333         }
 334         return ret;
 335     }
 336 
 337     /**
 338      * Determine classes used by a method or constructor, so they can be inverse mapped.
 339      */
 340     private void mapExecutable(ExecutableElement ee) {
 341         final boolean isConstructor = utils.isConstructor(ee);
 342         Set<TypeMirror> classArgs = new TreeSet<>(utils.makeTypeMirrorClassUseComparator());
 343         for (VariableElement param : ee.getParameters()) {
 344             TypeMirror pType = param.asType();
 345             // primitives don't get mapped and type variables are mapped elsewhere
 346             if (!pType.getKind().isPrimitive() && !utils.isTypeVariable(pType)) {
 347                 // no duplicates please
 348                 if (classArgs.add(pType)) {
 349                     new SimpleTypeVisitor9<Void, ExecutableElement>() {
 350                         @Override
 351                         public Void visitArray(ArrayType t, ExecutableElement p) {
 352                             return visit(t.getComponentType(), p);
 353                         }
 354 
 355                         @Override
 356                         public Void visitDeclared(DeclaredType t, ExecutableElement p) {
 357                             add(isConstructor
 358                                     ? classToConstructorArgs
 359                                     : classToMethodArgs,
 360                                     (TypeElement) t.asElement(), p);
 361                             return null;
 362                         }
 363                         @Override
 364                         public Void visitTypeVariable(TypeVariable t, ExecutableElement p) {
 365                             visit(typeUtils.erasure(t), p);
 366                             return null;
 367                         }
 368                     }.visit(pType, ee);
 369                     mapTypeParameters(isConstructor
 370                             ? classToConstructorArgTypeParam
 371                             : classToMethodArgTypeParam,
 372                             pType, ee);
 373                 }
 374             }
 375             mapAnnotations(isConstructor
 376                     ? classToConstructorParamAnnotation
 377                     : classToMethodParamAnnotation,
 378                     param, ee);
 379 
 380         }
 381         for (TypeMirror anException : ee.getThrownTypes()) {
 382             SimpleTypeVisitor9<Void, ExecutableElement> stv = new SimpleTypeVisitor9<Void, ExecutableElement>() {
 383 
 384                 @Override
 385                 public Void visitArray(ArrayType t, ExecutableElement p) {
 386                     super.visit(t.getComponentType(), p);
 387                     return null;
 388                 }
 389 
 390                 @Override
 391                 public Void visitDeclared(DeclaredType t, ExecutableElement p) {
 392                     add(isConstructor ? classToConstructorThrows : classToMethodThrows,
 393                             (TypeElement) t.asElement(), p);
 394                     return null;
 395                 }
 396 
 397                 @Override
 398                 public Void visitError(ErrorType t, ExecutableElement p) {
 399                     add(isConstructor ? classToConstructorThrows : classToMethodThrows,
 400                             (TypeElement) t.asElement(), p);
 401                     return null;
 402                 }
 403 
 404                 @Override
 405                 protected Void defaultAction(TypeMirror e, ExecutableElement p) {
 406                     throw new AssertionError("this should not happen");
 407                 }
 408             };
 409 
 410             stv.visit(typeUtils.erasure(anException), ee);
 411         }
 412     }
 413 
 414     private <T> List<T> refList(Map<TypeElement, List<T>> map, Element element) {
 415         List<T> list = map.get(element);
 416         if (list == null) {
 417             list = new ArrayList<>();
 418             map.put((TypeElement) element, list);
 419         }
 420         return list;
 421     }
 422 
 423     private Set<PackageElement> packageSet(TypeElement te) {
 424         Set<PackageElement> pkgSet = classToPackage.get(te);
 425         if (pkgSet == null) {
 426             pkgSet = new TreeSet<>(utils.makeClassUseComparator());
 427             classToPackage.put(te, pkgSet);
 428         }
 429         return pkgSet;
 430     }
 431 
 432     private Set<TypeElement> classSet(TypeElement te) {
 433         Set<TypeElement> clsSet = classToClass.get(te);
 434         if (clsSet == null) {
 435             clsSet = new TreeSet<>(utils.makeClassUseComparator());
 436             classToClass.put(te, clsSet);
 437         }
 438         return clsSet;
 439     }
 440 
 441     private <T extends Element> void add(Map<TypeElement, List<T>> map, TypeElement te, T ref) {
 442         // add to specified map
 443         refList(map, te).add(ref);
 444         // add ref's package to package map and class map
 445         packageSet(te).add(elementUtils.getPackageOf(ref));
 446         TypeElement entry = (utils.isField((Element) ref)
 447                 || utils.isConstructor((Element) ref)
 448                 || utils.isMethod((Element) ref))
 449                 ? (TypeElement) ref.getEnclosingElement()
 450                 : (TypeElement) ref;
 451         classSet(te).add(entry);
 452     }
 453 
 454     private void addAll(Map<TypeElement, List<TypeElement>> map, TypeElement te, Collection<TypeElement> refs) {
 455         if (refs == null) {
 456             return;
 457         }
 458         // add to specified map
 459         refList(map, te).addAll(refs);
 460 
 461         Set<PackageElement> pkgSet = packageSet(te);
 462         Set<TypeElement> clsSet = classSet(te);
 463         // add ref's package to package map and class map
 464         for (TypeElement cls : refs) {
 465             pkgSet.add(utils.containingPackage(cls));
 466             clsSet.add(cls);
 467         }
 468     }
 469 
 470     /**
 471      * Map the TypeElements to the members that use them as type parameters.
 472      *
 473      * @param map the map the insert the information into.
 474      * @param element the te whose type parameters are being checked.
 475      * @param holder the holder that owns the type parameters.
 476      */
 477     private <T extends Element> void mapTypeParameters(final Map<TypeElement, List<T>> map,
 478             Element element, final T holder) {
 479 
 480         SimpleElementVisitor9<Void, Void> elementVisitor
 481                 = new SimpleElementVisitor9<Void, Void>() {
 482 
 483                     private void addParameters(TypeParameterElement e) {
 484                         for (TypeMirror type : utils.getBounds(e)) {
 485                             addTypeParameterToMap(map, type, holder);
 486                         }
 487                     }
 488 
 489                     @Override
 490                     public Void visitType(TypeElement e, Void p) {
 491                         for (TypeParameterElement param : e.getTypeParameters()) {
 492                             addParameters(param);
 493                         }
 494                         return null;
 495                     }
 496 
 497                     @Override
 498                     public Void visitExecutable(ExecutableElement e, Void p) {
 499                         for (TypeParameterElement param : e.getTypeParameters()) {
 500                             addParameters(param);
 501                         }
 502                         return null;
 503                     }
 504 
 505                     @Override
 506                     protected Void defaultAction(Element e, Void p) {
 507                         mapTypeParameters(map, e.asType(), holder);
 508                         return null;
 509                     }
 510 
 511                     @Override
 512                     public Void visitTypeParameter(TypeParameterElement e, Void p) {
 513                         addParameters(e);
 514                         return null;
 515                     }
 516                 };
 517         elementVisitor.visit(element);
 518     }
 519 
 520     private <T extends Element> void mapTypeParameters(final Map<TypeElement, List<T>> map,
 521             TypeMirror aType, final T holder) {
 522 
 523         SimpleTypeVisitor9<Void, Void> tv = new SimpleTypeVisitor9<Void, Void>() {
 524 
 525             @Override
 526             public Void visitWildcard(WildcardType t, Void p) {
 527                 TypeMirror bound = t.getExtendsBound();
 528                 if (bound != null) {
 529                     addTypeParameterToMap(map, bound, holder);
 530                 }
 531                 bound = t.getSuperBound();
 532                 if (bound != null) {
 533                     addTypeParameterToMap(map, bound, holder);
 534                 }
 535                 return null;
 536             }
 537 
 538             // ParameterizedType
 539             @Override
 540             public Void visitDeclared(DeclaredType t, Void p) {
 541                 for (TypeMirror targ : t.getTypeArguments()) {
 542                     addTypeParameterToMap(map, targ, holder);
 543                 }
 544                 return null;
 545             }
 546         };
 547         tv.visit(aType);
 548     }
 549 
 550     /**
 551      * Map the AnnotationType to the members that use them as type parameters.
 552      *
 553      * @param map the map the insert the information into.
 554      * @param element whose type parameters are being checked.
 555      * @param holder the holder that owns the type parameters.
 556      */
 557     private <T extends Element> void mapAnnotations(final Map<TypeElement, List<T>> map,
 558             Element e, final T holder) {
 559         new SimpleElementVisitor9<Void, Void>() {
 560 
 561             void addAnnotations(Element e) {
 562                 for (AnnotationMirror a : e.getAnnotationMirrors()) {
 563                     add(map, (TypeElement) a.getAnnotationType().asElement(), holder);
 564                 }
 565             }
 566 
 567             @Override
 568             public Void visitPackage(PackageElement e, Void p) {
 569                 for (AnnotationMirror a : e.getAnnotationMirrors()) {
 570                     refList(map, a.getAnnotationType().asElement()).add(holder);
 571                 }
 572                 return null;
 573             }
 574 
 575             @Override
 576             protected Void defaultAction(Element e, Void p) {
 577                 addAnnotations(e);
 578                 return null;
 579             }
 580         }.visit(e);
 581     }
 582 
 583     private <T extends Element> void addTypeParameterToMap(final Map<TypeElement, List<T>> map,
 584             TypeMirror type, final T holder) {
 585         new SimpleTypeVisitor9<Void, Void>() {
 586 
 587             @Override
 588             protected Void defaultAction(TypeMirror e, Void p) {
 589                 return super.defaultAction(e, p);
 590             }
 591 
 592             @Override
 593             public Void visitDeclared(DeclaredType t, Void p) {
 594                 add(map, (TypeElement) t.asElement(), holder);
 595                 return null;
 596             }
 597 
 598         }.visit(type);
 599         mapTypeParameters(map, type, holder);
 600     }
 601 }