001/* 002 * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025package org.jdrupes.mdoclet.internal.doclets.toolkit.util; 026 027import static org.jdrupes.mdoclet.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*; 028 029import java.util.*; 030 031import javax.lang.model.element.AnnotationMirror; 032import javax.lang.model.element.Element; 033import javax.lang.model.element.ExecutableElement; 034import javax.lang.model.element.PackageElement; 035import javax.lang.model.element.TypeElement; 036import javax.lang.model.element.TypeParameterElement; 037import javax.lang.model.element.VariableElement; 038import javax.lang.model.type.ArrayType; 039import javax.lang.model.type.DeclaredType; 040import javax.lang.model.type.ErrorType; 041import javax.lang.model.type.TypeMirror; 042import javax.lang.model.type.TypeVariable; 043import javax.lang.model.type.WildcardType; 044import javax.lang.model.util.ElementFilter; 045import javax.lang.model.util.Elements; 046import javax.lang.model.util.SimpleElementVisitor14; 047import javax.lang.model.util.SimpleTypeVisitor9; 048import javax.lang.model.util.Types; 049 050import org.jdrupes.mdoclet.internal.doclets.toolkit.BaseConfiguration; 051 052import jdk.javadoc.doclet.DocletEnvironment; 053 054/** 055 * Map all class uses for a given class. 056 * 057 * <p> 058 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at 059 * your own risk. This code and its internal interfaces are subject to change or deletion without 060 * notice.</b> 061 */ 062public class ClassUseMapper { 063 064 private final ClassTree classTree; 065 066 /** 067 * Mapping of TypeElements to set of PackageElements used by that class. 068 */ 069 public final Map<TypeElement, Set<PackageElement>> classToPackage; 070 071 /** 072 * Mapping of TypeElements representing annotations to a set of PackageElements that use the annotation. 073 */ 074 public final Map<TypeElement, 075 List<PackageElement>> classToPackageAnnotations = new HashMap<>(); 076 077 /** 078 * Mapping of TypeElements to a set of TypeElements used by that class. 079 */ 080 public final Map<TypeElement, Set<TypeElement>> classToClass 081 = new HashMap<>(); 082 083 /** 084 * Mapping of TypeElements to a list of TypeElements which are direct or indirect subClasses of 085 * that class. 086 */ 087 public final Map<TypeElement, List<TypeElement>> classToSubclass 088 = new HashMap<>(); 089 090 /** 091 * Mapping of TypeElements to list of TypeElements which are direct or indirect subInterfaces of 092 * that interface. 093 */ 094 public final Map<TypeElement, List<TypeElement>> classToSubinterface 095 = new HashMap<>(); 096 097 /** 098 * Mapping of TypeElements to list of TypeElements which implement this interface. 099 */ 100 public Map<TypeElement, List<TypeElement>> classToImplementingClass 101 = new HashMap<>(); 102 103 /** 104 * Mapping of TypeElements to list of VariableElements declared as that class. 105 */ 106 public final Map<TypeElement, List<VariableElement>> classToField 107 = new HashMap<>(); 108 109 /** 110 * Mapping of TypeElements to list of ExecutableElements returning that class. 111 */ 112 public final Map<TypeElement, List<ExecutableElement>> classToMethodReturn 113 = new HashMap<>(); 114 115 /** 116 * Mapping of TypeElements to list of ExecutableElements having that class as an arg. 117 */ 118 public final Map<TypeElement, List<ExecutableElement>> classToMethodArgs 119 = new HashMap<>(); 120 121 /** 122 * Mapping of TypeElements to list of ExecutableElements which throws that class. 123 */ 124 public final Map<TypeElement, List<ExecutableElement>> classToMethodThrows 125 = new HashMap<>(); 126 127 /** 128 * Mapping of TypeElements to list of ExecutableElements (constructors) having that 129 * class as an arg. 130 */ 131 public final Map<TypeElement, 132 List<ExecutableElement>> classToConstructorArgs = new HashMap<>(); 133 134 /** 135 * Mapping of TypeElements to list of constructors which throws that class. 136 */ 137 public final Map<TypeElement, 138 List<ExecutableElement>> classToConstructorThrows = new HashMap<>(); 139 140 /** 141 * The mapping of TypeElements representing annotations to constructors that use them. 142 */ 143 public final Map<TypeElement, 144 List<ExecutableElement>> classToConstructorAnnotations 145 = new HashMap<>(); 146 147 /** 148 * The mapping of TypeElement representing annotations to constructor parameters that use them. 149 */ 150 public final Map<TypeElement, 151 List<ExecutableElement>> classToConstructorParamAnnotation 152 = new HashMap<>(); 153 154 /** 155 * The mapping of TypeElements to constructor arguments that use them as type parameters. 156 */ 157 public final Map<TypeElement, 158 List<ExecutableElement>> classToConstructorArgTypeParam 159 = new HashMap<>(); 160 161 /** 162 * The mapping of TypeElement to TypeElement that use them as type parameters. 163 */ 164 public final Map<TypeElement, List<TypeElement>> classToClassTypeParam 165 = new HashMap<>(); 166 167 /** 168 * The mapping of TypeElement representing annotation to TypeElements that use them. 169 */ 170 public final Map<TypeElement, List<TypeElement>> classToClassAnnotations 171 = new HashMap<>(); 172 173 /** 174 * The mapping of TypeElement to methods that use them as type parameters. 175 */ 176 public final Map<TypeElement, 177 List<ExecutableElement>> classToMethodTypeParam = new HashMap<>(); 178 179 /** 180 * The mapping of TypeElement to method arguments that use them as type parameters. 181 */ 182 public final Map<TypeElement, 183 List<ExecutableElement>> classToMethodArgTypeParam 184 = new HashMap<>(); 185 186 /** 187 * The mapping of TypeElement representing annotation to methods that use them. 188 */ 189 public final Map<TypeElement, 190 List<ExecutableElement>> classToMethodAnnotations = new HashMap<>(); 191 192 /** 193 * The mapping of TypeElements to methods that have return type with type parameters 194 * of that class. 195 */ 196 public final Map<TypeElement, 197 List<ExecutableElement>> classToMethodReturnTypeParam 198 = new HashMap<>(); 199 200 /** 201 * The mapping of TypeElements representing annotations to method parameters that use them. 202 */ 203 public final Map<TypeElement, 204 List<ExecutableElement>> classToMethodParamAnnotation 205 = new HashMap<>(); 206 207 /** 208 * The mapping of TypeElements to fields that use them as type parameters. 209 */ 210 public final Map<TypeElement, List<VariableElement>> classToFieldTypeParam 211 = new HashMap<>(); 212 213 /** 214 * The mapping of TypeElements representing annotation to fields that use them. 215 */ 216 public final Map<TypeElement, List<VariableElement>> annotationToField 217 = new HashMap<>(); 218 219 private final DocletEnvironment docEnv; 220 private final Elements elementUtils; 221 private final Types typeUtils; 222 private final Utils utils; 223 private final Comparators comparators; 224 225 public ClassUseMapper(BaseConfiguration configuration, 226 ClassTree classTree) { 227 docEnv = configuration.docEnv; 228 elementUtils = docEnv.getElementUtils(); 229 typeUtils = docEnv.getTypeUtils(); 230 utils = configuration.utils; 231 comparators = utils.comparators; 232 this.classTree = classTree; 233 classToPackage = new TreeMap<>(comparators.makeClassUseComparator()); 234 // Map subclassing, subinterfacing implementing, ... 235 for (TypeElement te : classTree.classes().roots()) { 236 subclasses(te); 237 } 238 for (TypeElement intfc : classTree.interfaces().roots()) { 239 // does subinterfacing as a side-effect 240 implementingClasses(intfc); 241 } 242 // Map methods, fields, constructors using a class. 243 Set<TypeElement> classes = configuration.getIncludedTypeElements(); 244 for (TypeElement aClass : classes) { 245 PackageElement pkg = elementUtils.getPackageOf(aClass); 246 mapAnnotations(classToPackageAnnotations, pkg, pkg); 247 mapTypeParameters(classToClassTypeParam, aClass, aClass); 248 mapAnnotations(classToClassAnnotations, aClass, aClass); 249 VisibleMemberTable vmt 250 = configuration.getVisibleMemberTable(aClass); 251 252 List<VariableElement> fields 253 = ElementFilter.fieldsIn(vmt.getVisibleMembers(FIELDS)); 254 for (VariableElement fd : fields) { 255 mapTypeParameters(classToFieldTypeParam, fd, fd); 256 mapAnnotations(annotationToField, fd, fd); 257 var stv = new SimpleTypeVisitor9<Void, VariableElement>() { 258 @Override 259 public Void visitArray(ArrayType t, VariableElement p) { 260 return visit(t.getComponentType(), p); 261 } 262 263 @Override 264 public Void visitDeclared(DeclaredType t, 265 VariableElement p) { 266 add(classToField, (TypeElement) t.asElement(), p); 267 return null; 268 } 269 270 @Override 271 public Void visitTypeVariable(TypeVariable t, 272 VariableElement p) { 273 return visit(typeUtils.erasure(t), p); 274 } 275 }; 276 stv.visit(fd.asType(), fd); 277 } 278 279 List<ExecutableElement> ctors 280 = ElementFilter.constructorsIn(vmt.getMembers(CONSTRUCTORS)); 281 for (ExecutableElement ctor : ctors) { 282 mapAnnotations(classToConstructorAnnotations, ctor, ctor); 283 mapExecutable(ctor); 284 } 285 286 List<ExecutableElement> methods 287 = ElementFilter.methodsIn(vmt.getMembers(METHODS)); 288 289 for (ExecutableElement method : methods) { 290 mapExecutable(method); 291 mapTypeParameters(classToMethodTypeParam, method, method); 292 mapAnnotations(classToMethodAnnotations, method, method); 293 var stv = new SimpleTypeVisitor9<Void, ExecutableElement>() { 294 @Override 295 public Void visitArray(ArrayType t, ExecutableElement p) { 296 TypeMirror componentType = t.getComponentType(); 297 return visit(utils.isTypeVariable(componentType) 298 ? typeUtils.erasure(componentType) 299 : componentType, p); 300 } 301 302 @Override 303 public Void visitDeclared(DeclaredType t, 304 ExecutableElement p) { 305 mapTypeParameters(classToMethodReturnTypeParam, t, p); 306 add(classToMethodReturn, (TypeElement) t.asElement(), 307 p); 308 return null; 309 } 310 311 @Override 312 protected Void defaultAction(TypeMirror e, 313 ExecutableElement p) { 314 return null; 315 } 316 }; 317 stv.visit(method.getReturnType(), method); 318 } 319 } 320 } 321 322 /** 323 * Return all subClasses of a class AND fill-in classToSubclass map. 324 */ 325 private Collection<TypeElement> subclasses(TypeElement te) { 326 Collection<TypeElement> ret = classToSubclass.get(te); 327 if (ret == null) { 328 ret = new TreeSet<>(comparators.makeClassUseComparator()); 329 Set<TypeElement> subs = classTree.subClasses(te); 330 if (subs != null) { 331 ret.addAll(subs); 332 for (TypeElement sub : subs) { 333 ret.addAll(subclasses(sub)); 334 } 335 } 336 addAll(classToSubclass, te, ret); 337 } 338 return ret; 339 } 340 341 /** 342 * Return all subInterfaces of an interface AND fill-in classToSubinterface map. 343 */ 344 private Collection<TypeElement> subinterfaces(TypeElement te) { 345 Collection<TypeElement> ret = classToSubinterface.get(te); 346 if (ret == null) { 347 ret = new TreeSet<>(comparators.makeClassUseComparator()); 348 Set<TypeElement> subs = classTree.subInterfaces(te); 349 if (subs != null) { 350 ret.addAll(subs); 351 for (TypeElement sub : subs) { 352 ret.addAll(subinterfaces(sub)); 353 } 354 } 355 addAll(classToSubinterface, te, ret); 356 } 357 return ret; 358 } 359 360 /** 361 * Return all implementing classes of an interface (including all subClasses of implementing 362 * classes and all classes implementing subInterfaces) AND fill-in both classToImplementingClass 363 * and classToSubinterface maps. 364 */ 365 private Collection<TypeElement> implementingClasses(TypeElement te) { 366 Collection<TypeElement> ret = classToImplementingClass.get(te); 367 if (ret == null) { 368 ret = new TreeSet<>(comparators.makeClassUseComparator()); 369 Set<TypeElement> impl = classTree.implementingClasses(te); 370 if (impl != null) { 371 ret.addAll(impl); 372 for (TypeElement anImpl : impl) { 373 ret.addAll(subclasses(anImpl)); 374 } 375 } 376 for (TypeElement intfc : subinterfaces(te)) { 377 ret.addAll(implementingClasses(intfc)); 378 } 379 addAll(classToImplementingClass, te, ret); 380 } 381 return ret; 382 } 383 384 /** 385 * Determine classes used by a method or constructor, so they can be inverse mapped. 386 */ 387 private void mapExecutable(ExecutableElement ee) { 388 final boolean isConstructor = utils.isConstructor(ee); 389 Set<TypeMirror> classArgs 390 = new TreeSet<>(comparators.makeTypeMirrorClassUseComparator()); 391 for (VariableElement param : ee.getParameters()) { 392 TypeMirror pType = param.asType(); 393 // primitives don't get mapped and type variables are mapped 394 // elsewhere 395 if (!pType.getKind().isPrimitive() 396 && !utils.isTypeVariable(pType)) { 397 // no duplicates please 398 if (classArgs.add(pType)) { 399 new SimpleTypeVisitor9<Void, ExecutableElement>() { 400 @Override 401 public Void visitArray(ArrayType t, 402 ExecutableElement p) { 403 return visit(t.getComponentType(), p); 404 } 405 406 @Override 407 public Void visitDeclared(DeclaredType t, 408 ExecutableElement p) { 409 add(isConstructor 410 ? classToConstructorArgs 411 : classToMethodArgs, 412 (TypeElement) t.asElement(), p); 413 return null; 414 } 415 416 @Override 417 public Void visitTypeVariable(TypeVariable t, 418 ExecutableElement p) { 419 visit(typeUtils.erasure(t), p); 420 return null; 421 } 422 }.visit(pType, ee); 423 mapTypeParameters(isConstructor 424 ? classToConstructorArgTypeParam 425 : classToMethodArgTypeParam, 426 pType, ee); 427 } 428 } 429 mapAnnotations(isConstructor 430 ? classToConstructorParamAnnotation 431 : classToMethodParamAnnotation, 432 param, ee); 433 434 } 435 for (TypeMirror anException : ee.getThrownTypes()) { 436 var stv = new SimpleTypeVisitor9<Void, ExecutableElement>() { 437 438 @Override 439 public Void visitArray(ArrayType t, ExecutableElement p) { 440 super.visit(t.getComponentType(), p); 441 return null; 442 } 443 444 @Override 445 public Void visitDeclared(DeclaredType t, ExecutableElement p) { 446 add(isConstructor ? classToConstructorThrows 447 : classToMethodThrows, 448 (TypeElement) t.asElement(), p); 449 return null; 450 } 451 452 @Override 453 public Void visitError(ErrorType t, ExecutableElement p) { 454 add(isConstructor ? classToConstructorThrows 455 : classToMethodThrows, 456 (TypeElement) t.asElement(), p); 457 return null; 458 } 459 460 @Override 461 protected Void defaultAction(TypeMirror e, 462 ExecutableElement p) { 463 throw new AssertionError("this should not happen"); 464 } 465 }; 466 467 stv.visit(typeUtils.erasure(anException), ee); 468 } 469 } 470 471 private <T> List<T> refList(Map<TypeElement, List<T>> map, 472 TypeElement element) { 473 return map.computeIfAbsent(element, k -> new ArrayList<>()); 474 } 475 476 private Set<PackageElement> packageSet(TypeElement te) { 477 Set<PackageElement> pkgSet = classToPackage.get(te); 478 if (pkgSet == null) { 479 pkgSet = new TreeSet<>(comparators.makeClassUseComparator()); 480 classToPackage.put(te, pkgSet); 481 } 482 return pkgSet; 483 } 484 485 private Set<TypeElement> classSet(TypeElement te) { 486 Set<TypeElement> clsSet = classToClass.get(te); 487 if (clsSet == null) { 488 clsSet = new TreeSet<>(comparators.makeClassUseComparator()); 489 classToClass.put(te, clsSet); 490 } 491 return clsSet; 492 } 493 494 private <T extends Element> void add(Map<TypeElement, List<T>> map, 495 TypeElement te, T ref) { 496 // add to specified map 497 refList(map, te).add(ref); 498 // add ref's package to package map and class map 499 packageSet(te).add(elementUtils.getPackageOf(ref)); 500 TypeElement entry = (utils.isField(ref) 501 || utils.isConstructor(ref) 502 || utils.isMethod(ref)) 503 ? (TypeElement) ref.getEnclosingElement() 504 : (TypeElement) ref; 505 classSet(te).add(entry); 506 } 507 508 private void addAll(Map<TypeElement, List<TypeElement>> map, TypeElement te, 509 Collection<TypeElement> refs) { 510 if (refs == null) { 511 return; 512 } 513 // add to specified map 514 refList(map, te).addAll(refs); 515 516 Set<PackageElement> pkgSet = packageSet(te); 517 Set<TypeElement> clsSet = classSet(te); 518 // add ref's package to package map and class map 519 for (TypeElement cls : refs) { 520 pkgSet.add(utils.containingPackage(cls)); 521 clsSet.add(cls); 522 } 523 } 524 525 /** 526 * Map the TypeElements to the members that use them as type parameters. 527 * 528 * @param map the map the insert the information into. 529 * @param element the te whose type parameters are being checked. 530 * @param holder the holder that owns the type parameters. 531 */ 532 private <T extends Element> void mapTypeParameters( 533 final Map<TypeElement, List<T>> map, 534 Element element, final T holder) { 535 536 var elementVisitor = new SimpleElementVisitor14<Void, Void>() { 537 538 private void addParameters(TypeParameterElement e) { 539 for (TypeMirror type : utils.getBounds(e)) { 540 addTypeParameterToMap(map, type, holder); 541 } 542 } 543 544 @Override 545 public Void visitType(TypeElement e, Void p) { 546 for (TypeParameterElement param : e.getTypeParameters()) { 547 addParameters(param); 548 } 549 return null; 550 } 551 552 @Override 553 public Void visitExecutable(ExecutableElement e, Void p) { 554 for (TypeParameterElement param : e.getTypeParameters()) { 555 addParameters(param); 556 } 557 return null; 558 } 559 560 @Override 561 protected Void defaultAction(Element e, Void p) { 562 mapTypeParameters(map, e.asType(), holder); 563 return null; 564 } 565 566 @Override 567 public Void visitTypeParameter(TypeParameterElement e, Void p) { 568 addParameters(e); 569 return null; 570 } 571 }; 572 elementVisitor.visit(element); 573 } 574 575 private <T extends Element> void mapTypeParameters( 576 final Map<TypeElement, List<T>> map, 577 TypeMirror aType, final T holder) { 578 579 var tv = new SimpleTypeVisitor9<Void, Void>() { 580 581 @Override 582 public Void visitWildcard(WildcardType t, Void p) { 583 TypeMirror bound = t.getExtendsBound(); 584 if (bound != null) { 585 addTypeParameterToMap(map, bound, holder); 586 } 587 bound = t.getSuperBound(); 588 if (bound != null) { 589 addTypeParameterToMap(map, bound, holder); 590 } 591 return null; 592 } 593 594 // ParameterizedType 595 @Override 596 public Void visitDeclared(DeclaredType t, Void p) { 597 for (TypeMirror targ : t.getTypeArguments()) { 598 addTypeParameterToMap(map, targ, holder); 599 } 600 return null; 601 } 602 }; 603 tv.visit(aType); 604 } 605 606 /** 607 * Map the AnnotationType to the members that use them as type parameters. 608 * 609 * @param map the map the insert the information into. 610 * @param e whose type parameters are being checked. 611 * @param holder owning the type parameters. 612 */ 613 private <T extends Element> void mapAnnotations( 614 final Map<TypeElement, List<T>> map, 615 Element e, final T holder) { 616 new SimpleElementVisitor14<Void, Void>() { 617 618 void addAnnotations(Element e) { 619 for (AnnotationMirror a : e.getAnnotationMirrors()) { 620 add(map, (TypeElement) a.getAnnotationType().asElement(), 621 holder); 622 } 623 } 624 625 @Override 626 public Void visitPackage(PackageElement e, Void p) { 627 for (AnnotationMirror a : e.getAnnotationMirrors()) { 628 refList(map, 629 (TypeElement) a.getAnnotationType().asElement()) 630 .add(holder); 631 } 632 return null; 633 } 634 635 @Override 636 protected Void defaultAction(Element e, Void p) { 637 addAnnotations(e); 638 return null; 639 } 640 }.visit(e); 641 } 642 643 private <T extends Element> void addTypeParameterToMap( 644 final Map<TypeElement, List<T>> map, 645 TypeMirror type, final T holder) { 646 new SimpleTypeVisitor9<Void, Void>() { 647 648 @Override 649 protected Void defaultAction(TypeMirror e, Void p) { 650 return super.defaultAction(e, p); 651 } 652 653 @Override 654 public Void visitDeclared(DeclaredType t, Void p) { 655 add(map, (TypeElement) t.asElement(), holder); 656 return null; 657 } 658 659 }.visit(type); 660 mapTypeParameters(map, type, holder); 661 } 662}