blob: f3f11de46354a5d61655bf8a171d80f60149d516 [file] [log] [blame]
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001/*
2 * Copyright (C) 2008 The Android Open Source Project
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
17import com.sun.javadoc.*;
18import com.sun.tools.doclets.*;
19import org.clearsilver.HDF;
20import org.clearsilver.CS;
21import java.util.*;
22import java.io.*;
23
24public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Scoped
25{
26 public static final Comparator<ClassInfo> comparator = new Comparator<ClassInfo>() {
27 public int compare(ClassInfo a, ClassInfo b) {
28 return a.name().compareTo(b.name());
29 }
30 };
31
32 public static final Comparator<ClassInfo> qualifiedComparator = new Comparator<ClassInfo>() {
33 public int compare(ClassInfo a, ClassInfo b) {
34 return a.qualifiedName().compareTo(b.qualifiedName());
35 }
36 };
37
38 public ClassInfo(
39 ClassDoc cl,
40 String rawCommentText, SourcePositionInfo position,
41 boolean isPublic, boolean isProtected, boolean isPackagePrivate,
42 boolean isPrivate, boolean isStatic,
43 boolean isInterface, boolean isAbstract, boolean isOrdinaryClass,
44 boolean isException, boolean isError, boolean isEnum, boolean isAnnotation,
45 boolean isFinal, boolean isIncluded, String name,
46 String qualifiedName, String qualifiedTypeName, boolean isPrimitive)
47 {
48 super(rawCommentText, position);
49
50 mClass = cl;
51 mIsPublic = isPublic;
52 mIsProtected = isProtected;
53 mIsPackagePrivate = isPackagePrivate;
54 mIsPrivate = isPrivate;
55 mIsStatic = isStatic;
56 mIsInterface = isInterface;
57 mIsAbstract = isAbstract;
58 mIsOrdinaryClass = isOrdinaryClass;
59 mIsException = isException;
60 mIsError = isError;
61 mIsEnum = isEnum;
62 mIsAnnotation = isAnnotation;
63 mIsFinal = isFinal;
64 mIsIncluded = isIncluded;
65 mName = name;
66 mQualifiedName = qualifiedName;
67 mQualifiedTypeName = qualifiedTypeName;
68 mIsPrimitive = isPrimitive;
69 mNameParts = name.split("\\.");
70 }
71
72 public void init(TypeInfo typeInfo, ClassInfo[] interfaces, TypeInfo[] interfaceTypes,
73 ClassInfo[] innerClasses,
74 MethodInfo[] constructors, MethodInfo[] methods, MethodInfo[] annotationElements,
75 FieldInfo[] fields, FieldInfo[] enumConstants,
76 PackageInfo containingPackage, ClassInfo containingClass,
77 ClassInfo superclass, TypeInfo superclassType, AnnotationInstanceInfo[] annotations)
78 {
79 mTypeInfo = typeInfo;
80 mRealInterfaces = interfaces;
81 mRealInterfaceTypes = interfaceTypes;
82 mInnerClasses = innerClasses;
83 mAllConstructors = constructors;
84 mAllSelfMethods = methods;
85 mAnnotationElements = annotationElements;
86 mAllSelfFields = fields;
87 mEnumConstants = enumConstants;
88 mContainingPackage = containingPackage;
89 mContainingClass = containingClass;
90 mRealSuperclass = superclass;
91 mRealSuperclassType = superclassType;
92 mAnnotations = annotations;
93
94 // after providing new methods and new superclass info,clear any cached
95 // lists of self + superclass methods, ctors, etc.
96 mSuperclassInit = false;
97 mConstructors = null;
98 mMethods = null;
99 mSelfMethods = null;
100 mFields = null;
101 mSelfFields = null;
102 mSelfAttributes = null;
103 mDeprecatedKnown = false;
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700104
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700105 Arrays.sort(mEnumConstants, FieldInfo.comparator);
106 Arrays.sort(mInnerClasses, ClassInfo.comparator);
107 }
108
109 public void init2() {
110 // calling this here forces the AttrTagInfo objects to be linked to the AttribtueInfo
111 // objects
112 selfAttributes();
113 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700114
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700115 public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses){
116 mTypeParameters = types;
117 mRealInnerClasses = realInnerClasses;
118 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700119
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700120 public ClassInfo[] getRealInnerClasses(){
121 return mRealInnerClasses;
122 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700123
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700124 public TypeInfo[] getTypeParameters(){
125 return mTypeParameters;
126 }
127
128 public boolean checkLevel()
129 {
130 int val = mCheckLevel;
131 if (val >= 0) {
132 return val != 0;
133 } else {
134 boolean v = DroidDoc.checkLevel(mIsPublic, mIsProtected,
135 mIsPackagePrivate, mIsPrivate, isHidden());
136 mCheckLevel = v ? 1 : 0;
137 return v;
138 }
139 }
140
141 public int compareTo(Object that) {
142 if (that instanceof ClassInfo) {
143 return mQualifiedName.compareTo(((ClassInfo)that).mQualifiedName);
144 } else {
145 return this.hashCode() - that.hashCode();
146 }
147 }
148
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700149 @Override
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700150 public ContainerInfo parent()
151 {
152 return this;
153 }
154
155 public boolean isPublic()
156 {
157 return mIsPublic;
158 }
159
160 public boolean isProtected()
161 {
162 return mIsProtected;
163 }
164
165 public boolean isPackagePrivate()
166 {
167 return mIsPackagePrivate;
168 }
169
170 public boolean isPrivate()
171 {
172 return mIsPrivate;
173 }
174
175 public boolean isStatic()
176 {
177 return mIsStatic;
178 }
179
180 public boolean isInterface()
181 {
182 return mIsInterface;
183 }
184
185 public boolean isAbstract()
186 {
187 return mIsAbstract;
188 }
189
190 public PackageInfo containingPackage()
191 {
192 return mContainingPackage;
193 }
194
195 public ClassInfo containingClass()
196 {
197 return mContainingClass;
198 }
199
200 public boolean isOrdinaryClass()
201 {
202 return mIsOrdinaryClass;
203 }
204
205 public boolean isException()
206 {
207 return mIsException;
208 }
209
210 public boolean isError()
211 {
212 return mIsError;
213 }
214
215 public boolean isEnum()
216 {
217 return mIsEnum;
218 }
219
220 public boolean isAnnotation()
221 {
222 return mIsAnnotation;
223 }
224
225 public boolean isFinal()
226 {
227 return mIsFinal;
228 }
229
230 public boolean isIncluded()
231 {
232 return mIsIncluded;
233 }
234
235 public HashSet<String> typeVariables()
236 {
237 HashSet<String> result = TypeInfo.typeVariables(mTypeInfo.typeArguments());
238 ClassInfo cl = containingClass();
239 while (cl != null) {
240 TypeInfo[] types = cl.asTypeInfo().typeArguments();
241 if (types != null) {
242 TypeInfo.typeVariables(types, result);
243 }
244 cl = cl.containingClass();
245 }
246 return result;
247 }
248
249 private static void gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces) {
250 for (ClassInfo iface: cl.mRealInterfaces) {
251 if (iface.checkLevel()) {
252 interfaces.add(iface);
253 } else {
254 gatherHiddenInterfaces(iface, interfaces);
255 }
256 }
257 }
258
259 public ClassInfo[] interfaces()
260 {
261 if (mInterfaces == null) {
262 if (checkLevel()) {
263 HashSet<ClassInfo> interfaces = new HashSet<ClassInfo>();
264 ClassInfo superclass = mRealSuperclass;
265 while (superclass != null && !superclass.checkLevel()) {
266 gatherHiddenInterfaces(superclass, interfaces);
267 superclass = superclass.mRealSuperclass;
268 }
269 gatherHiddenInterfaces(this, interfaces);
270 mInterfaces = interfaces.toArray(new ClassInfo[interfaces.size()]);
271 } else {
272 // put something here in case someone uses it
273 mInterfaces = mRealInterfaces;
274 }
275 Arrays.sort(mInterfaces, ClassInfo.qualifiedComparator);
276 }
277 return mInterfaces;
278 }
279
280 public ClassInfo[] realInterfaces()
281 {
282 return mRealInterfaces;
283 }
284
285 TypeInfo[] realInterfaceTypes()
286 {
287 return mRealInterfaceTypes;
288 }
289
290 public String name()
291 {
292 return mName;
293 }
294
295 public String[] nameParts()
296 {
297 return mNameParts;
298 }
299
300 public String leafName()
301 {
302 return mNameParts[mNameParts.length-1];
303 }
304
305 public String qualifiedName()
306 {
307 return mQualifiedName;
308 }
309
310 public String qualifiedTypeName()
311 {
312 return mQualifiedTypeName;
313 }
314
315 public boolean isPrimitive()
316 {
317 return mIsPrimitive;
318 }
319
320 public MethodInfo[] allConstructors() {
321 return mAllConstructors;
322 }
323
324 public MethodInfo[] constructors()
325 {
326 if (mConstructors == null) {
327 MethodInfo[] methods = mAllConstructors;
328 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
329 for (int i=0; i<methods.length; i++) {
330 MethodInfo m = methods[i];
331 if (!m.isHidden()) {
332 ctors.add(m);
333 }
334 }
335 mConstructors = ctors.toArray(new MethodInfo[ctors.size()]);
336 Arrays.sort(mConstructors, MethodInfo.comparator);
337 }
338 return mConstructors;
339 }
340
341 public ClassInfo[] innerClasses()
342 {
343 return mInnerClasses;
344 }
345
346 public TagInfo[] inlineTags()
347 {
348 return comment().tags();
349 }
350
351 public TagInfo[] firstSentenceTags()
352 {
353 return comment().briefTags();
354 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700355
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700356 public boolean isDeprecated() {
357 boolean deprecated = false;
358 if (!mDeprecatedKnown) {
359 boolean commentDeprecated = (comment().deprecatedTags().length > 0);
360 boolean annotationDeprecated = false;
361 for (AnnotationInstanceInfo annotation : annotations()) {
362 if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
363 annotationDeprecated = true;
364 break;
365 }
366 }
367
368 if (commentDeprecated != annotationDeprecated) {
369 Errors.error(Errors.DEPRECATION_MISMATCH, position(),
370 "Class " + qualifiedName()
371 + ": @Deprecated annotation and @deprecated comment do not match");
372 }
373
374 mIsDeprecated = commentDeprecated | annotationDeprecated;
375 mDeprecatedKnown = true;
376 }
377 return mIsDeprecated;
378 }
379
380 public TagInfo[] deprecatedTags()
381 {
Mike Hearn5496ad22009-01-14 17:27:57 +0100382 // Should we also do the interfaces?
383 return comment().deprecatedTags();
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700384 }
385
386 public MethodInfo[] methods()
387 {
388 if (mMethods == null) {
389 TreeMap<String,MethodInfo> all = new TreeMap<String,MethodInfo>();
390
391 ClassInfo[] ifaces = interfaces();
392 for (ClassInfo iface: ifaces) {
393 if (iface != null) {
394 MethodInfo[] inhereted = iface.methods();
395 for (MethodInfo method: inhereted) {
396 String key = method.name() + method.signature();
397 all.put(key, method);
398 }
399 }
400 }
401
402 ClassInfo superclass = superclass();
403 if (superclass != null) {
404 MethodInfo[] inhereted = superclass.methods();
405 for (MethodInfo method: inhereted) {
406 String key = method.name() + method.signature();
407 all.put(key, method);
408 }
409 }
410
411 MethodInfo[] methods = selfMethods();
412 for (MethodInfo method: methods) {
413 String key = method.name() + method.signature();
414 MethodInfo old = all.put(key, method);
415 }
416
417 mMethods = all.values().toArray(new MethodInfo[all.size()]);
418 }
419 return mMethods;
420 }
421
422 public MethodInfo[] annotationElements()
423 {
424 return mAnnotationElements;
425 }
426
427 public AnnotationInstanceInfo[] annotations()
428 {
429 return mAnnotations;
430 }
431
432 private static void addFields(ClassInfo cl, TreeMap<String,FieldInfo> all)
433 {
434 FieldInfo[] fields = cl.fields();
435 int N = fields.length;
436 for (int i=0; i<N; i++) {
437 FieldInfo f = fields[i];
438 all.put(f.name(), f);
439 }
440 }
441
442 public FieldInfo[] fields()
443 {
444 if (mFields == null) {
445 int N;
446 TreeMap<String,FieldInfo> all = new TreeMap<String,FieldInfo>();
447
448 ClassInfo[] interfaces = interfaces();
449 N = interfaces.length;
450 for (int i=0; i<N; i++) {
451 addFields(interfaces[i], all);
452 }
453
454 ClassInfo superclass = superclass();
455 if (superclass != null) {
456 addFields(superclass, all);
457 }
458
459 FieldInfo[] fields = selfFields();
460 N = fields.length;
461 for (int i=0; i<N; i++) {
462 FieldInfo f = fields[i];
463 if (!f.isHidden()) {
464 String key = f.name();
465 all.put(key, f);
466 }
467 }
468
469 mFields = all.values().toArray(new FieldInfo[0]);
470 }
471 return mFields;
472 }
473
474 public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields) {
475 FieldInfo[] flds = cl.selfFields();
476 for (FieldInfo f: flds) {
477 if (f.checkLevel()) {
478 fields.put(f.name(), f.cloneForClass(owner));
479 }
480 }
481 }
482
483 public FieldInfo[] selfFields()
484 {
485 if (mSelfFields == null) {
486 HashMap<String,FieldInfo> fields = new HashMap<String,FieldInfo>();
487 // our hidden parents
488 if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
489 gatherFields(this, mRealSuperclass, fields);
490 }
491 for (ClassInfo iface: mRealInterfaces) {
492 if (!iface.checkLevel()) {
493 gatherFields(this, iface, fields);
494 }
495 }
496 // mine
497 FieldInfo[] selfFields = mAllSelfFields;
498 for (int i=0; i<selfFields.length; i++) {
499 FieldInfo f = selfFields[i];
500 if (!f.isHidden()) {
501 fields.put(f.name(), f);
502 }
503 }
504 // combine and return in
505 mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]);
506 Arrays.sort(mSelfFields, FieldInfo.comparator);
507 }
508 return mSelfFields;
509 }
510
511 public FieldInfo[] allSelfFields() {
512 return mAllSelfFields;
513 }
514
515 public void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods) {
516 MethodInfo[] meth = cl.selfMethods();
517 for (MethodInfo m: meth) {
518 if (m.checkLevel()) {
519 methods.put(m.name()+m.signature(), m.cloneForClass(owner));
520 }
521 }
522 }
523
524 public MethodInfo[] selfMethods()
525 {
526 if (mSelfMethods == null) {
527 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
528 // our hidden parents
529 if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
530 gatherMethods(this, mRealSuperclass, methods);
531 }
532 for (ClassInfo iface: mRealInterfaces) {
533 if (!iface.checkLevel()) {
534 gatherMethods(this, iface, methods);
535 }
536 }
537 // mine
538 MethodInfo[] selfMethods = mAllSelfMethods;
539 for (int i=0; i<selfMethods.length; i++) {
540 MethodInfo m = selfMethods[i];
541 if (m.checkLevel()) {
542 methods.put(m.name()+m.signature(), m);
543 }
544 }
545 // combine and return it
546 mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]);
547 Arrays.sort(mSelfMethods, MethodInfo.comparator);
548 }
549 return mSelfMethods;
550 }
551
552 public MethodInfo[] allSelfMethods() {
553 return mAllSelfMethods;
554 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700555
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700556 public void addMethod(MethodInfo method) {
557 MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
558 int i = 0;
559 for (MethodInfo m : mAllSelfMethods) {
560 methods[i] = m;
561 i++;
562 }
563 methods[i] = method;
564 mAllSelfMethods = methods;
565 }
566
567 public AttributeInfo[] selfAttributes()
568 {
569 if (mSelfAttributes == null) {
570 TreeMap<FieldInfo,AttributeInfo> attrs = new TreeMap<FieldInfo,AttributeInfo>();
571
572 // the ones in the class comment won't have any methods
573 for (AttrTagInfo tag: comment().attrTags()) {
574 FieldInfo field = tag.reference();
575 if (field != null) {
576 AttributeInfo attr = attrs.get(field);
577 if (attr == null) {
578 attr = new AttributeInfo(this, field);
579 attrs.put(field, attr);
580 }
581 tag.setAttribute(attr);
582 }
583 }
584
585 // in the methods
586 for (MethodInfo m: selfMethods()) {
587 for (AttrTagInfo tag: m.comment().attrTags()) {
588 FieldInfo field = tag.reference();
589 if (field != null) {
590 AttributeInfo attr = attrs.get(field);
591 if (attr == null) {
592 attr = new AttributeInfo(this, field);
593 attrs.put(field, attr);
594 }
595 tag.setAttribute(attr);
596 attr.methods.add(m);
597 }
598 }
599 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -0700600
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700601 //constructors too
602 for (MethodInfo m: constructors()) {
603 for (AttrTagInfo tag: m.comment().attrTags()) {
604 FieldInfo field = tag.reference();
605 if (field != null) {
606 AttributeInfo attr = attrs.get(field);
607 if (attr == null) {
608 attr = new AttributeInfo(this, field);
609 attrs.put(field, attr);
610 }
611 tag.setAttribute(attr);
612 attr.methods.add(m);
613 }
614 }
615 }
616
617 mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]);
618 Arrays.sort(mSelfAttributes, AttributeInfo.comparator);
619 }
620 return mSelfAttributes;
621 }
622
623 public FieldInfo[] enumConstants()
624 {
625 return mEnumConstants;
626 }
627
628 public ClassInfo superclass()
629 {
630 if (!mSuperclassInit) {
631 if (this.checkLevel()) {
632 // rearrange our little inheritance hierarchy, because we need to hide classes that
633 // don't pass checkLevel
634 ClassInfo superclass = mRealSuperclass;
635 while (superclass != null && !superclass.checkLevel()) {
636 superclass = superclass.mRealSuperclass;
637 }
638 mSuperclass = superclass;
639 } else {
640 mSuperclass = mRealSuperclass;
641 }
642 }
643 return mSuperclass;
644 }
645
646 public ClassInfo realSuperclass()
647 {
648 return mRealSuperclass;
649 }
650
651 /** always the real superclass, not the collapsed one we get through superclass(),
652 * also has the type parameter info if it's generic.
653 */
654 public TypeInfo superclassType()
655 {
656 return mRealSuperclassType;
657 }
658
659 public TypeInfo asTypeInfo()
660 {
661 return mTypeInfo;
662 }
663
664 TypeInfo[] interfaceTypes()
665 {
666 ClassInfo[] infos = interfaces();
667 int len = infos.length;
668 TypeInfo[] types = new TypeInfo[len];
669 for (int i=0; i<len; i++) {
670 types[i] = infos[i].asTypeInfo();
671 }
672 return types;
673 }
674
675 public String htmlPage()
676 {
677 String s = containingPackage().name();
678 s = s.replace('.', '/');
679 s += '/';
680 s += name();
681 s += ".html";
682 s = DroidDoc.javadocDir + s;
683 return s;
684 }
685
686 /** Even indirectly */
687 public boolean isDerivedFrom(ClassInfo cl)
688 {
689 ClassInfo dad = this.superclass();
690 if (dad != null) {
691 if (dad.equals(cl)) {
692 return true;
693 } else {
694 if (dad.isDerivedFrom(cl)) {
695 return true;
696 }
697 }
698 }
699 for (ClassInfo iface: interfaces()) {
700 if (iface.equals(cl)) {
701 return true;
702 } else {
703 if (iface.isDerivedFrom(cl)) {
704 return true;
705 }
706 }
707 }
708 return false;
709 }
710
711 public void makeKeywordEntries(List<KeywordEntry> keywords)
712 {
713 if (!checkLevel()) {
714 return;
715 }
716
717 String htmlPage = htmlPage();
718 String qualifiedName = qualifiedName();
719
720 keywords.add(new KeywordEntry(name(), htmlPage,
721 "class in " + containingPackage().name()));
722
723 FieldInfo[] fields = selfFields();
724 FieldInfo[] enumConstants = enumConstants();
725 MethodInfo[] ctors = constructors();
726 MethodInfo[] methods = selfMethods();
727
728 // enum constants
729 for (FieldInfo field: enumConstants()) {
730 if (field.checkLevel()) {
731 keywords.add(new KeywordEntry(field.name(),
732 htmlPage + "#" + field.anchor(),
733 "enum constant in " + qualifiedName));
734 }
735 }
736
737 // constants
738 for (FieldInfo field: fields) {
739 if (field.isConstant() && field.checkLevel()) {
740 keywords.add(new KeywordEntry(field.name(),
741 htmlPage + "#" + field.anchor(),
742 "constant in " + qualifiedName));
743 }
744 }
745
746 // fields
747 for (FieldInfo field: fields) {
748 if (!field.isConstant() && field.checkLevel()) {
749 keywords.add(new KeywordEntry(field.name(),
750 htmlPage + "#" + field.anchor(),
751 "field in " + qualifiedName));
752 }
753 }
754
755 // public constructors
756 for (MethodInfo m: ctors) {
757 if (m.isPublic() && m.checkLevel()) {
758 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
759 htmlPage + "#" + m.anchor(),
760 "constructor in " + qualifiedName));
761 }
762 }
763
764 // protected constructors
765 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
766 for (MethodInfo m: ctors) {
767 if (m.isProtected() && m.checkLevel()) {
768 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
769 htmlPage + "#" + m.anchor(),
770 "constructor in " + qualifiedName));
771 }
772 }
773 }
774
775 // package private constructors
776 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
777 for (MethodInfo m: ctors) {
778 if (m.isPackagePrivate() && m.checkLevel()) {
779 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
780 htmlPage + "#" + m.anchor(),
781 "constructor in " + qualifiedName));
782 }
783 }
784 }
785
786 // private constructors
787 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
788 for (MethodInfo m: ctors) {
789 if (m.isPrivate() && m.checkLevel()) {
790 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
791 htmlPage + "#" + m.anchor(),
792 "constructor in " + qualifiedName));
793 }
794 }
795 }
796
797 // public methods
798 for (MethodInfo m: methods) {
799 if (m.isPublic() && m.checkLevel()) {
800 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
801 htmlPage + "#" + m.anchor(),
802 "method in " + qualifiedName));
803 }
804 }
805
806 // protected methods
807 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
808 for (MethodInfo m: methods) {
809 if (m.isProtected() && m.checkLevel()) {
810 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
811 htmlPage + "#" + m.anchor(),
812 "method in " + qualifiedName));
813 }
814 }
815 }
816
817 // package private methods
818 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
819 for (MethodInfo m: methods) {
820 if (m.isPackagePrivate() && m.checkLevel()) {
821 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
822 htmlPage + "#" + m.anchor(),
823 "method in " + qualifiedName));
824 }
825 }
826 }
827
828 // private methods
829 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
830 for (MethodInfo m: methods) {
831 if (m.isPrivate() && m.checkLevel()) {
832 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
833 htmlPage + "#" + m.anchor(),
834 "method in " + qualifiedName));
835 }
836 }
837 }
838 }
839
840 public void makeLink(HDF data, String base)
841 {
842 data.setValue(base + ".label", this.name());
843 if (!this.isPrimitive() && this.isIncluded() && this.checkLevel()) {
844 data.setValue(base + ".link", this.htmlPage());
845 }
846 }
847
848 public static void makeLinkListHDF(HDF data, String base, ClassInfo[] classes) {
849 final int N = classes.length;
850 for (int i=0; i<N; i++) {
851 ClassInfo cl = classes[i];
852 if (cl.checkLevel()) {
853 cl.asTypeInfo().makeHDF(data, base + "." + i);
854 }
855 }
856 }
857
858 /**
859 * Used in lists of this class (packages, nested classes, known subclasses)
860 */
861 public void makeShortDescrHDF(HDF data, String base)
862 {
863 mTypeInfo.makeHDF(data, base + ".type");
864 data.setValue(base + ".kind", this.kind());
865 TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags());
866 TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
Scott Main25fda192009-08-04 11:26:30 -0700867 data.setValue(base + ".since", getSince());
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700868 }
869
870 /**
871 * Turns into the main class page
872 */
873 public void makeHDF(HDF data)
874 {
875 int i, j, n;
876 String name = name();
877 String qualified = qualifiedName();
878 AttributeInfo[] selfAttributes = selfAttributes();
879 MethodInfo[] methods = selfMethods();
880 FieldInfo[] fields = selfFields();
881 FieldInfo[] enumConstants = enumConstants();
882 MethodInfo[] ctors = constructors();
883 ClassInfo[] inners = innerClasses();
884
885 // class name
886 mTypeInfo.makeHDF(data, "class.type");
887 mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType");
888 data.setValue("class.name", name);
889 data.setValue("class.qualified", qualified);
890 String scope = "";
891 if (isProtected()) {
892 data.setValue("class.scope", "protected");
893 }
894 else if (isPublic()) {
895 data.setValue("class.scope", "public");
896 }
897 if (isStatic()) {
898 data.setValue("class.static", "static");
899 }
900 if (isFinal()) {
901 data.setValue("class.final", "final");
902 }
903 if (isAbstract() && !isInterface()) {
904 data.setValue("class.abstract", "abstract");
905 }
906
907 // class info
908 String kind = kind();
909 if (kind != null) {
910 data.setValue("class.kind", kind);
911 }
Jesse Wilson5e0dd412009-06-01 17:59:44 -0700912 data.setValue("class.since", getSince());
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -0700913
914 // the containing package -- note that this can be passed to type_link,
915 // but it also contains the list of all of the packages
916 containingPackage().makeClassLinkListHDF(data, "class.package");
917
918 // inheritance hierarchy
919 Vector<ClassInfo> superClasses = new Vector<ClassInfo>();
920 superClasses.add(this);
921 ClassInfo supr = superclass();
922 while (supr != null) {
923 superClasses.add(supr);
924 supr = supr.superclass();
925 }
926 n = superClasses.size();
927 for (i=0; i<n; i++) {
928 supr = superClasses.elementAt(n-i-1);
929
930 supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class");
931 supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class");
932 j = 0;
933 for (TypeInfo t: supr.interfaceTypes()) {
934 t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j);
935 j++;
936 }
937 }
938
939 // class description
940 TagInfo.makeHDF(data, "class.descr", inlineTags());
941 TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags());
942 TagInfo.makeHDF(data, "class.deprecated", deprecatedTags());
943
944 // known subclasses
945 TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>();
946 TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>();
947 ClassInfo[] all = Converter.rootClasses();
948 for (ClassInfo cl: all) {
949 if (cl.superclass() != null && cl.superclass().equals(this)) {
950 direct.put(cl.name(), cl);
951 }
952 else if (cl.isDerivedFrom(this)) {
953 indirect.put(cl.name(), cl);
954 }
955 }
956 // direct
957 i = 0;
958 for (ClassInfo cl: direct.values()) {
959 if (cl.checkLevel()) {
960 cl.makeShortDescrHDF(data, "class.subclasses.direct." + i);
961 }
962 i++;
963 }
964 // indirect
965 i = 0;
966 for (ClassInfo cl: indirect.values()) {
967 if (cl.checkLevel()) {
968 cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i);
969 }
970 i++;
971 }
972
973 // nested classes
974 i=0;
975 for (ClassInfo inner: inners) {
976 if (inner.checkLevel()) {
977 inner.makeShortDescrHDF(data, "class.inners." + i);
978 }
979 i++;
980 }
981
982 // enum constants
983 i=0;
984 for (FieldInfo field: enumConstants) {
985 if (field.isConstant()) {
986 field.makeHDF(data, "class.enumConstants." + i);
987 i++;
988 }
989 }
990
991 // constants
992 i=0;
993 for (FieldInfo field: fields) {
994 if (field.isConstant()) {
995 field.makeHDF(data, "class.constants." + i);
996 i++;
997 }
998 }
999
1000 // fields
1001 i=0;
1002 for (FieldInfo field: fields) {
1003 if (!field.isConstant()) {
1004 field.makeHDF(data, "class.fields." + i);
1005 i++;
1006 }
1007 }
1008
1009 // public constructors
1010 i=0;
1011 for (MethodInfo ctor: ctors) {
1012 if (ctor.isPublic()) {
1013 ctor.makeHDF(data, "class.ctors.public." + i);
1014 i++;
1015 }
1016 }
1017
1018 // protected constructors
1019 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1020 i=0;
1021 for (MethodInfo ctor: ctors) {
1022 if (ctor.isProtected()) {
1023 ctor.makeHDF(data, "class.ctors.protected." + i);
1024 i++;
1025 }
1026 }
1027 }
1028
1029 // package private constructors
1030 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1031 i=0;
1032 for (MethodInfo ctor: ctors) {
1033 if (ctor.isPackagePrivate()) {
1034 ctor.makeHDF(data, "class.ctors.package." + i);
1035 i++;
1036 }
1037 }
1038 }
1039
1040 // private constructors
1041 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1042 i=0;
1043 for (MethodInfo ctor: ctors) {
1044 if (ctor.isPrivate()) {
1045 ctor.makeHDF(data, "class.ctors.private." + i);
1046 i++;
1047 }
1048 }
1049 }
1050
1051 // public methods
1052 i=0;
1053 for (MethodInfo method: methods) {
1054 if (method.isPublic()) {
1055 method.makeHDF(data, "class.methods.public." + i);
1056 i++;
1057 }
1058 }
1059
1060 // protected methods
1061 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1062 i=0;
1063 for (MethodInfo method: methods) {
1064 if (method.isProtected()) {
1065 method.makeHDF(data, "class.methods.protected." + i);
1066 i++;
1067 }
1068 }
1069 }
1070
1071 // package private methods
1072 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1073 i=0;
1074 for (MethodInfo method: methods) {
1075 if (method.isPackagePrivate()) {
1076 method.makeHDF(data, "class.methods.package." + i);
1077 i++;
1078 }
1079 }
1080 }
1081
1082 // private methods
1083 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1084 i=0;
1085 for (MethodInfo method: methods) {
1086 if (method.isPrivate()) {
1087 method.makeHDF(data, "class.methods.private." + i);
1088 i++;
1089 }
1090 }
1091 }
1092
1093 // xml attributes
1094 i=0;
1095 for (AttributeInfo attr: selfAttributes) {
1096 if (attr.checkLevel()) {
1097 attr.makeHDF(data, "class.attrs." + i);
1098 i++;
1099 }
1100 }
1101
1102 // inherited methods
1103 Set<ClassInfo> interfaces = new TreeSet<ClassInfo>();
1104 addInterfaces(interfaces(), interfaces);
1105 ClassInfo cl = superclass();
1106 i=0;
1107 while (cl != null) {
1108 addInterfaces(cl.interfaces(), interfaces);
1109 makeInheritedHDF(data, i, cl);
1110 cl = cl.superclass();
1111 i++;
1112 }
1113 for (ClassInfo iface: interfaces) {
1114 makeInheritedHDF(data, i, iface);
1115 i++;
1116 }
1117 }
1118
1119 private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out)
1120 {
1121 for (ClassInfo cl: ifaces) {
1122 out.add(cl);
1123 addInterfaces(cl.interfaces(), out);
1124 }
1125 }
1126
1127 private static void makeInheritedHDF(HDF data, int index, ClassInfo cl)
1128 {
1129 int i;
1130
1131 String base = "class.inherited." + index;
1132 data.setValue(base + ".qualified", cl.qualifiedName());
1133 if (cl.checkLevel()) {
1134 data.setValue(base + ".link", cl.htmlPage());
1135 }
1136 String kind = cl.kind();
1137 if (kind != null) {
1138 data.setValue(base + ".kind", kind);
1139 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001140
Xavier Ducrohet63ec8e32009-09-11 10:59:31 -07001141 if (cl.mIsIncluded) {
1142 data.setValue(base + ".included", "true");
1143 }
1144
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001145 // xml attributes
1146 i=0;
1147 for (AttributeInfo attr: cl.selfAttributes()) {
1148 attr.makeHDF(data, base + ".attrs." + i);
1149 i++;
1150 }
1151
1152 // methods
1153 i=0;
1154 for (MethodInfo method: cl.selfMethods()) {
1155 method.makeHDF(data, base + ".methods." + i);
1156 i++;
1157 }
1158
1159 // fields
1160 i=0;
1161 for (FieldInfo field: cl.selfFields()) {
1162 if (!field.isConstant()) {
1163 field.makeHDF(data, base + ".fields." + i);
1164 i++;
1165 }
1166 }
1167
1168 // constants
1169 i=0;
1170 for (FieldInfo field: cl.selfFields()) {
1171 if (field.isConstant()) {
1172 field.makeHDF(data, base + ".constants." + i);
1173 i++;
1174 }
1175 }
1176 }
1177
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001178 @Override
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001179 public boolean isHidden()
1180 {
1181 int val = mHidden;
1182 if (val >= 0) {
1183 return val != 0;
1184 } else {
1185 boolean v = isHiddenImpl();
1186 mHidden = v ? 1 : 0;
1187 return v;
1188 }
1189 }
1190
1191 public boolean isHiddenImpl()
1192 {
1193 ClassInfo cl = this;
1194 while (cl != null) {
1195 PackageInfo pkg = cl.containingPackage();
The Android Open Source Projectf122bec2009-03-18 17:39:42 -07001196 if (pkg != null && pkg.isHidden()) {
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001197 return true;
1198 }
1199 if (cl.comment().isHidden()) {
1200 return true;
1201 }
1202 cl = cl.containingClass();
1203 }
1204 return false;
1205 }
1206
1207 private MethodInfo matchMethod(MethodInfo[] methods, String name,
1208 String[] params, String[] dimensions)
1209 {
1210 int len = methods.length;
1211 for (int i=0; i<len; i++) {
1212 MethodInfo method = methods[i];
1213 if (method.name().equals(name)) {
1214 if (params == null) {
1215 return method;
1216 } else {
1217 if (method.matchesParams(params, dimensions)) {
1218 return method;
1219 }
1220 }
1221 }
1222 }
1223 return null;
1224 }
1225
1226 public MethodInfo findMethod(String name,
1227 String[] params, String[] dimensions)
1228 {
1229 // first look on our class, and our superclasses
1230
1231 // for methods
1232 MethodInfo rv;
1233 rv = matchMethod(methods(), name, params, dimensions);
1234
1235 if (rv != null) {
1236 return rv;
1237 }
1238
1239 // for constructors
1240 rv = matchMethod(constructors(), name, params, dimensions);
1241 if (rv != null) {
1242 return rv;
1243 }
1244
1245 // then recursively look at our containing class
1246 ClassInfo containing = containingClass();
1247 if (containing != null) {
1248 return containing.findMethod(name, params, dimensions);
1249 }
1250
1251 return null;
1252 }
1253
1254 private ClassInfo searchInnerClasses(String[] nameParts, int index)
1255 {
1256 String part = nameParts[index];
1257
1258 ClassInfo[] inners = mInnerClasses;
1259 for (ClassInfo in: inners) {
1260 String[] innerParts = in.nameParts();
1261 if (part.equals(innerParts[innerParts.length-1])) {
1262 if (index == nameParts.length-1) {
1263 return in;
1264 } else {
1265 return in.searchInnerClasses(nameParts, index+1);
1266 }
1267 }
1268 }
1269 return null;
1270 }
1271
1272 public ClassInfo extendedFindClass(String className)
1273 {
1274 // ClassDoc.findClass has this bug that we're working around here:
1275 // If you have a class PackageManager with an inner class PackageInfo
1276 // and you call it with "PackageInfo" it doesn't find it.
1277 return searchInnerClasses(className.split("\\."), 0);
1278 }
1279
1280 public ClassInfo findClass(String className)
1281 {
1282 return Converter.obtainClass(mClass.findClass(className));
1283 }
1284
1285 public ClassInfo findInnerClass(String className)
1286 {
1287 // ClassDoc.findClass won't find inner classes. To deal with that,
1288 // we try what they gave us first, but if that didn't work, then
1289 // we see if there are any periods in className, and start searching
1290 // from there.
1291 String[] nodes = className.split("\\.");
1292 ClassDoc cl = mClass;
1293 for (String n: nodes) {
1294 cl = cl.findClass(n);
1295 if (cl == null) {
1296 return null;
1297 }
1298 }
1299 return Converter.obtainClass(cl);
1300 }
1301
1302 public FieldInfo findField(String name)
1303 {
1304 // first look on our class, and our superclasses
1305 for (FieldInfo f: fields()) {
1306 if (f.name().equals(name)) {
1307 return f;
1308 }
1309 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001310
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001311 // then look at our enum constants (these are really fields, maybe
1312 // they should be mixed into fields(). not sure)
1313 for (FieldInfo f: enumConstants()) {
1314 if (f.name().equals(name)) {
1315 return f;
1316 }
1317 }
1318
1319 // then recursively look at our containing class
1320 ClassInfo containing = containingClass();
1321 if (containing != null) {
1322 return containing.findField(name);
1323 }
1324
1325 return null;
1326 }
1327
1328 public static ClassInfo[] sortByName(ClassInfo[] classes)
1329 {
1330 int i;
1331 Sorter[] sorted = new Sorter[classes.length];
1332 for (i=0; i<sorted.length; i++) {
1333 ClassInfo cl = classes[i];
1334 sorted[i] = new Sorter(cl.name(), cl);
1335 }
1336
1337 Arrays.sort(sorted);
1338
1339 ClassInfo[] rv = new ClassInfo[classes.length];
1340 for (i=0; i<rv.length; i++) {
1341 rv[i] = (ClassInfo)sorted[i].data;
1342 }
1343
1344 return rv;
1345 }
1346
1347 public boolean equals(ClassInfo that)
1348 {
1349 if (that != null) {
1350 return this.qualifiedName().equals(that.qualifiedName());
1351 } else {
1352 return false;
1353 }
1354 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001355
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001356 public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
1357 mNonWrittenConstructors = nonWritten;
1358 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001359
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001360 public MethodInfo[] getNonWrittenConstructors() {
1361 return mNonWrittenConstructors;
1362 }
1363
1364 public String kind()
1365 {
1366 if (isOrdinaryClass()) {
1367 return "class";
1368 }
1369 else if (isInterface()) {
1370 return "interface";
1371 }
1372 else if (isEnum()) {
1373 return "enum";
1374 }
1375 else if (isError()) {
1376 return "class";
1377 }
1378 else if (isException()) {
1379 return "class";
1380 }
1381 else if (isAnnotation()) {
1382 return "@interface";
1383 }
1384 return null;
1385 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001386
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001387 public void setHiddenMethods(MethodInfo[] mInfo){
1388 mHiddenMethods = mInfo;
1389 }
1390 public MethodInfo[] getHiddenMethods(){
1391 return mHiddenMethods;
1392 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001393 @Override
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001394 public String toString(){
1395 return this.qualifiedName();
1396 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001397
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001398 public void setReasonIncluded(String reason) {
1399 mReasonIncluded = reason;
1400 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001401
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001402 public String getReasonIncluded() {
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001403 return mReasonIncluded;
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001404 }
1405
1406 private ClassDoc mClass;
1407
1408 // ctor
1409 private boolean mIsPublic;
1410 private boolean mIsProtected;
1411 private boolean mIsPackagePrivate;
1412 private boolean mIsPrivate;
1413 private boolean mIsStatic;
1414 private boolean mIsInterface;
1415 private boolean mIsAbstract;
1416 private boolean mIsOrdinaryClass;
1417 private boolean mIsException;
1418 private boolean mIsError;
1419 private boolean mIsEnum;
1420 private boolean mIsAnnotation;
1421 private boolean mIsFinal;
1422 private boolean mIsIncluded;
1423 private String mName;
1424 private String mQualifiedName;
1425 private String mQualifiedTypeName;
1426 private boolean mIsPrimitive;
1427 private TypeInfo mTypeInfo;
1428 private String[] mNameParts;
1429
1430 // init
1431 private ClassInfo[] mRealInterfaces;
1432 private ClassInfo[] mInterfaces;
1433 private TypeInfo[] mRealInterfaceTypes;
1434 private ClassInfo[] mInnerClasses;
1435 private MethodInfo[] mAllConstructors;
1436 private MethodInfo[] mAllSelfMethods;
1437 private MethodInfo[] mAnnotationElements; // if this class is an annotation
1438 private FieldInfo[] mAllSelfFields;
1439 private FieldInfo[] mEnumConstants;
1440 private PackageInfo mContainingPackage;
1441 private ClassInfo mContainingClass;
1442 private ClassInfo mRealSuperclass;
1443 private TypeInfo mRealSuperclassType;
1444 private ClassInfo mSuperclass;
1445 private AnnotationInstanceInfo[] mAnnotations;
1446 private boolean mSuperclassInit;
1447 private boolean mDeprecatedKnown;
1448
1449 // lazy
1450 private MethodInfo[] mConstructors;
1451 private ClassInfo[] mRealInnerClasses;
1452 private MethodInfo[] mSelfMethods;
1453 private FieldInfo[] mSelfFields;
1454 private AttributeInfo[] mSelfAttributes;
1455 private MethodInfo[] mMethods;
1456 private FieldInfo[] mFields;
1457 private TypeInfo[] mTypeParameters;
1458 private MethodInfo[] mHiddenMethods;
1459 private int mHidden = -1;
1460 private int mCheckLevel = -1;
1461 private String mReasonIncluded;
1462 private MethodInfo[] mNonWrittenConstructors;
1463 private boolean mIsDeprecated;
1464}