blob: e620bf380543184a5b604cfa46d9683113fb38f7 [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
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 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700117 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)))));
Hui Shu5118ffe2014-02-18 14:06:42 -0800135 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
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700147 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)))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700154 }
155
156 public static ClassInfo obtainClass(String className) {
157 return Converter.obtainClass(root.classNamed(className));
158 }
159
160 public static PackageInfo obtainPackage(String packageName) {
161 return Converter.obtainPackage(root.packageNamed(packageName));
162 }
163
164 private static TagInfo convertTag(Tag tag) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700165 return new TextTagInfo(tag.name(), tag.kind(), tag.text(),
166 Converter.convertSourcePosition(tag.position()));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700167 }
168
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
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
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
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
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
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
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
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
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
253 private Converter() {}
254
255 private static class ClassNeedingInit {
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
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
302 private static MethodInfo[] getHiddenMethods(MethodDoc[] methods) {
303 if (methods == null) return null;
Hui Shu5118ffe2014-02-18 14:06:42 -0800304 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);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700309 }
310 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800311
312 return hiddenMethods.toArray(new MethodInfo[hiddenMethods.size()]);
313 }
314
315 // Gets the removed methods regardless of access levels
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()]);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700327 }
328
329 /**
Hui Shu5118ffe2014-02-18 14:06:42 -0800330 * Converts FieldDoc[] into List<FieldInfo>. No filtering is done.
Ben Dodson920dbbb2010-08-04 15:21:06 -0700331 */
Hui Shu5118ffe2014-02-18 14:06:42 -0800332 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);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700339 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800340
341 return allFields;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700342 }
343
Hui Shu5118ffe2014-02-18 14:06:42 -0800344 /**
345 * Converts ExecutableMemberDoc[] into List<MethodInfo>. No filtering is done.
346 */
347 private static List<MethodInfo> convertAllMethods(ExecutableMemberDoc[] methods) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700348 if (methods == null) return null;
Hui Shu5118ffe2014-02-18 14:06:42 -0800349 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 */
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);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700369 }
370 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800371
372 return filteredMethods.toArray(new MethodInfo[filteredMethods.size()]);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700373 }
374
375 private static MethodInfo[] convertNonWrittenConstructors(ConstructorDoc[] methods) {
376 if (methods == null) return null;
Hui Shu5118ffe2014-02-18 14:06:42 -0800377 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);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700382 }
383 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800384
385 return ctors.toArray(new MethodInfo[ctors.size()]);
Ben Dodson920dbbb2010-08-04 15:21:06 -0700386 }
387
Hui Shu5118ffe2014-02-18 14:06:42 -0800388 private static <E extends ExecutableMemberDoc> MethodInfo obtainMethod(E o) {
Ben Dodson920dbbb2010-08-04 15:21:06 -0700389 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 =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700398 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()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700413 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 =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700419 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()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700435 result.setVarargs(m.isVarArgs());
436 result.init(null);
437 return result;
438 } else {
439 ConstructorDoc m = (ConstructorDoc) o;
440 MethodInfo result =
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700441 new MethodInfo(m.getRawCommentText(), new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(m.typeParameters()))), m
Ben Dodson920dbbb2010-08-04 15:21:06 -0700442 .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(),
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700446 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()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700449 result.setVarargs(m.isVarArgs());
450 result.init(null);
451 return result;
452 }
453 }
454 };
455
456
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
470 private static FieldInfo obtainField(FieldDoc o) {
471 return (FieldInfo) mFields.obtain(o);
472 }
473
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(),
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700486 f.constantValue(), Converter.convertSourcePosition(f.position()),
487 new ArrayList<AnnotationInstanceInfo>(Arrays.asList(Converter
488 .convertAnnotationInstances(f.annotations()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700489 }
490 };
491
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
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) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700529 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asParameterizedType().typeArguments()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700530 } else if (t instanceof ClassDoc) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700531 ti.setTypeArguments(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(((ClassDoc) t).typeParameters()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700532 } else if (t.asTypeVariable() != null) {
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700533 ti.setBounds(null, new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes((t.asTypeVariable().bounds())))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700534 ti.setIsTypeVariable(true);
535 } else if (t.asWildcardType() != null) {
536 ti.setIsWildcard(true);
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700537 ti.setBounds(new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().superBounds()))),
538 new ArrayList<TypeInfo>(Arrays.asList(Converter.convertTypes(t.asWildcardType().extendsBounds()))));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700539 }
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 };
Hui Shu5118ffe2014-02-18 14:06:42 -0800585
Ben Dodson920dbbb2010-08-04 15:21:06 -0700586 public static TypeInfo obtainTypeFromString(String type) {
587 return (TypeInfo) mTypesFromString.obtain(type);
588 }
Hui Shu5118ffe2014-02-18 14:06:42 -0800589
Ben Dodson920dbbb2010-08-04 15:21:06 -0700590 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) {
Hui Shu5118ffe2014-02-18 14:06:42 -0800599
Ben Dodson920dbbb2010-08-04 15:21:06 -0700600 }
601
602 @Override
603 protected Object keyFor(Object o) {
604 return o;
605 }
606 };
607
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
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
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 {
658 void put(Object key, Object value) {
659 mCache.put(key, value);
660 }
661
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
678 protected abstract Object make(Object o);
679
680 protected void made(Object o, Object r) {}
681
682 protected Object keyFor(Object o) {
683 return o;
684 }
685
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
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
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;
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700727 ArrayList<AnnotationValueInfo> values = new ArrayList<AnnotationValueInfo>();
728 for (int i = 0; i < old.length; i++) {
729 values.add(Converter.obtainAnnotationValue(old[i], null));
Ben Dodson920dbbb2010-08-04 15:21:06 -0700730 }
Andrew Sappersteind6eaacb2011-05-20 13:14:56 -0700731 converted = values;
Ben Dodson920dbbb2010-08-04 15:21:06 -0700732 } else {
733 converted = orig;
734 }
735 v.init(converted);
736 }
737
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}