1/* 2 * Copyright (c) 1998, 2014, 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 26package com.sun.tools.doclets.internal.toolkit.util; 27 28import java.util.*; 29 30import com.sun.javadoc.*; 31import com.sun.tools.doclets.formats.html.ConfigurationImpl; 32 33/** 34 * Map all class uses for a given class. 35 * 36 * <p><b>This is NOT part of any supported API. 37 * If you write code that depends on this, you do so at your own risk. 38 * This code and its internal interfaces are subject to change or 39 * deletion without notice.</b> 40 * 41 * @since 1.2 42 * @author Robert G. Field 43 */ 44@Deprecated 45public class ClassUseMapper { 46 47 private final ClassTree classtree; 48 49 /** 50 * Mapping of ClassDocs to set of PackageDoc used by that class. 51 * Entries may be null. 52 */ 53 public Map<String,Set<PackageDoc>> classToPackage = new HashMap<>(); 54 55 /** 56 * Mapping of Annotations to set of PackageDoc that use the annotation. 57 */ 58 public Map<String,List<PackageDoc>> classToPackageAnnotations = new HashMap<>(); 59 60 /** 61 * Mapping of ClassDocs to set of ClassDoc used by that class. 62 * Entries may be null. 63 */ 64 public Map<String,Set<ClassDoc>> classToClass = new HashMap<>(); 65 66 /** 67 * Mapping of ClassDocs to list of ClassDoc which are direct or 68 * indirect subclasses of that class. 69 * Entries may be null. 70 */ 71 public Map<String,List<ClassDoc>> classToSubclass = new HashMap<>(); 72 73 /** 74 * Mapping of ClassDocs to list of ClassDoc which are direct or 75 * indirect subinterfaces of that interface. 76 * Entries may be null. 77 */ 78 public Map<String,List<ClassDoc>> classToSubinterface = new HashMap<>(); 79 80 /** 81 * Mapping of ClassDocs to list of ClassDoc which implement 82 * this interface. 83 * Entries may be null. 84 */ 85 public Map<String,List<ClassDoc>> classToImplementingClass = new HashMap<>(); 86 87 /** 88 * Mapping of ClassDocs to list of FieldDoc declared as that class. 89 * Entries may be null. 90 */ 91 public Map<String,List<FieldDoc>> classToField = new HashMap<>(); 92 93 /** 94 * Mapping of ClassDocs to list of MethodDoc returning that class. 95 * Entries may be null. 96 */ 97 public Map<String,List<MethodDoc>> classToMethodReturn = new HashMap<>(); 98 99 /** 100 * Mapping of ClassDocs to list of MethodDoc having that class 101 * as an arg. 102 * Entries may be null. 103 */ 104 public Map<String,List<ExecutableMemberDoc>> classToMethodArgs = new HashMap<>(); 105 106 /** 107 * Mapping of ClassDocs to list of MethodDoc which throws that class. 108 * Entries may be null. 109 */ 110 public Map<String,List<ExecutableMemberDoc>> classToMethodThrows = new HashMap<>(); 111 112 /** 113 * Mapping of ClassDocs to list of ConstructorDoc having that class 114 * as an arg. 115 * Entries may be null. 116 */ 117 public Map<String,List<ExecutableMemberDoc>> classToConstructorArgs = new HashMap<>(); 118 119 /** 120 * Mapping of ClassDocs to list of ConstructorDoc which throws that class. 121 * Entries may be null. 122 */ 123 public Map<String,List<ExecutableMemberDoc>> classToConstructorThrows = new HashMap<>(); 124 125 /** 126 * The mapping of AnnotationTypeDocs to constructors that use them. 127 */ 128 public Map<String,List<ConstructorDoc>> classToConstructorAnnotations = new HashMap<>(); 129 130 /** 131 * The mapping of AnnotationTypeDocs to Constructor parameters that use them. 132 */ 133 public Map<String,List<ExecutableMemberDoc>> classToConstructorParamAnnotation = new HashMap<>(); 134 135 /** 136 * The mapping of ClassDocs to Constructor arguments that use them as type parameters. 137 */ 138 public Map<String,List<ExecutableMemberDoc>> classToConstructorDocArgTypeParam = new HashMap<>(); 139 140 /** 141 * The mapping of ClassDocs to ClassDocs that use them as type parameters. 142 */ 143 public Map<String,List<ClassDoc>> classToClassTypeParam = new HashMap<>(); 144 145 /** 146 * The mapping of AnnotationTypeDocs to ClassDocs that use them. 147 */ 148 public Map<String,List<ClassDoc>> classToClassAnnotations = new HashMap<>(); 149 150 /** 151 * The mapping of ClassDocs to ExecutableMemberDocs that use them as type parameters. 152 */ 153 public Map<String,List<MethodDoc>> classToExecMemberDocTypeParam = new HashMap<>(); 154 155 /** 156 * The mapping of ClassDocs to ExecutableMemberDocs arguments that use them as type parameters. 157 */ 158 public Map<String,List<ExecutableMemberDoc>> classToExecMemberDocArgTypeParam = new HashMap<>(); 159 160 /** 161 * The mapping of AnnotationTypeDocs to ExecutableMemberDocs that use them. 162 */ 163 public Map<String,List<MethodDoc>> classToExecMemberDocAnnotations = new HashMap<>(); 164 165 /** 166 * The mapping of ClassDocs to ExecutableMemberDocs that have return type 167 * with type parameters of that class. 168 */ 169 public Map<String,List<MethodDoc>> classToExecMemberDocReturnTypeParam = new HashMap<>(); 170 171 /** 172 * The mapping of AnnotationTypeDocs to MethodDoc parameters that use them. 173 */ 174 public Map<String,List<ExecutableMemberDoc>> classToExecMemberDocParamAnnotation = new HashMap<>(); 175 176 /** 177 * The mapping of ClassDocs to FieldDocs that use them as type parameters. 178 */ 179 public Map<String,List<FieldDoc>> classToFieldDocTypeParam = new HashMap<>(); 180 181 /** 182 * The mapping of AnnotationTypeDocs to FieldDocs that use them. 183 */ 184 public Map<String,List<FieldDoc>> annotationToFieldDoc = new HashMap<>(); 185 186 private final Utils utils; 187 public ClassUseMapper(ConfigurationImpl configuration, ClassTree classtree) { 188 RootDoc root = configuration.root; 189 this.classtree = classtree; 190 utils = configuration.utils; 191 // Map subclassing, subinterfacing implementing, ... 192 for (ClassDoc doc : classtree.baseclasses()) { 193 subclasses(doc); 194 } 195 for (ClassDoc doc : classtree.baseinterfaces()) { 196 // does subinterfacing as side-effect 197 implementingClasses(doc); 198 } 199 // Map methods, fields, constructors using a class. 200 ClassDoc[] classes = root.classes(); 201 for (ClassDoc aClass : classes) { 202 PackageDoc pkg = aClass.containingPackage(); 203 mapAnnotations(classToPackageAnnotations, pkg, pkg); 204 ClassDoc cd = aClass; 205 mapTypeParameters(classToClassTypeParam, cd, cd); 206 mapAnnotations(classToClassAnnotations, cd, cd); 207 FieldDoc[] fields = cd.fields(); 208 for (FieldDoc fd : fields) { 209 mapTypeParameters(classToFieldDocTypeParam, fd, fd); 210 mapAnnotations(annotationToFieldDoc, fd, fd); 211 if (!fd.type().isPrimitive()) { 212 add(classToField, fd.type().asClassDoc(), fd); 213 } 214 } 215 ConstructorDoc[] cons = cd.constructors(); 216 for (ConstructorDoc con : cons) { 217 mapAnnotations(classToConstructorAnnotations, con, con); 218 mapExecutable(con); 219 } 220 MethodDoc[] meths = cd.methods(); 221 for (MethodDoc md : meths) { 222 mapExecutable(md); 223 mapTypeParameters(classToExecMemberDocTypeParam, md, md); 224 mapAnnotations(classToExecMemberDocAnnotations, md, md); 225 if (!(md.returnType().isPrimitive() || md.returnType() instanceof TypeVariable)) { 226 mapTypeParameters(classToExecMemberDocReturnTypeParam, 227 md.returnType(), md); 228 add(classToMethodReturn, md.returnType().asClassDoc(), md); 229 } 230 } 231 } 232 } 233 234 /** 235 * Return all subclasses of a class AND fill-in classToSubclass map. 236 */ 237 private Collection<ClassDoc> subclasses(ClassDoc cd) { 238 Collection<ClassDoc> ret = classToSubclass.get(cd.qualifiedName()); 239 if (ret == null) { 240 ret = new TreeSet<>(utils.makeComparatorForClassUse()); 241 SortedSet<ClassDoc> subs = classtree.subclasses(cd); 242 if (subs != null) { 243 ret.addAll(subs); 244 for (ClassDoc sub : subs) { 245 ret.addAll(subclasses(sub)); 246 } 247 } 248 addAll(classToSubclass, cd, ret); 249 } 250 return ret; 251 } 252 253 /** 254 * Return all subinterfaces of an interface AND fill-in classToSubinterface map. 255 */ 256 private Collection<ClassDoc> subinterfaces(ClassDoc cd) { 257 Collection<ClassDoc> ret = classToSubinterface.get(cd.qualifiedName()); 258 if (ret == null) { 259 ret = new TreeSet<>(utils.makeComparatorForClassUse()); 260 SortedSet<ClassDoc> subs = classtree.subinterfaces(cd); 261 if (subs != null) { 262 ret.addAll(subs); 263 for (ClassDoc sub : subs) { 264 ret.addAll(subinterfaces(sub)); 265 } 266 } 267 addAll(classToSubinterface, cd, ret); 268 } 269 return ret; 270 } 271 272 /** 273 * Return all implementing classes of an interface (including 274 * all subclasses of implementing classes and all classes 275 * implementing subinterfaces) AND fill-in both classToImplementingClass 276 * and classToSubinterface maps. 277 */ 278 private Collection<ClassDoc> implementingClasses(ClassDoc cd) { 279 Collection<ClassDoc> ret = classToImplementingClass.get(cd.qualifiedName()); 280 if (ret == null) { 281 ret = new TreeSet<>(utils.makeComparatorForClassUse()); 282 SortedSet<ClassDoc> impl = classtree.implementingclasses(cd); 283 if (impl != null) { 284 ret.addAll(impl); 285 for (ClassDoc anImpl : impl) { 286 ret.addAll(subclasses(anImpl)); 287 } 288 } 289 for (ClassDoc doc : subinterfaces(cd)) { 290 ret.addAll(implementingClasses(doc)); 291 } 292 addAll(classToImplementingClass, cd, ret); 293 } 294 return ret; 295 } 296 297 /** 298 * Determine classes used by a method or constructor, so they can be 299 * inverse mapped. 300 */ 301 private void mapExecutable(ExecutableMemberDoc em) { 302 boolean isConstructor = em.isConstructor(); 303 Set<Type> classArgs = new TreeSet<>(utils.makeTypeComparator()); 304 for (Parameter param : em.parameters()) { 305 Type pcd = param.type(); 306 // ignore primitives and typevars, typevars are handled elsewhere 307 if ((!param.type().isPrimitive()) && !(pcd instanceof TypeVariable)) { 308 // avoid dups 309 if (classArgs.add(pcd)) { 310 add(isConstructor ? classToConstructorArgs : classToMethodArgs, 311 pcd.asClassDoc(), em); 312 mapTypeParameters(isConstructor 313 ? classToConstructorDocArgTypeParam 314 : classToExecMemberDocArgTypeParam, 315 pcd, em); 316 } 317 } 318 mapAnnotations(isConstructor 319 ? classToConstructorParamAnnotation 320 : classToExecMemberDocParamAnnotation, 321 param, em); 322 323 } 324 for (ClassDoc anException : em.thrownExceptions()) { 325 add(isConstructor ? classToConstructorThrows : classToMethodThrows, 326 anException, em); 327 } 328 } 329 330 private <T> List<T> refList(Map<String,List<T>> map, ClassDoc cd) { 331 List<T> list = map.get(cd.qualifiedName()); 332 if (list == null) { 333 list = new ArrayList<>(); 334 map.put(cd.qualifiedName(), list); 335 } 336 return list; 337 } 338 339 private Set<PackageDoc> packageSet(ClassDoc cd) { 340 Set<PackageDoc> pkgSet = classToPackage.get(cd.qualifiedName()); 341 if (pkgSet == null) { 342 pkgSet = new TreeSet<>(); 343 classToPackage.put(cd.qualifiedName(), pkgSet); 344 } 345 return pkgSet; 346 } 347 348 private Set<ClassDoc> classSet(ClassDoc cd) { 349 Set<ClassDoc> clsSet = classToClass.get(cd.qualifiedName()); 350 if (clsSet == null) { 351 clsSet = new TreeSet<>(); 352 classToClass.put(cd.qualifiedName(), clsSet); 353 } 354 return clsSet; 355 } 356 357 private <T extends ProgramElementDoc> void add(Map<String,List<T>> map, ClassDoc cd, T ref) { 358 // add to specified map 359 refList(map, cd).add(ref); 360 361 // add ref's package to package map and class map 362 packageSet(cd).add(ref.containingPackage()); 363 364 classSet(cd).add(ref instanceof MemberDoc? 365 ((MemberDoc)ref).containingClass() : 366 (ClassDoc)ref); 367 } 368 369 private void addAll(Map<String,List<ClassDoc>> map, ClassDoc cd, Collection<ClassDoc> refs) { 370 if (refs == null) { 371 return; 372 } 373 // add to specified map 374 refList(map, cd).addAll(refs); 375 376 Set<PackageDoc> pkgSet = packageSet(cd); 377 Set<ClassDoc> clsSet = classSet(cd); 378 // add ref's package to package map and class map 379 for (ClassDoc cls : refs) { 380 pkgSet.add(cls.containingPackage()); 381 clsSet.add(cls); 382 383 } 384 } 385 386 /** 387 * Map the ClassDocs to the ProgramElementDocs that use them as 388 * type parameters. 389 * 390 * @param map the map the insert the information into. 391 * @param doc the doc whose type parameters are being checked. 392 * @param holder the holder that owns the type parameters. 393 */ 394 private <T extends ProgramElementDoc> void mapTypeParameters(Map<String,List<T>> map, Object doc, 395 T holder) { 396 TypeVariable[] typeVariables; 397 if (doc instanceof ClassDoc) { 398 typeVariables = ((ClassDoc) doc).typeParameters(); 399 } else if (doc instanceof WildcardType) { 400 for (Type extendsBound : ((WildcardType) doc).extendsBounds()) { 401 addTypeParameterToMap(map, extendsBound, holder); 402 } 403 for (Type superBound : ((WildcardType) doc).superBounds()) { 404 addTypeParameterToMap(map, superBound, holder); 405 } 406 return; 407 } else if (doc instanceof ParameterizedType) { 408 for (Type typeArgument : ((ParameterizedType) doc).typeArguments()) { 409 addTypeParameterToMap(map, typeArgument, holder); 410 } 411 return; 412 } else if (doc instanceof ExecutableMemberDoc) { 413 typeVariables = ((ExecutableMemberDoc) doc).typeParameters(); 414 } else if (doc instanceof FieldDoc) { 415 Type fieldType = ((FieldDoc) doc).type(); 416 mapTypeParameters(map, fieldType, holder); 417 return; 418 } else { 419 return; 420 } 421 for (TypeVariable typeVariable : typeVariables) { 422 for (Type bound : typeVariable.bounds()) { 423 addTypeParameterToMap(map, bound, holder); 424 } 425 } 426 } 427 428 /** 429 * Map the AnnotationType to the ProgramElementDocs that use them as 430 * type parameters. 431 * 432 * @param map the map the insert the information into. 433 * @param doc the doc whose type parameters are being checked. 434 * @param holder the holder that owns the type parameters. 435 */ 436 private <T extends ProgramElementDoc> void mapAnnotations(Map<String,List<T>> map, Object doc, 437 T holder) { 438 AnnotationDesc[] annotations; 439 boolean isPackage = false; 440 if (doc instanceof ProgramElementDoc) { 441 annotations = ((ProgramElementDoc) doc).annotations(); 442 } else if (doc instanceof PackageDoc) { 443 annotations = ((PackageDoc) doc).annotations(); 444 isPackage = true; 445 } else if (doc instanceof Parameter) { 446 annotations = ((Parameter) doc).annotations(); 447 } else { 448 throw new DocletAbortException("should not happen"); 449 } 450 for (AnnotationDesc annotation : annotations) { 451 AnnotationTypeDoc annotationDoc = annotation.annotationType(); 452 if (isPackage) 453 refList(map, annotationDoc).add(holder); 454 else 455 add(map, annotationDoc, holder); 456 } 457 } 458 459 460 /** 461 * Map the AnnotationType to the ProgramElementDocs that use them as 462 * type parameters. 463 * 464 * @param map the map the insert the information into. 465 * @param doc the doc whose type parameters are being checked. 466 * @param holder the holder that owns the type parameters. 467 */ 468 private <T extends PackageDoc> void mapAnnotations(Map<String,List<T>> map, PackageDoc doc, 469 T holder) { 470 for (AnnotationDesc annotation : doc.annotations()) { 471 AnnotationTypeDoc annotationDoc = annotation.annotationType(); 472 refList(map, annotationDoc).add(holder); 473 } 474 } 475 476 private <T extends ProgramElementDoc> void addTypeParameterToMap(Map<String,List<T>> map, Type type, 477 T holder) { 478 if (type instanceof ClassDoc) { 479 add(map, (ClassDoc) type, holder); 480 } else if (type instanceof ParameterizedType) { 481 add(map, ((ParameterizedType) type).asClassDoc(), holder); 482 } 483 mapTypeParameters(map, type, holder); 484 } 485} 486