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