1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.doclava; 18 19 20 import com.sun.javadoc.AnnotationDesc; 21 import com.sun.javadoc.AnnotationTypeDoc; 22 import com.sun.javadoc.AnnotationTypeElementDoc; 23 import com.sun.javadoc.AnnotationValue; 24 import com.sun.javadoc.ClassDoc; 25 import com.sun.javadoc.ConstructorDoc; 26 import com.sun.javadoc.ExecutableMemberDoc; 27 import com.sun.javadoc.FieldDoc; 28 import com.sun.javadoc.MemberDoc; 29 import com.sun.javadoc.MethodDoc; 30 import com.sun.javadoc.PackageDoc; 31 import com.sun.javadoc.ParamTag; 32 import com.sun.javadoc.Parameter; 33 import com.sun.javadoc.RootDoc; 34 import com.sun.javadoc.SeeTag; 35 import com.sun.javadoc.SourcePosition; 36 import com.sun.javadoc.Tag; 37 import com.sun.javadoc.ThrowsTag; 38 import com.sun.javadoc.Type; 39 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.HashMap; 43 import java.util.HashSet; 44 import java.util.List; 45 46 public class Converter { 47 private static RootDoc root; 48 makeInfo(RootDoc r)49 public static void makeInfo(RootDoc r) { 50 root = r; 51 52 // create the objects 53 ClassDoc[] classes = getClasses(r); 54 for (ClassDoc c : classes) { 55 Converter.obtainClass(c); 56 } 57 58 ArrayList<ClassInfo> classesNeedingInit2 = new ArrayList<ClassInfo>(); 59 60 int i; 61 // fill in the fields that reference other classes 62 while (mClassesNeedingInit.size() > 0) { 63 i = mClassesNeedingInit.size() - 1; 64 ClassNeedingInit clni = mClassesNeedingInit.get(i); 65 mClassesNeedingInit.remove(i); 66 67 initClass(clni.c, clni.cl); 68 classesNeedingInit2.add(clni.cl); 69 } 70 mClassesNeedingInit = null; 71 for (ClassInfo cl : classesNeedingInit2) { 72 cl.init2(); 73 } 74 75 finishAnnotationValueInit(); 76 77 // fill in the "root" stuff 78 mRootClasses = Converter.convertClasses(classes); 79 } 80 getClasses(RootDoc r)81 private static ClassDoc[] getClasses(RootDoc r) { 82 ClassDoc[] classDocs = r.classes(); 83 ArrayList<ClassDoc> filtered = new ArrayList<ClassDoc>(classDocs.length); 84 for (ClassDoc c : classDocs) { 85 if (c.position() != null) { 86 // Work around a javadoc bug in Java 7: We sometimes spuriously 87 // receive duplicate top level ClassDocs with null positions and no type 88 // information. Ignore them, since every ClassDoc must have a non null 89 // position. 90 91 filtered.add(c); 92 } 93 } 94 95 ClassDoc[] filteredArray = new ClassDoc[filtered.size()]; 96 filtered.toArray(filteredArray); 97 return filteredArray; 98 } 99 100 private static ClassInfo[] mRootClasses; 101 rootClasses()102 public static ClassInfo[] rootClasses() { 103 return mRootClasses; 104 } 105 allClasses()106 public static ClassInfo[] allClasses() { 107 return (ClassInfo[]) mClasses.all(); 108 } 109 initClass(ClassDoc c, ClassInfo cl)110 private static void initClass(ClassDoc c, ClassInfo cl) { 111 MethodDoc[] annotationElements; 112 if (c instanceof AnnotationTypeDoc) { 113 annotationElements = ((AnnotationTypeDoc) c).elements(); 114 } else { 115 annotationElements = new MethodDoc[0]; 116 } 117 cl.init(Converter.obtainType(c), 118 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.interfaces()))), 119 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.interfaceTypes()))), 120 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.innerClasses()))), 121 new ArrayList<MethodInfo>(Arrays.asList( 122 Converter.convertMethods(c.constructors(false)))), 123 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(c.methods(false)))), 124 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(annotationElements))), 125 new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.fields(false)))), 126 new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.enumConstants()))), 127 Converter.obtainPackage(c.containingPackage()), 128 Converter.obtainClass(c.containingClass()), 129 Converter.obtainClass(c.superclass()), Converter.obtainType(c.superclassType()), 130 new ArrayList<AnnotationInstanceInfo>(Arrays.asList( 131 Converter.convertAnnotationInstances(c.annotations())))); 132 133 cl.setHiddenMethods( 134 new ArrayList<MethodInfo>(Arrays.asList(Converter.getHiddenMethods(c.methods(false))))); 135 cl.setRemovedMethods( 136 new ArrayList<MethodInfo>(Arrays.asList(Converter.getRemovedMethods(c.methods(false))))); 137 138 cl.setRemovedSelfMethods( 139 new ArrayList<MethodInfo>(Converter.convertAllMethods(c.methods(false)))); 140 cl.setRemovedConstructors( 141 new ArrayList<MethodInfo>(Converter.convertAllMethods(c.constructors(false)))); 142 cl.setRemovedSelfFields( 143 new ArrayList<FieldInfo>(Converter.convertAllFields(c.fields(false)))); 144 cl.setRemovedEnumConstants( 145 new ArrayList<FieldInfo>(Converter.convertAllFields(c.enumConstants()))); 146 147 cl.setNonWrittenConstructors( 148 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertNonWrittenConstructors( 149 c.constructors(false))))); 150 cl.init3( 151 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.typeParameters()))), 152 new ArrayList<ClassInfo>(Arrays.asList( 153 Converter.convertClasses(c.innerClasses(false))))); 154 } 155 obtainClass(String className)156 public static ClassInfo obtainClass(String className) { 157 return Converter.obtainClass(root.classNamed(className)); 158 } 159 obtainPackage(String packageName)160 public static PackageInfo obtainPackage(String packageName) { 161 return Converter.obtainPackage(root.packageNamed(packageName)); 162 } 163 convertTag(Tag tag)164 private static TagInfo convertTag(Tag tag) { 165 return new TextTagInfo(tag.name(), tag.kind(), tag.text(), 166 Converter.convertSourcePosition(tag.position())); 167 } 168 convertThrowsTag(ThrowsTag tag, ContainerInfo base)169 private static ThrowsTagInfo convertThrowsTag(ThrowsTag tag, ContainerInfo base) { 170 return new ThrowsTagInfo(tag.name(), tag.text(), tag.kind(), Converter.obtainClass(tag 171 .exception()), tag.exceptionComment(), base, Converter 172 .convertSourcePosition(tag.position())); 173 } 174 convertParamTag(ParamTag tag, ContainerInfo base)175 private static ParamTagInfo convertParamTag(ParamTag tag, ContainerInfo base) { 176 return new ParamTagInfo(tag.name(), tag.kind(), tag.text(), tag.isTypeParameter(), tag 177 .parameterComment(), tag.parameterName(), base, Converter.convertSourcePosition(tag 178 .position())); 179 } 180 convertSeeTag(SeeTag tag, ContainerInfo base)181 private static SeeTagInfo convertSeeTag(SeeTag tag, ContainerInfo base) { 182 return new SeeTagInfo(tag.name(), tag.kind(), tag.text(), base, Converter 183 .convertSourcePosition(tag.position())); 184 } 185 convertSourcePosition(SourcePosition sp)186 private static SourcePositionInfo convertSourcePosition(SourcePosition sp) { 187 if (sp == null) { 188 return null; 189 } 190 return new SourcePositionInfo(sp.file().toString(), sp.line(), sp.column()); 191 } 192 convertTags(Tag[] tags, ContainerInfo base)193 public static TagInfo[] convertTags(Tag[] tags, ContainerInfo base) { 194 int len = tags.length; 195 TagInfo[] out = new TagInfo[len]; 196 for (int i = 0; i < len; i++) { 197 Tag t = tags[i]; 198 /* 199 * System.out.println("Tag name='" + t.name() + "' kind='" + t.kind() + "'"); 200 */ 201 if (t instanceof SeeTag) { 202 out[i] = Converter.convertSeeTag((SeeTag) t, base); 203 } else if (t instanceof ThrowsTag) { 204 out[i] = Converter.convertThrowsTag((ThrowsTag) t, base); 205 } else if (t instanceof ParamTag) { 206 out[i] = Converter.convertParamTag((ParamTag) t, base); 207 } else { 208 out[i] = Converter.convertTag(t); 209 } 210 } 211 return out; 212 } 213 convertClasses(ClassDoc[] classes)214 public static ClassInfo[] convertClasses(ClassDoc[] classes) { 215 if (classes == null) return null; 216 int N = classes.length; 217 ClassInfo[] result = new ClassInfo[N]; 218 for (int i = 0; i < N; i++) { 219 result[i] = Converter.obtainClass(classes[i]); 220 } 221 return result; 222 } 223 convertParameter(Parameter p, SourcePosition pos, boolean isVarArg)224 private static ParameterInfo convertParameter(Parameter p, SourcePosition pos, boolean isVarArg) { 225 if (p == null) return null; 226 ParameterInfo pi = 227 new ParameterInfo(p.name(), p.typeName(), Converter.obtainType(p.type()), isVarArg, 228 Converter.convertSourcePosition(pos)); 229 return pi; 230 } 231 convertParameters(Parameter[] p, ExecutableMemberDoc m)232 private static ParameterInfo[] convertParameters(Parameter[] p, ExecutableMemberDoc m) { 233 SourcePosition pos = m.position(); 234 int len = p.length; 235 ParameterInfo[] q = new ParameterInfo[len]; 236 for (int i = 0; i < len; i++) { 237 boolean isVarArg = (m.isVarArgs() && i == len - 1); 238 q[i] = Converter.convertParameter(p[i], pos, isVarArg); 239 } 240 return q; 241 } 242 convertTypes(Type[] p)243 private static TypeInfo[] convertTypes(Type[] p) { 244 if (p == null) return null; 245 int len = p.length; 246 TypeInfo[] q = new TypeInfo[len]; 247 for (int i = 0; i < len; i++) { 248 q[i] = Converter.obtainType(p[i]); 249 } 250 return q; 251 } 252 Converter()253 private Converter() {} 254 255 private static class ClassNeedingInit { ClassNeedingInit(ClassDoc c, ClassInfo cl)256 ClassNeedingInit(ClassDoc c, ClassInfo cl) { 257 this.c = c; 258 this.cl = cl; 259 } 260 261 ClassDoc c; 262 ClassInfo cl; 263 } 264 265 private static ArrayList<ClassNeedingInit> mClassesNeedingInit = 266 new ArrayList<ClassNeedingInit>(); 267 obtainClass(ClassDoc o)268 static ClassInfo obtainClass(ClassDoc o) { 269 return (ClassInfo) mClasses.obtain(o); 270 } 271 272 private static Cache mClasses = new Cache() { 273 @Override 274 protected Object make(Object o) { 275 ClassDoc c = (ClassDoc) o; 276 ClassInfo cl = 277 new ClassInfo(c, c.getRawCommentText(), Converter.convertSourcePosition(c.position()), c 278 .isPublic(), c.isProtected(), c.isPackagePrivate(), c.isPrivate(), c.isStatic(), c 279 .isInterface(), c.isAbstract(), c.isOrdinaryClass(), c.isException(), c.isError(), c 280 .isEnum(), (c instanceof AnnotationTypeDoc), c.isFinal(), c.isIncluded(), c.name(), c 281 .qualifiedName(), c.qualifiedTypeName(), c.isPrimitive()); 282 if (mClassesNeedingInit != null) { 283 mClassesNeedingInit.add(new ClassNeedingInit(c, cl)); 284 } 285 return cl; 286 } 287 288 @Override 289 protected void made(Object o, Object r) { 290 if (mClassesNeedingInit == null) { 291 initClass((ClassDoc) o, (ClassInfo) r); 292 ((ClassInfo) r).init2(); 293 } 294 } 295 296 @Override 297 ClassInfo[] all() { 298 return mCache.values().toArray(new ClassInfo[mCache.size()]); 299 } 300 }; 301 getHiddenMethods(MethodDoc[] methods)302 private static MethodInfo[] getHiddenMethods(MethodDoc[] methods) { 303 if (methods == null) return null; 304 ArrayList<MethodInfo> hiddenMethods = new ArrayList<MethodInfo>(); 305 for (MethodDoc method : methods) { 306 MethodInfo methodInfo = Converter.obtainMethod(method); 307 if (methodInfo.isHidden()) { 308 hiddenMethods.add(methodInfo); 309 } 310 } 311 312 return hiddenMethods.toArray(new MethodInfo[hiddenMethods.size()]); 313 } 314 315 // Gets the removed methods regardless of access levels getRemovedMethods(MethodDoc[] methods)316 private static MethodInfo[] getRemovedMethods(MethodDoc[] methods) { 317 if (methods == null) return null; 318 ArrayList<MethodInfo> removedMethods = new ArrayList<MethodInfo>(); 319 for (MethodDoc method : methods) { 320 MethodInfo methodInfo = Converter.obtainMethod(method); 321 if (methodInfo.isRemoved()) { 322 removedMethods.add(methodInfo); 323 } 324 } 325 326 return removedMethods.toArray(new MethodInfo[removedMethods.size()]); 327 } 328 329 /** 330 * Converts FieldDoc[] into List<FieldInfo>. No filtering is done. 331 */ convertAllFields(FieldDoc[] fields)332 private static List<FieldInfo> convertAllFields(FieldDoc[] fields) { 333 if (fields == null) return null; 334 List<FieldInfo> allFields = new ArrayList<FieldInfo>(); 335 336 for (FieldDoc field : fields) { 337 FieldInfo fieldInfo = Converter.obtainField(field); 338 allFields.add(fieldInfo); 339 } 340 341 return allFields; 342 } 343 344 /** 345 * Converts ExecutableMemberDoc[] into List<MethodInfo>. No filtering is done. 346 */ convertAllMethods(ExecutableMemberDoc[] methods)347 private static List<MethodInfo> convertAllMethods(ExecutableMemberDoc[] methods) { 348 if (methods == null) return null; 349 List<MethodInfo> allMethods = new ArrayList<MethodInfo>(); 350 for (ExecutableMemberDoc method : methods) { 351 MethodInfo methodInfo = Converter.obtainMethod(method); 352 allMethods.add(methodInfo); 353 } 354 return allMethods; 355 } 356 357 /** 358 * Convert MethodDoc[] or ConstructorDoc[] into MethodInfo[]. 359 * Also filters according to the -private, -public option, 360 * because the filtering doesn't seem to be working in the ClassDoc.constructors(boolean) call. 361 */ convertMethods(ExecutableMemberDoc[] methods)362 private static MethodInfo[] convertMethods(ExecutableMemberDoc[] methods) { 363 if (methods == null) return null; 364 List<MethodInfo> filteredMethods = new ArrayList<MethodInfo>(); 365 for (ExecutableMemberDoc method : methods) { 366 MethodInfo methodInfo = Converter.obtainMethod(method); 367 if (methodInfo.checkLevel()) { 368 filteredMethods.add(methodInfo); 369 } 370 } 371 372 return filteredMethods.toArray(new MethodInfo[filteredMethods.size()]); 373 } 374 convertNonWrittenConstructors(ConstructorDoc[] methods)375 private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods) { 376 if (methods == null) return null; 377 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>(); 378 for (ConstructorDoc method : methods) { 379 MethodInfo methodInfo = Converter.obtainMethod(method); 380 if (!methodInfo.checkLevel()) { 381 ctors.add(methodInfo); 382 } 383 } 384 385 return ctors.toArray(new MethodInfo[ctors.size()]); 386 } 387 obtainMethod(E o)388 private static <E extends ExecutableMemberDoc> MethodInfo obtainMethod(E o) { 389 return (MethodInfo) mMethods.obtain(o); 390 } 391 392 private static Cache mMethods = new Cache() { 393 @Override 394 protected Object make(Object o) { 395 if (o instanceof AnnotationTypeElementDoc) { 396 AnnotationTypeElementDoc m = (AnnotationTypeElementDoc) o; 397 MethodInfo result = 398 new MethodInfo(m.getRawCommentText(), 399 new ArrayList<TypeInfo>(Arrays.asList( 400 Converter.convertTypes(m.typeParameters()))), 401 m.name(), m.signature(), Converter.obtainClass(m.containingClass()), 402 Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m 403 .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(), 404 m.isAbstract(), m.isSynchronized(), m.isNative(), true, "annotationElement", 405 m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()), 406 Converter.obtainType(m.returnType()), 407 new ArrayList<ParameterInfo>(Arrays.asList( 408 Converter.convertParameters(m.parameters(), m))), 409 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses( 410 m.thrownExceptions()))), Converter.convertSourcePosition(m.position()), 411 new ArrayList<AnnotationInstanceInfo>(Arrays.asList( 412 Converter.convertAnnotationInstances(m.annotations())))); 413 result.setVarargs(m.isVarArgs()); 414 result.init(Converter.obtainAnnotationValue(m.defaultValue(), result)); 415 return result; 416 } else if (o instanceof MethodDoc) { 417 MethodDoc m = (MethodDoc) o; 418 MethodInfo result = 419 new MethodInfo(m.getRawCommentText(), 420 new ArrayList<TypeInfo>(Arrays.asList( 421 Converter.convertTypes(m.typeParameters()))), m.name(), m.signature(), 422 Converter.obtainClass(m.containingClass()), 423 Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), 424 m.isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(), 425 m.isAbstract(), m.isSynchronized(), m.isNative(), false, "method", 426 m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()), 427 Converter.obtainType(m.returnType()), 428 new ArrayList<ParameterInfo>(Arrays.asList( 429 Converter.convertParameters(m.parameters(), m))), 430 new ArrayList<ClassInfo>(Arrays.asList( 431 Converter.convertClasses(m.thrownExceptions()))), 432 Converter.convertSourcePosition(m.position()), 433 new ArrayList<AnnotationInstanceInfo>(Arrays.asList( 434 Converter.convertAnnotationInstances(m.annotations())))); 435 result.setVarargs(m.isVarArgs()); 436 result.init(null); 437 return result; 438 } else { 439 ConstructorDoc m = (ConstructorDoc) o; 440 MethodInfo result = 441 new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), m 442 .name(), m.signature(), Converter.obtainClass(m.containingClass()), Converter 443 .obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m 444 .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(), 445 false, m.isSynchronized(), m.isNative(), false, "constructor", m.flatSignature(), 446 null, null, new ArrayList<ParameterInfo>(Arrays.asList(Converter.convertParameters(m.parameters(), m))), 447 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(m.thrownExceptions()))), Converter.convertSourcePosition(m 448 .position()), new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter.convertAnnotationInstances(m.annotations())))); 449 result.setVarargs(m.isVarArgs()); 450 result.init(null); 451 return result; 452 } 453 } 454 }; 455 456 convertFields(FieldDoc[] fields)457 private static FieldInfo[] convertFields(FieldDoc[] fields) { 458 if (fields == null) return null; 459 ArrayList<FieldInfo> out = new ArrayList<FieldInfo>(); 460 int N = fields.length; 461 for (int i = 0; i < N; i++) { 462 FieldInfo f = Converter.obtainField(fields[i]); 463 if (f.checkLevel()) { 464 out.add(f); 465 } 466 } 467 return out.toArray(new FieldInfo[out.size()]); 468 } 469 obtainField(FieldDoc o)470 private static FieldInfo obtainField(FieldDoc o) { 471 return (FieldInfo) mFields.obtain(o); 472 } 473 obtainField(ConstructorDoc o)474 private static FieldInfo obtainField(ConstructorDoc o) { 475 return (FieldInfo) mFields.obtain(o); 476 } 477 478 private static Cache mFields = new Cache() { 479 @Override 480 protected Object make(Object o) { 481 FieldDoc f = (FieldDoc) o; 482 return new FieldInfo(f.name(), Converter.obtainClass(f.containingClass()), Converter 483 .obtainClass(f.containingClass()), f.isPublic(), f.isProtected(), f.isPackagePrivate(), f 484 .isPrivate(), f.isFinal(), f.isStatic(), f.isTransient(), f.isVolatile(), 485 f.isSynthetic(), Converter.obtainType(f.type()), f.getRawCommentText(), 486 f.constantValue(), Converter.convertSourcePosition(f.position()), 487 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter 488 .convertAnnotationInstances(f.annotations())))); 489 } 490 }; 491 obtainPackage(PackageDoc o)492 private static PackageInfo obtainPackage(PackageDoc o) { 493 return (PackageInfo) mPackagees.obtain(o); 494 } 495 496 private static Cache mPackagees = new Cache() { 497 @Override 498 protected Object make(Object o) { 499 PackageDoc p = (PackageDoc) o; 500 return new PackageInfo(p, p.name(), Converter.convertSourcePosition(p.position())); 501 } 502 }; 503 obtainType(Type o)504 private static TypeInfo obtainType(Type o) { 505 return (TypeInfo) mTypes.obtain(o); 506 } 507 508 private static Cache mTypes = new Cache() { 509 @Override 510 protected Object make(Object o) { 511 Type t = (Type) o; 512 String simpleTypeName; 513 if (t instanceof ClassDoc) { 514 simpleTypeName = ((ClassDoc) t).name(); 515 } else { 516 simpleTypeName = t.simpleTypeName(); 517 } 518 TypeInfo ti = 519 new TypeInfo(t.isPrimitive(), t.dimension(), simpleTypeName, t.qualifiedTypeName(), 520 Converter.obtainClass(t.asClassDoc())); 521 return ti; 522 } 523 524 @Override 525 protected void made(Object o, Object r) { 526 Type t = (Type) o; 527 TypeInfo ti = (TypeInfo) r; 528 if (t.asParameterizedType() != null) { 529 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asParameterizedType().typeArguments())))); 530 } else if (t instanceof ClassDoc) { 531 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(((ClassDoc) t).typeParameters())))); 532 } else if (t.asTypeVariable() != null) { 533 ti.setBounds(null, new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes((t.asTypeVariable().bounds()))))); 534 ti.setIsTypeVariable(true); 535 } else if (t.asWildcardType() != null) { 536 ti.setIsWildcard(true); 537 ti.setBounds(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().superBounds()))), 538 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().extendsBounds())))); 539 } 540 } 541 542 @Override 543 protected Object keyFor(Object o) { 544 Type t = (Type) o; 545 String keyString = o.getClass().getName() + "/" + o.toString() + "/"; 546 if (t.asParameterizedType() != null) { 547 keyString += t.asParameterizedType().toString() + "/"; 548 if (t.asParameterizedType().typeArguments() != null) { 549 for (Type ty : t.asParameterizedType().typeArguments()) { 550 keyString += ty.toString() + "/"; 551 } 552 } 553 } else { 554 keyString += "NoParameterizedType//"; 555 } 556 if (t.asTypeVariable() != null) { 557 keyString += t.asTypeVariable().toString() + "/"; 558 if (t.asTypeVariable().bounds() != null) { 559 for (Type ty : t.asTypeVariable().bounds()) { 560 keyString += ty.toString() + "/"; 561 } 562 } 563 } else { 564 keyString += "NoTypeVariable//"; 565 } 566 if (t.asWildcardType() != null) { 567 keyString += t.asWildcardType().toString() + "/"; 568 if (t.asWildcardType().superBounds() != null) { 569 for (Type ty : t.asWildcardType().superBounds()) { 570 keyString += ty.toString() + "/"; 571 } 572 } 573 if (t.asWildcardType().extendsBounds() != null) { 574 for (Type ty : t.asWildcardType().extendsBounds()) { 575 keyString += ty.toString() + "/"; 576 } 577 } 578 } else { 579 keyString += "NoWildCardType//"; 580 } 581 582 return keyString; 583 } 584 }; 585 obtainTypeFromString(String type)586 public static TypeInfo obtainTypeFromString(String type) { 587 return (TypeInfo) mTypesFromString.obtain(type); 588 } 589 590 private static final Cache mTypesFromString = new Cache() { 591 @Override 592 protected Object make(Object o) { 593 String name = (String) o; 594 return new TypeInfo(name); 595 } 596 597 @Override 598 protected void made(Object o, Object r) { 599 600 } 601 602 @Override 603 protected Object keyFor(Object o) { 604 return o; 605 } 606 }; 607 obtainMember(MemberDoc o)608 private static MemberInfo obtainMember(MemberDoc o) { 609 return (MemberInfo) mMembers.obtain(o); 610 } 611 612 private static Cache mMembers = new Cache() { 613 @Override 614 protected Object make(Object o) { 615 if (o instanceof MethodDoc) { 616 return Converter.obtainMethod((MethodDoc) o); 617 } else if (o instanceof ConstructorDoc) { 618 return Converter.obtainMethod((ConstructorDoc) o); 619 } else if (o instanceof FieldDoc) { 620 return Converter.obtainField((FieldDoc) o); 621 } else { 622 return null; 623 } 624 } 625 }; 626 convertAnnotationInstances(AnnotationDesc[] orig)627 private static AnnotationInstanceInfo[] convertAnnotationInstances(AnnotationDesc[] orig) { 628 int len = orig.length; 629 AnnotationInstanceInfo[] out = new AnnotationInstanceInfo[len]; 630 for (int i = 0; i < len; i++) { 631 out[i] = Converter.obtainAnnotationInstance(orig[i]); 632 } 633 return out; 634 } 635 636 obtainAnnotationInstance(AnnotationDesc o)637 private static AnnotationInstanceInfo obtainAnnotationInstance(AnnotationDesc o) { 638 return (AnnotationInstanceInfo) mAnnotationInstances.obtain(o); 639 } 640 641 private static Cache mAnnotationInstances = new Cache() { 642 @Override 643 protected Object make(Object o) { 644 AnnotationDesc a = (AnnotationDesc) o; 645 ClassInfo annotationType = Converter.obtainClass(a.annotationType()); 646 AnnotationDesc.ElementValuePair[] ev = a.elementValues(); 647 AnnotationValueInfo[] elementValues = new AnnotationValueInfo[ev.length]; 648 for (int i = 0; i < ev.length; i++) { 649 elementValues[i] = 650 obtainAnnotationValue(ev[i].value(), Converter.obtainMethod(ev[i].element())); 651 } 652 return new AnnotationInstanceInfo(annotationType, elementValues); 653 } 654 }; 655 656 657 private abstract static class Cache { put(Object key, Object value)658 void put(Object key, Object value) { 659 mCache.put(key, value); 660 } 661 obtain(Object o)662 Object obtain(Object o) { 663 if (o == null) { 664 return null; 665 } 666 Object k = keyFor(o); 667 Object r = mCache.get(k); 668 if (r == null) { 669 r = make(o); 670 mCache.put(k, r); 671 made(o, r); 672 } 673 return r; 674 } 675 676 protected HashMap<Object, Object> mCache = new HashMap<Object, Object>(); 677 make(Object o)678 protected abstract Object make(Object o); 679 made(Object o, Object r)680 protected void made(Object o, Object r) {} 681 keyFor(Object o)682 protected Object keyFor(Object o) { 683 return o; 684 } 685 all()686 Object[] all() { 687 return null; 688 } 689 } 690 691 // annotation values 692 private static HashMap<AnnotationValue, AnnotationValueInfo> mAnnotationValues = 693 new HashMap<AnnotationValue, AnnotationValueInfo>(); 694 private static HashSet<AnnotationValue> mAnnotationValuesNeedingInit = 695 new HashSet<AnnotationValue>(); 696 obtainAnnotationValue(AnnotationValue o, MethodInfo element)697 private static AnnotationValueInfo obtainAnnotationValue(AnnotationValue o, MethodInfo element) { 698 if (o == null) { 699 return null; 700 } 701 AnnotationValueInfo v = mAnnotationValues.get(o); 702 if (v != null) return v; 703 v = new AnnotationValueInfo(element); 704 mAnnotationValues.put(o, v); 705 if (mAnnotationValuesNeedingInit != null) { 706 mAnnotationValuesNeedingInit.add(o); 707 } else { 708 initAnnotationValue(o, v); 709 } 710 return v; 711 } 712 initAnnotationValue(AnnotationValue o, AnnotationValueInfo v)713 private static void initAnnotationValue(AnnotationValue o, AnnotationValueInfo v) { 714 Object orig = o.value(); 715 Object converted; 716 if (orig instanceof Type) { 717 // class literal 718 converted = Converter.obtainType((Type) orig); 719 } else if (orig instanceof FieldDoc) { 720 // enum constant 721 converted = Converter.obtainField((FieldDoc) orig); 722 } else if (orig instanceof AnnotationDesc) { 723 // annotation instance 724 converted = Converter.obtainAnnotationInstance((AnnotationDesc) orig); 725 } else if (orig instanceof AnnotationValue[]) { 726 AnnotationValue[] old = (AnnotationValue[]) orig; 727 ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>(); 728 for (int i = 0; i < old.length; i++) { 729 values.add(Converter.obtainAnnotationValue(old[i], null)); 730 } 731 converted = values; 732 } else { 733 converted = orig; 734 } 735 v.init(converted); 736 } 737 finishAnnotationValueInit()738 private static void finishAnnotationValueInit() { 739 int depth = 0; 740 while (mAnnotationValuesNeedingInit.size() > 0) { 741 HashSet<AnnotationValue> set = mAnnotationValuesNeedingInit; 742 mAnnotationValuesNeedingInit = new HashSet<AnnotationValue>(); 743 for (AnnotationValue o : set) { 744 AnnotationValueInfo v = mAnnotationValues.get(o); 745 initAnnotationValue(o, v); 746 } 747 depth++; 748 } 749 mAnnotationValuesNeedingInit = null; 750 } 751 } 752