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