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 }