blob: 3153b4164c6033715161d8b151e1ee0d57c7058b [file] [log] [blame]
Ben Dodson920dbbb2010-08-04 15:21:06 -07001/*
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
17package com.google.doclava;
18
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010019
20import com.sun.javadoc.AnnotationDesc;
21import com.sun.javadoc.AnnotationTypeDoc;
22import com.sun.javadoc.AnnotationTypeElementDoc;
23import com.sun.javadoc.AnnotationValue;
24import com.sun.javadoc.ClassDoc;
25import com.sun.javadoc.ConstructorDoc;
26import com.sun.javadoc.ExecutableMemberDoc;
27import com.sun.javadoc.FieldDoc;
28import com.sun.javadoc.MemberDoc;
29import com.sun.javadoc.MethodDoc;
30import com.sun.javadoc.PackageDoc;
31import com.sun.javadoc.ParamTag;
32import com.sun.javadoc.Parameter;
33import com.sun.javadoc.RootDoc;
34import com.sun.javadoc.SeeTag;
35import com.sun.javadoc.SourcePosition;
36import com.sun.javadoc.Tag;
37import com.sun.javadoc.ThrowsTag;
38import com.sun.javadoc.Type;
39
Ben Dodson920dbbb2010-08-04 15:21:06 -070040import java.util.ArrayList;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -070041import java.util.Arrays;
Ben Dodson920dbbb2010-08-04 15:21:06 -070042import java.util.HashMap;
43import java.util.HashSet;
Hui Shu5118ffe2014-02-18 14:06:42 -080044import java.util.List;
Ben Dodson920dbbb2010-08-04 15:21:06 -070045
46public class Converter {
47 private static RootDoc root;
48
49 public static void makeInfo(RootDoc r) {
50 root = r;
51
Ben Dodson920dbbb2010-08-04 15:21:06 -070052 // create the objects
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010053 ClassDoc[] classes = getClasses(r);
54 for (ClassDoc c : classes) {
55 Converter.obtainClass(c);
Ben Dodson920dbbb2010-08-04 15:21:06 -070056 }
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010057
Ben Dodson920dbbb2010-08-04 15:21:06 -070058 ArrayList<ClassInfo> classesNeedingInit2 = new ArrayList<ClassInfo>();
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010059
60 int i;
Ben Dodson920dbbb2010-08-04 15:21:06 -070061 // 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
Narayan Kamathb1b0ee72013-10-24 15:57:08 +010078 mRootClasses = Converter.convertClasses(classes);
79 }
80
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;
Ben Dodson920dbbb2010-08-04 15:21:06 -070098 }
99
100 private static ClassInfo[] mRootClasses;
101
102 public static ClassInfo[] rootClasses() {
103 return mRootClasses;
104 }
105
106 public static ClassInfo[] allClasses() {
107 return (ClassInfo[]) mClasses.all();
108 }
109
C. Sean Youngda4b2e22015-05-18 14:12:30 -0500110 private static final MethodDoc[] EMPTY_METHOD_DOC = new MethodDoc[0];
111
Ben Dodson920dbbb2010-08-04 15:21:06 -0700112 private static void initClass(ClassDoc c, ClassInfo cl) {
113 MethodDoc[] annotationElements;
114 if (c instanceof AnnotationTypeDoc) {
115 annotationElements = ((AnnotationTypeDoc) c).elements();
116 } else {
C. Sean Youngda4b2e22015-05-18 14:12:30 -0500117 annotationElements = EMPTY_METHOD_DOC;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700118 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700119 cl.init(Converter.obtainType(c),
120 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.interfaces()))),
121 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.interfaceTypes()))),
122 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(c.innerClasses()))),
123 new ArrayList<MethodInfo>(Arrays.asList(
124 Converter.convertMethods(c.constructors(false)))),
125 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(c.methods(false)))),
126 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertMethods(annotationElements))),
127 new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.fields(false)))),
128 new ArrayList<FieldInfo>(Arrays.asList(Converter.convertFields(c.enumConstants()))),
129 Converter.obtainPackage(c.containingPackage()),
130 Converter.obtainClass(c.containingClass()),
131 Converter.obtainClass(c.superclass()), Converter.obtainType(c.superclassType()),
132 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
133 Converter.convertAnnotationInstances(c.annotations()))));
134
135 cl.setHiddenMethods(
136 new ArrayList<MethodInfo>(Arrays.asList(Converter.getHiddenMethods(c.methods(false)))));
Hui Shu5118ffe2014-02-18 14:06:42 -0800137 cl.setRemovedMethods(
138 new ArrayList<MethodInfo>(Arrays.asList(Converter.getRemovedMethods(c.methods(false)))));
139
140 cl.setRemovedSelfMethods(
141 new ArrayList<MethodInfo>(Converter.convertAllMethods(c.methods(false))));
142 cl.setRemovedConstructors(
143 new ArrayList<MethodInfo>(Converter.convertAllMethods(c.constructors(false))));
144 cl.setRemovedSelfFields(
145 new ArrayList<FieldInfo>(Converter.convertAllFields(c.fields(false))));
146 cl.setRemovedEnumConstants(
147 new ArrayList<FieldInfo>(Converter.convertAllFields(c.enumConstants())));
148
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700149 cl.setNonWrittenConstructors(
150 new ArrayList<MethodInfo>(Arrays.asList(Converter.convertNonWrittenConstructors(
151 c.constructors(false)))));
152 cl.init3(
153 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(c.typeParameters()))),
154 new ArrayList<ClassInfo>(Arrays.asList(
155 Converter.convertClasses(c.innerClasses(false)))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700156 }
157
158 public static ClassInfo obtainClass(String className) {
159 return Converter.obtainClass(root.classNamed(className));
160 }
161
162 public static PackageInfo obtainPackage(String packageName) {
163 return Converter.obtainPackage(root.packageNamed(packageName));
164 }
165
166 private static TagInfo convertTag(Tag tag) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700167 return new TextTagInfo(tag.name(), tag.kind(), tag.text(),
168 Converter.convertSourcePosition(tag.position()));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700169 }
170
171 private static ThrowsTagInfo convertThrowsTag(ThrowsTag tag, ContainerInfo base) {
172 return new ThrowsTagInfo(tag.name(), tag.text(), tag.kind(), Converter.obtainClass(tag
173 .exception()), tag.exceptionComment(), base, Converter
174 .convertSourcePosition(tag.position()));
175 }
176
177 private static ParamTagInfo convertParamTag(ParamTag tag, ContainerInfo base) {
178 return new ParamTagInfo(tag.name(), tag.kind(), tag.text(), tag.isTypeParameter(), tag
179 .parameterComment(), tag.parameterName(), base, Converter.convertSourcePosition(tag
180 .position()));
181 }
182
183 private static SeeTagInfo convertSeeTag(SeeTag tag, ContainerInfo base) {
184 return new SeeTagInfo(tag.name(), tag.kind(), tag.text(), base, Converter
185 .convertSourcePosition(tag.position()));
186 }
187
188 private static SourcePositionInfo convertSourcePosition(SourcePosition sp) {
189 if (sp == null) {
190 return null;
191 }
192 return new SourcePositionInfo(sp.file().toString(), sp.line(), sp.column());
193 }
194
195 public static TagInfo[] convertTags(Tag[] tags, ContainerInfo base) {
196 int len = tags.length;
C. Sean Youngda4b2e22015-05-18 14:12:30 -0500197 TagInfo[] out = TagInfo.getArray(len);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700198 for (int i = 0; i < len; i++) {
199 Tag t = tags[i];
200 /*
201 * System.out.println("Tag name='" + t.name() + "' kind='" + t.kind() + "'");
202 */
203 if (t instanceof SeeTag) {
204 out[i] = Converter.convertSeeTag((SeeTag) t, base);
205 } else if (t instanceof ThrowsTag) {
206 out[i] = Converter.convertThrowsTag((ThrowsTag) t, base);
207 } else if (t instanceof ParamTag) {
208 out[i] = Converter.convertParamTag((ParamTag) t, base);
209 } else {
210 out[i] = Converter.convertTag(t);
211 }
212 }
213 return out;
214 }
215
216 public static ClassInfo[] convertClasses(ClassDoc[] classes) {
217 if (classes == null) return null;
218 int N = classes.length;
219 ClassInfo[] result = new ClassInfo[N];
220 for (int i = 0; i < N; i++) {
221 result[i] = Converter.obtainClass(classes[i]);
222 }
223 return result;
224 }
225
226 private static ParameterInfo convertParameter(Parameter p, SourcePosition pos, boolean isVarArg) {
227 if (p == null) return null;
228 ParameterInfo pi =
229 new ParameterInfo(p.name(), p.typeName(), Converter.obtainType(p.type()), isVarArg,
230 Converter.convertSourcePosition(pos));
231 return pi;
232 }
233
234 private static ParameterInfo[] convertParameters(Parameter[] p, ExecutableMemberDoc m) {
235 SourcePosition pos = m.position();
236 int len = p.length;
237 ParameterInfo[] q = new ParameterInfo[len];
238 for (int i = 0; i < len; i++) {
239 boolean isVarArg = (m.isVarArgs() && i == len - 1);
240 q[i] = Converter.convertParameter(p[i], pos, isVarArg);
241 }
242 return q;
243 }
244
245 private static TypeInfo[] convertTypes(Type[] p) {
246 if (p == null) return null;
247 int len = p.length;
248 TypeInfo[] q = new TypeInfo[len];
249 for (int i = 0; i < len; i++) {
250 q[i] = Converter.obtainType(p[i]);
251 }
252 return q;
253 }
254
255 private Converter() {}
256
257 private static class ClassNeedingInit {
258 ClassNeedingInit(ClassDoc c, ClassInfo cl) {
259 this.c = c;
260 this.cl = cl;
261 }
262
263 ClassDoc c;
264 ClassInfo cl;
265 }
266
267 private static ArrayList<ClassNeedingInit> mClassesNeedingInit =
268 new ArrayList<ClassNeedingInit>();
269
270 static ClassInfo obtainClass(ClassDoc o) {
271 return (ClassInfo) mClasses.obtain(o);
272 }
273
274 private static Cache mClasses = new Cache() {
275 @Override
276 protected Object make(Object o) {
277 ClassDoc c = (ClassDoc) o;
278 ClassInfo cl =
279 new ClassInfo(c, c.getRawCommentText(), Converter.convertSourcePosition(c.position()), c
280 .isPublic(), c.isProtected(), c.isPackagePrivate(), c.isPrivate(), c.isStatic(), c
281 .isInterface(), c.isAbstract(), c.isOrdinaryClass(), c.isException(), c.isError(), c
282 .isEnum(), (c instanceof AnnotationTypeDoc), c.isFinal(), c.isIncluded(), c.name(), c
283 .qualifiedName(), c.qualifiedTypeName(), c.isPrimitive());
284 if (mClassesNeedingInit != null) {
285 mClassesNeedingInit.add(new ClassNeedingInit(c, cl));
286 }
287 return cl;
288 }
289
290 @Override
291 protected void made(Object o, Object r) {
292 if (mClassesNeedingInit == null) {
293 initClass((ClassDoc) o, (ClassInfo) r);
294 ((ClassInfo) r).init2();
295 }
296 }
297
298 @Override
299 ClassInfo[] all() {
300 return mCache.values().toArray(new ClassInfo[mCache.size()]);
301 }
302 };
303
304 private static MethodInfo[] getHiddenMethods(MethodDoc[] methods) {
305 if (methods == null) return null;
Hui Shu5118ffe2014-02-18 14:06:42 -0800306 ArrayList<MethodInfo> hiddenMethods = new ArrayList<MethodInfo>();
307 for (MethodDoc method : methods) {
308 MethodInfo methodInfo = Converter.obtainMethod(method);
309 if (methodInfo.isHidden()) {
310 hiddenMethods.add(methodInfo);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700311 }
312 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800313
314 return hiddenMethods.toArray(new MethodInfo[hiddenMethods.size()]);
315 }
316
317 // Gets the removed methods regardless of access levels
318 private static MethodInfo[] getRemovedMethods(MethodDoc[] methods) {
319 if (methods == null) return null;
320 ArrayList<MethodInfo> removedMethods = new ArrayList<MethodInfo>();
321 for (MethodDoc method : methods) {
322 MethodInfo methodInfo = Converter.obtainMethod(method);
323 if (methodInfo.isRemoved()) {
324 removedMethods.add(methodInfo);
325 }
326 }
327
328 return removedMethods.toArray(new MethodInfo[removedMethods.size()]);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700329 }
330
331 /**
Hui Shu5118ffe2014-02-18 14:06:42 -0800332 * Converts FieldDoc[] into List<FieldInfo>. No filtering is done.
Ben Dodson920dbbb2010-08-04 15:21:06 -0700333 */
Hui Shu5118ffe2014-02-18 14:06:42 -0800334 private static List<FieldInfo> convertAllFields(FieldDoc[] fields) {
335 if (fields == null) return null;
336 List<FieldInfo> allFields = new ArrayList<FieldInfo>();
337
338 for (FieldDoc field : fields) {
339 FieldInfo fieldInfo = Converter.obtainField(field);
340 allFields.add(fieldInfo);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700341 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800342
343 return allFields;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700344 }
345
Hui Shu5118ffe2014-02-18 14:06:42 -0800346 /**
347 * Converts ExecutableMemberDoc[] into List<MethodInfo>. No filtering is done.
348 */
349 private static List<MethodInfo> convertAllMethods(ExecutableMemberDoc[] methods) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700350 if (methods == null) return null;
Hui Shu5118ffe2014-02-18 14:06:42 -0800351 List<MethodInfo> allMethods = new ArrayList<MethodInfo>();
352 for (ExecutableMemberDoc method : methods) {
353 MethodInfo methodInfo = Converter.obtainMethod(method);
354 allMethods.add(methodInfo);
355 }
356 return allMethods;
357 }
358
359 /**
360 * Convert MethodDoc[] or ConstructorDoc[] into MethodInfo[].
361 * Also filters according to the -private, -public option,
362 * because the filtering doesn't seem to be working in the ClassDoc.constructors(boolean) call.
363 */
364 private static MethodInfo[] convertMethods(ExecutableMemberDoc[] methods) {
365 if (methods == null) return null;
366 List<MethodInfo> filteredMethods = new ArrayList<MethodInfo>();
367 for (ExecutableMemberDoc method : methods) {
368 MethodInfo methodInfo = Converter.obtainMethod(method);
369 if (methodInfo.checkLevel()) {
370 filteredMethods.add(methodInfo);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700371 }
372 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800373
374 return filteredMethods.toArray(new MethodInfo[filteredMethods.size()]);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700375 }
376
377 private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods) {
378 if (methods == null) return null;
Hui Shu5118ffe2014-02-18 14:06:42 -0800379 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
380 for (ConstructorDoc method : methods) {
381 MethodInfo methodInfo = Converter.obtainMethod(method);
382 if (!methodInfo.checkLevel()) {
383 ctors.add(methodInfo);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700384 }
385 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800386
387 return ctors.toArray(new MethodInfo[ctors.size()]);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700388 }
389
Hui Shu5118ffe2014-02-18 14:06:42 -0800390 private static <E extends ExecutableMemberDoc> MethodInfo obtainMethod(E o) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700391 return (MethodInfo) mMethods.obtain(o);
392 }
393
394 private static Cache mMethods = new Cache() {
395 @Override
396 protected Object make(Object o) {
397 if (o instanceof AnnotationTypeElementDoc) {
398 AnnotationTypeElementDoc m = (AnnotationTypeElementDoc) o;
399 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700400 new MethodInfo(m.getRawCommentText(),
401 new ArrayList<TypeInfo>(Arrays.asList(
402 Converter.convertTypes(m.typeParameters()))),
403 m.name(), m.signature(), Converter.obtainClass(m.containingClass()),
404 Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
405 .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
406 m.isAbstract(), m.isSynchronized(), m.isNative(), true, "annotationElement",
407 m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()),
408 Converter.obtainType(m.returnType()),
409 new ArrayList<ParameterInfo>(Arrays.asList(
410 Converter.convertParameters(m.parameters(), m))),
411 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(
412 m.thrownExceptions()))), Converter.convertSourcePosition(m.position()),
413 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
414 Converter.convertAnnotationInstances(m.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700415 result.setVarargs(m.isVarArgs());
416 result.init(Converter.obtainAnnotationValue(m.defaultValue(), result));
417 return result;
418 } else if (o instanceof MethodDoc) {
419 MethodDoc m = (MethodDoc) o;
420 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700421 new MethodInfo(m.getRawCommentText(),
422 new ArrayList<TypeInfo>(Arrays.asList(
423 Converter.convertTypes(m.typeParameters()))), m.name(), m.signature(),
424 Converter.obtainClass(m.containingClass()),
425 Converter.obtainClass(m.containingClass()), m.isPublic(), m.isProtected(),
426 m.isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
427 m.isAbstract(), m.isSynchronized(), m.isNative(), false, "method",
428 m.flatSignature(), Converter.obtainMethod(m.overriddenMethod()),
429 Converter.obtainType(m.returnType()),
430 new ArrayList<ParameterInfo>(Arrays.asList(
431 Converter.convertParameters(m.parameters(), m))),
432 new ArrayList<ClassInfo>(Arrays.asList(
433 Converter.convertClasses(m.thrownExceptions()))),
434 Converter.convertSourcePosition(m.position()),
435 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(
436 Converter.convertAnnotationInstances(m.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700437 result.setVarargs(m.isVarArgs());
438 result.init(null);
439 return result;
440 } else {
441 ConstructorDoc m = (ConstructorDoc) o;
442 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700443 new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), m
Ben Dodson920dbbb2010-08-04 15:21:06 -0700444 .name(), m.signature(), Converter.obtainClass(m.containingClass()), Converter
445 .obtainClass(m.containingClass()), m.isPublic(), m.isProtected(), m
446 .isPackagePrivate(), m.isPrivate(), m.isFinal(), m.isStatic(), m.isSynthetic(),
447 false, m.isSynchronized(), m.isNative(), false, "constructor", m.flatSignature(),
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700448 null, null, new ArrayList<ParameterInfo>(Arrays.asList(Converter.convertParameters(m.parameters(), m))),
449 new ArrayList<ClassInfo>(Arrays.asList(Converter.convertClasses(m.thrownExceptions()))), Converter.convertSourcePosition(m
450 .position()), new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter.convertAnnotationInstances(m.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700451 result.setVarargs(m.isVarArgs());
452 result.init(null);
453 return result;
454 }
455 }
456 };
457
458
459 private static FieldInfo[] convertFields(FieldDoc[] fields) {
460 if (fields == null) return null;
461 ArrayList<FieldInfo> out = new ArrayList<FieldInfo>();
462 int N = fields.length;
463 for (int i = 0; i < N; i++) {
464 FieldInfo f = Converter.obtainField(fields[i]);
465 if (f.checkLevel()) {
466 out.add(f);
467 }
468 }
469 return out.toArray(new FieldInfo[out.size()]);
470 }
471
472 private static FieldInfo obtainField(FieldDoc o) {
473 return (FieldInfo) mFields.obtain(o);
474 }
475
476 private static FieldInfo obtainField(ConstructorDoc o) {
477 return (FieldInfo) mFields.obtain(o);
478 }
479
480 private static Cache mFields = new Cache() {
481 @Override
482 protected Object make(Object o) {
483 FieldDoc f = (FieldDoc) o;
484 return new FieldInfo(f.name(), Converter.obtainClass(f.containingClass()), Converter
485 .obtainClass(f.containingClass()), f.isPublic(), f.isProtected(), f.isPackagePrivate(), f
486 .isPrivate(), f.isFinal(), f.isStatic(), f.isTransient(), f.isVolatile(),
487 f.isSynthetic(), Converter.obtainType(f.type()), f.getRawCommentText(),
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700488 f.constantValue(), Converter.convertSourcePosition(f.position()),
489 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter
490 .convertAnnotationInstances(f.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700491 }
492 };
493
494 private static PackageInfo obtainPackage(PackageDoc o) {
495 return (PackageInfo) mPackagees.obtain(o);
496 }
497
498 private static Cache mPackagees = new Cache() {
499 @Override
500 protected Object make(Object o) {
501 PackageDoc p = (PackageDoc) o;
502 return new PackageInfo(p, p.name(), Converter.convertSourcePosition(p.position()));
503 }
504 };
505
506 private static TypeInfo obtainType(Type o) {
507 return (TypeInfo) mTypes.obtain(o);
508 }
509
510 private static Cache mTypes = new Cache() {
511 @Override
512 protected Object make(Object o) {
513 Type t = (Type) o;
514 String simpleTypeName;
515 if (t instanceof ClassDoc) {
516 simpleTypeName = ((ClassDoc) t).name();
517 } else {
518 simpleTypeName = t.simpleTypeName();
519 }
520 TypeInfo ti =
521 new TypeInfo(t.isPrimitive(), t.dimension(), simpleTypeName, t.qualifiedTypeName(),
522 Converter.obtainClass(t.asClassDoc()));
523 return ti;
524 }
525
526 @Override
527 protected void made(Object o, Object r) {
528 Type t = (Type) o;
529 TypeInfo ti = (TypeInfo) r;
530 if (t.asParameterizedType() != null) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700531 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asParameterizedType().typeArguments()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700532 } else if (t instanceof ClassDoc) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700533 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(((ClassDoc) t).typeParameters()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700534 } else if (t.asTypeVariable() != null) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700535 ti.setBounds(null, new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes((t.asTypeVariable().bounds())))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700536 ti.setIsTypeVariable(true);
537 } else if (t.asWildcardType() != null) {
538 ti.setIsWildcard(true);
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700539 ti.setBounds(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().superBounds()))),
540 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().extendsBounds()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700541 }
542 }
543
544 @Override
545 protected Object keyFor(Object o) {
546 Type t = (Type) o;
547 String keyString = o.getClass().getName() + "/" + o.toString() + "/";
548 if (t.asParameterizedType() != null) {
549 keyString += t.asParameterizedType().toString() + "/";
550 if (t.asParameterizedType().typeArguments() != null) {
551 for (Type ty : t.asParameterizedType().typeArguments()) {
552 keyString += ty.toString() + "/";
553 }
554 }
555 } else {
556 keyString += "NoParameterizedType//";
557 }
558 if (t.asTypeVariable() != null) {
559 keyString += t.asTypeVariable().toString() + "/";
560 if (t.asTypeVariable().bounds() != null) {
561 for (Type ty : t.asTypeVariable().bounds()) {
562 keyString += ty.toString() + "/";
563 }
564 }
565 } else {
566 keyString += "NoTypeVariable//";
567 }
568 if (t.asWildcardType() != null) {
569 keyString += t.asWildcardType().toString() + "/";
570 if (t.asWildcardType().superBounds() != null) {
571 for (Type ty : t.asWildcardType().superBounds()) {
572 keyString += ty.toString() + "/";
573 }
574 }
575 if (t.asWildcardType().extendsBounds() != null) {
576 for (Type ty : t.asWildcardType().extendsBounds()) {
577 keyString += ty.toString() + "/";
578 }
579 }
580 } else {
581 keyString += "NoWildCardType//";
582 }
583
584 return keyString;
585 }
586 };
Hui Shu5118ffe2014-02-18 14:06:42 -0800587
Ben Dodson920dbbb2010-08-04 15:21:06 -0700588 public static TypeInfo obtainTypeFromString(String type) {
589 return (TypeInfo) mTypesFromString.obtain(type);
590 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800591
Ben Dodson920dbbb2010-08-04 15:21:06 -0700592 private static final Cache mTypesFromString = new Cache() {
593 @Override
594 protected Object make(Object o) {
595 String name = (String) o;
596 return new TypeInfo(name);
597 }
598
599 @Override
600 protected void made(Object o, Object r) {
Hui Shu5118ffe2014-02-18 14:06:42 -0800601
Ben Dodson920dbbb2010-08-04 15:21:06 -0700602 }
603
604 @Override
605 protected Object keyFor(Object o) {
606 return o;
607 }
608 };
609
610 private static MemberInfo obtainMember(MemberDoc o) {
611 return (MemberInfo) mMembers.obtain(o);
612 }
613
614 private static Cache mMembers = new Cache() {
615 @Override
616 protected Object make(Object o) {
617 if (o instanceof MethodDoc) {
618 return Converter.obtainMethod((MethodDoc) o);
619 } else if (o instanceof ConstructorDoc) {
620 return Converter.obtainMethod((ConstructorDoc) o);
621 } else if (o instanceof FieldDoc) {
622 return Converter.obtainField((FieldDoc) o);
623 } else {
624 return null;
625 }
626 }
627 };
628
629 private static AnnotationInstanceInfo[] convertAnnotationInstances(AnnotationDesc[] orig) {
630 int len = orig.length;
631 AnnotationInstanceInfo[] out = new AnnotationInstanceInfo[len];
632 for (int i = 0; i < len; i++) {
633 out[i] = Converter.obtainAnnotationInstance(orig[i]);
634 }
635 return out;
636 }
637
638
639 private static AnnotationInstanceInfo obtainAnnotationInstance(AnnotationDesc o) {
640 return (AnnotationInstanceInfo) mAnnotationInstances.obtain(o);
641 }
642
643 private static Cache mAnnotationInstances = new Cache() {
644 @Override
645 protected Object make(Object o) {
646 AnnotationDesc a = (AnnotationDesc) o;
647 ClassInfo annotationType = Converter.obtainClass(a.annotationType());
648 AnnotationDesc.ElementValuePair[] ev = a.elementValues();
649 AnnotationValueInfo[] elementValues = new AnnotationValueInfo[ev.length];
650 for (int i = 0; i < ev.length; i++) {
651 elementValues[i] =
652 obtainAnnotationValue(ev[i].value(), Converter.obtainMethod(ev[i].element()));
653 }
654 return new AnnotationInstanceInfo(annotationType, elementValues);
655 }
656 };
657
658
659 private abstract static class Cache {
660 void put(Object key, Object value) {
661 mCache.put(key, value);
662 }
663
664 Object obtain(Object o) {
665 if (o == null) {
666 return null;
667 }
668 Object k = keyFor(o);
669 Object r = mCache.get(k);
670 if (r == null) {
671 r = make(o);
672 mCache.put(k, r);
673 made(o, r);
674 }
675 return r;
676 }
677
678 protected HashMap<Object, Object> mCache = new HashMap<Object, Object>();
679
680 protected abstract Object make(Object o);
681
682 protected void made(Object o, Object r) {}
683
684 protected Object keyFor(Object o) {
685 return o;
686 }
687
688 Object[] all() {
689 return null;
690 }
691 }
692
693 // annotation values
694 private static HashMap<AnnotationValue, AnnotationValueInfo> mAnnotationValues =
695 new HashMap<AnnotationValue, AnnotationValueInfo>();
696 private static HashSet<AnnotationValue> mAnnotationValuesNeedingInit =
697 new HashSet<AnnotationValue>();
698
699 private static AnnotationValueInfo obtainAnnotationValue(AnnotationValue o, MethodInfo element) {
700 if (o == null) {
701 return null;
702 }
703 AnnotationValueInfo v = mAnnotationValues.get(o);
704 if (v != null) return v;
705 v = new AnnotationValueInfo(element);
706 mAnnotationValues.put(o, v);
707 if (mAnnotationValuesNeedingInit != null) {
708 mAnnotationValuesNeedingInit.add(o);
709 } else {
710 initAnnotationValue(o, v);
711 }
712 return v;
713 }
714
715 private static void initAnnotationValue(AnnotationValue o, AnnotationValueInfo v) {
716 Object orig = o.value();
717 Object converted;
718 if (orig instanceof Type) {
719 // class literal
720 converted = Converter.obtainType((Type) orig);
721 } else if (orig instanceof FieldDoc) {
722 // enum constant
723 converted = Converter.obtainField((FieldDoc) orig);
724 } else if (orig instanceof AnnotationDesc) {
725 // annotation instance
726 converted = Converter.obtainAnnotationInstance((AnnotationDesc) orig);
727 } else if (orig instanceof AnnotationValue[]) {
728 AnnotationValue[] old = (AnnotationValue[]) orig;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700729 ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>();
730 for (int i = 0; i < old.length; i++) {
731 values.add(Converter.obtainAnnotationValue(old[i], null));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700732 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700733 converted = values;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700734 } else {
735 converted = orig;
736 }
737 v.init(converted);
738 }
739
740 private static void finishAnnotationValueInit() {
741 int depth = 0;
742 while (mAnnotationValuesNeedingInit.size() > 0) {
743 HashSet<AnnotationValue> set = mAnnotationValuesNeedingInit;
744 mAnnotationValuesNeedingInit = new HashSet<AnnotationValue>();
745 for (AnnotationValue o : set) {
746 AnnotationValueInfo v = mAnnotationValues.get(o);
747 initAnnotationValue(o, v);
748 }
749 depth++;
750 }
751 mAnnotationValuesNeedingInit = null;
752 }
753}