blob: 36edbf801b46411d87709b653b37f0ab2cf033c6 [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;
104
105 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 }
114
115 public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses){
116 mTypeParameters = types;
117 mRealInnerClasses = realInnerClasses;
118 }
119
120 public ClassInfo[] getRealInnerClasses(){
121 return mRealInnerClasses;
122 }
123
124 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
149 public ContainerInfo parent()
150 {
151 return this;
152 }
153
154 public boolean isPublic()
155 {
156 return mIsPublic;
157 }
158
159 public boolean isProtected()
160 {
161 return mIsProtected;
162 }
163
164 public boolean isPackagePrivate()
165 {
166 return mIsPackagePrivate;
167 }
168
169 public boolean isPrivate()
170 {
171 return mIsPrivate;
172 }
173
174 public boolean isStatic()
175 {
176 return mIsStatic;
177 }
178
179 public boolean isInterface()
180 {
181 return mIsInterface;
182 }
183
184 public boolean isAbstract()
185 {
186 return mIsAbstract;
187 }
188
189 public PackageInfo containingPackage()
190 {
191 return mContainingPackage;
192 }
193
194 public ClassInfo containingClass()
195 {
196 return mContainingClass;
197 }
198
199 public boolean isOrdinaryClass()
200 {
201 return mIsOrdinaryClass;
202 }
203
204 public boolean isException()
205 {
206 return mIsException;
207 }
208
209 public boolean isError()
210 {
211 return mIsError;
212 }
213
214 public boolean isEnum()
215 {
216 return mIsEnum;
217 }
218
219 public boolean isAnnotation()
220 {
221 return mIsAnnotation;
222 }
223
224 public boolean isFinal()
225 {
226 return mIsFinal;
227 }
228
229 public boolean isIncluded()
230 {
231 return mIsIncluded;
232 }
233
234 public HashSet<String> typeVariables()
235 {
236 HashSet<String> result = TypeInfo.typeVariables(mTypeInfo.typeArguments());
237 ClassInfo cl = containingClass();
238 while (cl != null) {
239 TypeInfo[] types = cl.asTypeInfo().typeArguments();
240 if (types != null) {
241 TypeInfo.typeVariables(types, result);
242 }
243 cl = cl.containingClass();
244 }
245 return result;
246 }
247
248 private static void gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces) {
249 for (ClassInfo iface: cl.mRealInterfaces) {
250 if (iface.checkLevel()) {
251 interfaces.add(iface);
252 } else {
253 gatherHiddenInterfaces(iface, interfaces);
254 }
255 }
256 }
257
258 public ClassInfo[] interfaces()
259 {
260 if (mInterfaces == null) {
261 if (checkLevel()) {
262 HashSet<ClassInfo> interfaces = new HashSet<ClassInfo>();
263 ClassInfo superclass = mRealSuperclass;
264 while (superclass != null && !superclass.checkLevel()) {
265 gatherHiddenInterfaces(superclass, interfaces);
266 superclass = superclass.mRealSuperclass;
267 }
268 gatherHiddenInterfaces(this, interfaces);
269 mInterfaces = interfaces.toArray(new ClassInfo[interfaces.size()]);
270 } else {
271 // put something here in case someone uses it
272 mInterfaces = mRealInterfaces;
273 }
274 Arrays.sort(mInterfaces, ClassInfo.qualifiedComparator);
275 }
276 return mInterfaces;
277 }
278
279 public ClassInfo[] realInterfaces()
280 {
281 return mRealInterfaces;
282 }
283
284 TypeInfo[] realInterfaceTypes()
285 {
286 return mRealInterfaceTypes;
287 }
288
289 public String name()
290 {
291 return mName;
292 }
293
294 public String[] nameParts()
295 {
296 return mNameParts;
297 }
298
299 public String leafName()
300 {
301 return mNameParts[mNameParts.length-1];
302 }
303
304 public String qualifiedName()
305 {
306 return mQualifiedName;
307 }
308
309 public String qualifiedTypeName()
310 {
311 return mQualifiedTypeName;
312 }
313
314 public boolean isPrimitive()
315 {
316 return mIsPrimitive;
317 }
318
319 public MethodInfo[] allConstructors() {
320 return mAllConstructors;
321 }
322
323 public MethodInfo[] constructors()
324 {
325 if (mConstructors == null) {
326 MethodInfo[] methods = mAllConstructors;
327 ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>();
328 for (int i=0; i<methods.length; i++) {
329 MethodInfo m = methods[i];
330 if (!m.isHidden()) {
331 ctors.add(m);
332 }
333 }
334 mConstructors = ctors.toArray(new MethodInfo[ctors.size()]);
335 Arrays.sort(mConstructors, MethodInfo.comparator);
336 }
337 return mConstructors;
338 }
339
340 public ClassInfo[] innerClasses()
341 {
342 return mInnerClasses;
343 }
344
345 public TagInfo[] inlineTags()
346 {
347 return comment().tags();
348 }
349
350 public TagInfo[] firstSentenceTags()
351 {
352 return comment().briefTags();
353 }
354
355 public boolean isDeprecated() {
356 boolean deprecated = false;
357 if (!mDeprecatedKnown) {
358 boolean commentDeprecated = (comment().deprecatedTags().length > 0);
359 boolean annotationDeprecated = false;
360 for (AnnotationInstanceInfo annotation : annotations()) {
361 if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) {
362 annotationDeprecated = true;
363 break;
364 }
365 }
366
367 if (commentDeprecated != annotationDeprecated) {
368 Errors.error(Errors.DEPRECATION_MISMATCH, position(),
369 "Class " + qualifiedName()
370 + ": @Deprecated annotation and @deprecated comment do not match");
371 }
372
373 mIsDeprecated = commentDeprecated | annotationDeprecated;
374 mDeprecatedKnown = true;
375 }
376 return mIsDeprecated;
377 }
378
379 public TagInfo[] deprecatedTags()
380 {
381 TagInfo[] result = comment().deprecatedTags();
382 if (result.length == 0) {
383 if (comment().undeprecateTags().length == 0) {
384 if (superclass() != null) {
385 result = superclass().deprecatedTags();
386 }
387 }
388 }
389 // should we also do the interfaces?
390 return result;
391 }
392
393 public MethodInfo[] methods()
394 {
395 if (mMethods == null) {
396 TreeMap<String,MethodInfo> all = new TreeMap<String,MethodInfo>();
397
398 ClassInfo[] ifaces = interfaces();
399 for (ClassInfo iface: ifaces) {
400 if (iface != null) {
401 MethodInfo[] inhereted = iface.methods();
402 for (MethodInfo method: inhereted) {
403 String key = method.name() + method.signature();
404 all.put(key, method);
405 }
406 }
407 }
408
409 ClassInfo superclass = superclass();
410 if (superclass != null) {
411 MethodInfo[] inhereted = superclass.methods();
412 for (MethodInfo method: inhereted) {
413 String key = method.name() + method.signature();
414 all.put(key, method);
415 }
416 }
417
418 MethodInfo[] methods = selfMethods();
419 for (MethodInfo method: methods) {
420 String key = method.name() + method.signature();
421 MethodInfo old = all.put(key, method);
422 }
423
424 mMethods = all.values().toArray(new MethodInfo[all.size()]);
425 }
426 return mMethods;
427 }
428
429 public MethodInfo[] annotationElements()
430 {
431 return mAnnotationElements;
432 }
433
434 public AnnotationInstanceInfo[] annotations()
435 {
436 return mAnnotations;
437 }
438
439 private static void addFields(ClassInfo cl, TreeMap<String,FieldInfo> all)
440 {
441 FieldInfo[] fields = cl.fields();
442 int N = fields.length;
443 for (int i=0; i<N; i++) {
444 FieldInfo f = fields[i];
445 all.put(f.name(), f);
446 }
447 }
448
449 public FieldInfo[] fields()
450 {
451 if (mFields == null) {
452 int N;
453 TreeMap<String,FieldInfo> all = new TreeMap<String,FieldInfo>();
454
455 ClassInfo[] interfaces = interfaces();
456 N = interfaces.length;
457 for (int i=0; i<N; i++) {
458 addFields(interfaces[i], all);
459 }
460
461 ClassInfo superclass = superclass();
462 if (superclass != null) {
463 addFields(superclass, all);
464 }
465
466 FieldInfo[] fields = selfFields();
467 N = fields.length;
468 for (int i=0; i<N; i++) {
469 FieldInfo f = fields[i];
470 if (!f.isHidden()) {
471 String key = f.name();
472 all.put(key, f);
473 }
474 }
475
476 mFields = all.values().toArray(new FieldInfo[0]);
477 }
478 return mFields;
479 }
480
481 public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields) {
482 FieldInfo[] flds = cl.selfFields();
483 for (FieldInfo f: flds) {
484 if (f.checkLevel()) {
485 fields.put(f.name(), f.cloneForClass(owner));
486 }
487 }
488 }
489
490 public FieldInfo[] selfFields()
491 {
492 if (mSelfFields == null) {
493 HashMap<String,FieldInfo> fields = new HashMap<String,FieldInfo>();
494 // our hidden parents
495 if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
496 gatherFields(this, mRealSuperclass, fields);
497 }
498 for (ClassInfo iface: mRealInterfaces) {
499 if (!iface.checkLevel()) {
500 gatherFields(this, iface, fields);
501 }
502 }
503 // mine
504 FieldInfo[] selfFields = mAllSelfFields;
505 for (int i=0; i<selfFields.length; i++) {
506 FieldInfo f = selfFields[i];
507 if (!f.isHidden()) {
508 fields.put(f.name(), f);
509 }
510 }
511 // combine and return in
512 mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]);
513 Arrays.sort(mSelfFields, FieldInfo.comparator);
514 }
515 return mSelfFields;
516 }
517
518 public FieldInfo[] allSelfFields() {
519 return mAllSelfFields;
520 }
521
522 public void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods) {
523 MethodInfo[] meth = cl.selfMethods();
524 for (MethodInfo m: meth) {
525 if (m.checkLevel()) {
526 methods.put(m.name()+m.signature(), m.cloneForClass(owner));
527 }
528 }
529 }
530
531 public MethodInfo[] selfMethods()
532 {
533 if (mSelfMethods == null) {
534 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
535 // our hidden parents
536 if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
537 gatherMethods(this, mRealSuperclass, methods);
538 }
539 for (ClassInfo iface: mRealInterfaces) {
540 if (!iface.checkLevel()) {
541 gatherMethods(this, iface, methods);
542 }
543 }
544 // mine
545 MethodInfo[] selfMethods = mAllSelfMethods;
546 for (int i=0; i<selfMethods.length; i++) {
547 MethodInfo m = selfMethods[i];
548 if (m.checkLevel()) {
549 methods.put(m.name()+m.signature(), m);
550 }
551 }
552 // combine and return it
553 mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]);
554 Arrays.sort(mSelfMethods, MethodInfo.comparator);
555 }
556 return mSelfMethods;
557 }
558
559 public MethodInfo[] allSelfMethods() {
560 return mAllSelfMethods;
561 }
562
563 public void addMethod(MethodInfo method) {
564 MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
565 int i = 0;
566 for (MethodInfo m : mAllSelfMethods) {
567 methods[i] = m;
568 i++;
569 }
570 methods[i] = method;
571 mAllSelfMethods = methods;
572 }
573
574 public AttributeInfo[] selfAttributes()
575 {
576 if (mSelfAttributes == null) {
577 TreeMap<FieldInfo,AttributeInfo> attrs = new TreeMap<FieldInfo,AttributeInfo>();
578
579 // the ones in the class comment won't have any methods
580 for (AttrTagInfo tag: comment().attrTags()) {
581 FieldInfo field = tag.reference();
582 if (field != null) {
583 AttributeInfo attr = attrs.get(field);
584 if (attr == null) {
585 attr = new AttributeInfo(this, field);
586 attrs.put(field, attr);
587 }
588 tag.setAttribute(attr);
589 }
590 }
591
592 // in the methods
593 for (MethodInfo m: selfMethods()) {
594 for (AttrTagInfo tag: m.comment().attrTags()) {
595 FieldInfo field = tag.reference();
596 if (field != null) {
597 AttributeInfo attr = attrs.get(field);
598 if (attr == null) {
599 attr = new AttributeInfo(this, field);
600 attrs.put(field, attr);
601 }
602 tag.setAttribute(attr);
603 attr.methods.add(m);
604 }
605 }
606 }
607
608 //constructors too
609 for (MethodInfo m: constructors()) {
610 for (AttrTagInfo tag: m.comment().attrTags()) {
611 FieldInfo field = tag.reference();
612 if (field != null) {
613 AttributeInfo attr = attrs.get(field);
614 if (attr == null) {
615 attr = new AttributeInfo(this, field);
616 attrs.put(field, attr);
617 }
618 tag.setAttribute(attr);
619 attr.methods.add(m);
620 }
621 }
622 }
623
624 mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]);
625 Arrays.sort(mSelfAttributes, AttributeInfo.comparator);
626 }
627 return mSelfAttributes;
628 }
629
630 public FieldInfo[] enumConstants()
631 {
632 return mEnumConstants;
633 }
634
635 public ClassInfo superclass()
636 {
637 if (!mSuperclassInit) {
638 if (this.checkLevel()) {
639 // rearrange our little inheritance hierarchy, because we need to hide classes that
640 // don't pass checkLevel
641 ClassInfo superclass = mRealSuperclass;
642 while (superclass != null && !superclass.checkLevel()) {
643 superclass = superclass.mRealSuperclass;
644 }
645 mSuperclass = superclass;
646 } else {
647 mSuperclass = mRealSuperclass;
648 }
649 }
650 return mSuperclass;
651 }
652
653 public ClassInfo realSuperclass()
654 {
655 return mRealSuperclass;
656 }
657
658 /** always the real superclass, not the collapsed one we get through superclass(),
659 * also has the type parameter info if it's generic.
660 */
661 public TypeInfo superclassType()
662 {
663 return mRealSuperclassType;
664 }
665
666 public TypeInfo asTypeInfo()
667 {
668 return mTypeInfo;
669 }
670
671 TypeInfo[] interfaceTypes()
672 {
673 ClassInfo[] infos = interfaces();
674 int len = infos.length;
675 TypeInfo[] types = new TypeInfo[len];
676 for (int i=0; i<len; i++) {
677 types[i] = infos[i].asTypeInfo();
678 }
679 return types;
680 }
681
682 public String htmlPage()
683 {
684 String s = containingPackage().name();
685 s = s.replace('.', '/');
686 s += '/';
687 s += name();
688 s += ".html";
689 s = DroidDoc.javadocDir + s;
690 return s;
691 }
692
693 /** Even indirectly */
694 public boolean isDerivedFrom(ClassInfo cl)
695 {
696 ClassInfo dad = this.superclass();
697 if (dad != null) {
698 if (dad.equals(cl)) {
699 return true;
700 } else {
701 if (dad.isDerivedFrom(cl)) {
702 return true;
703 }
704 }
705 }
706 for (ClassInfo iface: interfaces()) {
707 if (iface.equals(cl)) {
708 return true;
709 } else {
710 if (iface.isDerivedFrom(cl)) {
711 return true;
712 }
713 }
714 }
715 return false;
716 }
717
718 public void makeKeywordEntries(List<KeywordEntry> keywords)
719 {
720 if (!checkLevel()) {
721 return;
722 }
723
724 String htmlPage = htmlPage();
725 String qualifiedName = qualifiedName();
726
727 keywords.add(new KeywordEntry(name(), htmlPage,
728 "class in " + containingPackage().name()));
729
730 FieldInfo[] fields = selfFields();
731 FieldInfo[] enumConstants = enumConstants();
732 MethodInfo[] ctors = constructors();
733 MethodInfo[] methods = selfMethods();
734
735 // enum constants
736 for (FieldInfo field: enumConstants()) {
737 if (field.checkLevel()) {
738 keywords.add(new KeywordEntry(field.name(),
739 htmlPage + "#" + field.anchor(),
740 "enum constant in " + qualifiedName));
741 }
742 }
743
744 // constants
745 for (FieldInfo field: fields) {
746 if (field.isConstant() && field.checkLevel()) {
747 keywords.add(new KeywordEntry(field.name(),
748 htmlPage + "#" + field.anchor(),
749 "constant in " + qualifiedName));
750 }
751 }
752
753 // fields
754 for (FieldInfo field: fields) {
755 if (!field.isConstant() && field.checkLevel()) {
756 keywords.add(new KeywordEntry(field.name(),
757 htmlPage + "#" + field.anchor(),
758 "field in " + qualifiedName));
759 }
760 }
761
762 // public constructors
763 for (MethodInfo m: ctors) {
764 if (m.isPublic() && m.checkLevel()) {
765 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
766 htmlPage + "#" + m.anchor(),
767 "constructor in " + qualifiedName));
768 }
769 }
770
771 // protected constructors
772 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
773 for (MethodInfo m: ctors) {
774 if (m.isProtected() && m.checkLevel()) {
775 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
776 htmlPage + "#" + m.anchor(),
777 "constructor in " + qualifiedName));
778 }
779 }
780 }
781
782 // package private constructors
783 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
784 for (MethodInfo m: ctors) {
785 if (m.isPackagePrivate() && m.checkLevel()) {
786 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
787 htmlPage + "#" + m.anchor(),
788 "constructor in " + qualifiedName));
789 }
790 }
791 }
792
793 // private constructors
794 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
795 for (MethodInfo m: ctors) {
796 if (m.isPrivate() && m.checkLevel()) {
797 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
798 htmlPage + "#" + m.anchor(),
799 "constructor in " + qualifiedName));
800 }
801 }
802 }
803
804 // public methods
805 for (MethodInfo m: methods) {
806 if (m.isPublic() && m.checkLevel()) {
807 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
808 htmlPage + "#" + m.anchor(),
809 "method in " + qualifiedName));
810 }
811 }
812
813 // protected methods
814 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
815 for (MethodInfo m: methods) {
816 if (m.isProtected() && m.checkLevel()) {
817 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
818 htmlPage + "#" + m.anchor(),
819 "method in " + qualifiedName));
820 }
821 }
822 }
823
824 // package private methods
825 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
826 for (MethodInfo m: methods) {
827 if (m.isPackagePrivate() && m.checkLevel()) {
828 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
829 htmlPage + "#" + m.anchor(),
830 "method in " + qualifiedName));
831 }
832 }
833 }
834
835 // private methods
836 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
837 for (MethodInfo m: methods) {
838 if (m.isPrivate() && m.checkLevel()) {
839 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
840 htmlPage + "#" + m.anchor(),
841 "method in " + qualifiedName));
842 }
843 }
844 }
845 }
846
847 public void makeLink(HDF data, String base)
848 {
849 data.setValue(base + ".label", this.name());
850 if (!this.isPrimitive() && this.isIncluded() && this.checkLevel()) {
851 data.setValue(base + ".link", this.htmlPage());
852 }
853 }
854
855 public static void makeLinkListHDF(HDF data, String base, ClassInfo[] classes) {
856 final int N = classes.length;
857 for (int i=0; i<N; i++) {
858 ClassInfo cl = classes[i];
859 if (cl.checkLevel()) {
860 cl.asTypeInfo().makeHDF(data, base + "." + i);
861 }
862 }
863 }
864
865 /**
866 * Used in lists of this class (packages, nested classes, known subclasses)
867 */
868 public void makeShortDescrHDF(HDF data, String base)
869 {
870 mTypeInfo.makeHDF(data, base + ".type");
871 data.setValue(base + ".kind", this.kind());
872 TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags());
873 TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
874 }
875
876 /**
877 * Turns into the main class page
878 */
879 public void makeHDF(HDF data)
880 {
881 int i, j, n;
882 String name = name();
883 String qualified = qualifiedName();
884 AttributeInfo[] selfAttributes = selfAttributes();
885 MethodInfo[] methods = selfMethods();
886 FieldInfo[] fields = selfFields();
887 FieldInfo[] enumConstants = enumConstants();
888 MethodInfo[] ctors = constructors();
889 ClassInfo[] inners = innerClasses();
890
891 // class name
892 mTypeInfo.makeHDF(data, "class.type");
893 mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType");
894 data.setValue("class.name", name);
895 data.setValue("class.qualified", qualified);
896 String scope = "";
897 if (isProtected()) {
898 data.setValue("class.scope", "protected");
899 }
900 else if (isPublic()) {
901 data.setValue("class.scope", "public");
902 }
903 if (isStatic()) {
904 data.setValue("class.static", "static");
905 }
906 if (isFinal()) {
907 data.setValue("class.final", "final");
908 }
909 if (isAbstract() && !isInterface()) {
910 data.setValue("class.abstract", "abstract");
911 }
912
913 // class info
914 String kind = kind();
915 if (kind != null) {
916 data.setValue("class.kind", kind);
917 }
918
919 // the containing package -- note that this can be passed to type_link,
920 // but it also contains the list of all of the packages
921 containingPackage().makeClassLinkListHDF(data, "class.package");
922
923 // inheritance hierarchy
924 Vector<ClassInfo> superClasses = new Vector<ClassInfo>();
925 superClasses.add(this);
926 ClassInfo supr = superclass();
927 while (supr != null) {
928 superClasses.add(supr);
929 supr = supr.superclass();
930 }
931 n = superClasses.size();
932 for (i=0; i<n; i++) {
933 supr = superClasses.elementAt(n-i-1);
934
935 supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class");
936 supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class");
937 j = 0;
938 for (TypeInfo t: supr.interfaceTypes()) {
939 t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j);
940 j++;
941 }
942 }
943
944 // class description
945 TagInfo.makeHDF(data, "class.descr", inlineTags());
946 TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags());
947 TagInfo.makeHDF(data, "class.deprecated", deprecatedTags());
948
949 // known subclasses
950 TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>();
951 TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>();
952 ClassInfo[] all = Converter.rootClasses();
953 for (ClassInfo cl: all) {
954 if (cl.superclass() != null && cl.superclass().equals(this)) {
955 direct.put(cl.name(), cl);
956 }
957 else if (cl.isDerivedFrom(this)) {
958 indirect.put(cl.name(), cl);
959 }
960 }
961 // direct
962 i = 0;
963 for (ClassInfo cl: direct.values()) {
964 if (cl.checkLevel()) {
965 cl.makeShortDescrHDF(data, "class.subclasses.direct." + i);
966 }
967 i++;
968 }
969 // indirect
970 i = 0;
971 for (ClassInfo cl: indirect.values()) {
972 if (cl.checkLevel()) {
973 cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i);
974 }
975 i++;
976 }
977
978 // nested classes
979 i=0;
980 for (ClassInfo inner: inners) {
981 if (inner.checkLevel()) {
982 inner.makeShortDescrHDF(data, "class.inners." + i);
983 }
984 i++;
985 }
986
987 // enum constants
988 i=0;
989 for (FieldInfo field: enumConstants) {
990 if (field.isConstant()) {
991 field.makeHDF(data, "class.enumConstants." + i);
992 i++;
993 }
994 }
995
996 // constants
997 i=0;
998 for (FieldInfo field: fields) {
999 if (field.isConstant()) {
1000 field.makeHDF(data, "class.constants." + i);
1001 i++;
1002 }
1003 }
1004
1005 // fields
1006 i=0;
1007 for (FieldInfo field: fields) {
1008 if (!field.isConstant()) {
1009 field.makeHDF(data, "class.fields." + i);
1010 i++;
1011 }
1012 }
1013
1014 // public constructors
1015 i=0;
1016 for (MethodInfo ctor: ctors) {
1017 if (ctor.isPublic()) {
1018 ctor.makeHDF(data, "class.ctors.public." + i);
1019 i++;
1020 }
1021 }
1022
1023 // protected constructors
1024 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1025 i=0;
1026 for (MethodInfo ctor: ctors) {
1027 if (ctor.isProtected()) {
1028 ctor.makeHDF(data, "class.ctors.protected." + i);
1029 i++;
1030 }
1031 }
1032 }
1033
1034 // package private constructors
1035 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1036 i=0;
1037 for (MethodInfo ctor: ctors) {
1038 if (ctor.isPackagePrivate()) {
1039 ctor.makeHDF(data, "class.ctors.package." + i);
1040 i++;
1041 }
1042 }
1043 }
1044
1045 // private constructors
1046 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1047 i=0;
1048 for (MethodInfo ctor: ctors) {
1049 if (ctor.isPrivate()) {
1050 ctor.makeHDF(data, "class.ctors.private." + i);
1051 i++;
1052 }
1053 }
1054 }
1055
1056 // public methods
1057 i=0;
1058 for (MethodInfo method: methods) {
1059 if (method.isPublic()) {
1060 method.makeHDF(data, "class.methods.public." + i);
1061 i++;
1062 }
1063 }
1064
1065 // protected methods
1066 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1067 i=0;
1068 for (MethodInfo method: methods) {
1069 if (method.isProtected()) {
1070 method.makeHDF(data, "class.methods.protected." + i);
1071 i++;
1072 }
1073 }
1074 }
1075
1076 // package private methods
1077 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1078 i=0;
1079 for (MethodInfo method: methods) {
1080 if (method.isPackagePrivate()) {
1081 method.makeHDF(data, "class.methods.package." + i);
1082 i++;
1083 }
1084 }
1085 }
1086
1087 // private methods
1088 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1089 i=0;
1090 for (MethodInfo method: methods) {
1091 if (method.isPrivate()) {
1092 method.makeHDF(data, "class.methods.private." + i);
1093 i++;
1094 }
1095 }
1096 }
1097
1098 // xml attributes
1099 i=0;
1100 for (AttributeInfo attr: selfAttributes) {
1101 if (attr.checkLevel()) {
1102 attr.makeHDF(data, "class.attrs." + i);
1103 i++;
1104 }
1105 }
1106
1107 // inherited methods
1108 Set<ClassInfo> interfaces = new TreeSet<ClassInfo>();
1109 addInterfaces(interfaces(), interfaces);
1110 ClassInfo cl = superclass();
1111 i=0;
1112 while (cl != null) {
1113 addInterfaces(cl.interfaces(), interfaces);
1114 makeInheritedHDF(data, i, cl);
1115 cl = cl.superclass();
1116 i++;
1117 }
1118 for (ClassInfo iface: interfaces) {
1119 makeInheritedHDF(data, i, iface);
1120 i++;
1121 }
1122 }
1123
1124 private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out)
1125 {
1126 for (ClassInfo cl: ifaces) {
1127 out.add(cl);
1128 addInterfaces(cl.interfaces(), out);
1129 }
1130 }
1131
1132 private static void makeInheritedHDF(HDF data, int index, ClassInfo cl)
1133 {
1134 int i;
1135
1136 String base = "class.inherited." + index;
1137 data.setValue(base + ".qualified", cl.qualifiedName());
1138 if (cl.checkLevel()) {
1139 data.setValue(base + ".link", cl.htmlPage());
1140 }
1141 String kind = cl.kind();
1142 if (kind != null) {
1143 data.setValue(base + ".kind", kind);
1144 }
1145
1146 // xml attributes
1147 i=0;
1148 for (AttributeInfo attr: cl.selfAttributes()) {
1149 attr.makeHDF(data, base + ".attrs." + i);
1150 i++;
1151 }
1152
1153 // methods
1154 i=0;
1155 for (MethodInfo method: cl.selfMethods()) {
1156 method.makeHDF(data, base + ".methods." + i);
1157 i++;
1158 }
1159
1160 // fields
1161 i=0;
1162 for (FieldInfo field: cl.selfFields()) {
1163 if (!field.isConstant()) {
1164 field.makeHDF(data, base + ".fields." + i);
1165 i++;
1166 }
1167 }
1168
1169 // constants
1170 i=0;
1171 for (FieldInfo field: cl.selfFields()) {
1172 if (field.isConstant()) {
1173 field.makeHDF(data, base + ".constants." + i);
1174 i++;
1175 }
1176 }
1177 }
1178
1179 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();
1196 if (pkg.isHidden()) {
1197 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 }
1310
1311 // 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 }
1355
1356 public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
1357 mNonWrittenConstructors = nonWritten;
1358 }
1359
1360 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 }
1386
1387 public void setHiddenMethods(MethodInfo[] mInfo){
1388 mHiddenMethods = mInfo;
1389 }
1390 public MethodInfo[] getHiddenMethods(){
1391 return mHiddenMethods;
1392 }
1393 public String toString(){
1394 return this.qualifiedName();
1395 }
1396
1397 public void setReasonIncluded(String reason) {
1398 mReasonIncluded = reason;
1399 }
1400
1401 public String getReasonIncluded() {
1402 return mReasonIncluded;
1403 }
1404
1405 private ClassDoc mClass;
1406
1407 // ctor
1408 private boolean mIsPublic;
1409 private boolean mIsProtected;
1410 private boolean mIsPackagePrivate;
1411 private boolean mIsPrivate;
1412 private boolean mIsStatic;
1413 private boolean mIsInterface;
1414 private boolean mIsAbstract;
1415 private boolean mIsOrdinaryClass;
1416 private boolean mIsException;
1417 private boolean mIsError;
1418 private boolean mIsEnum;
1419 private boolean mIsAnnotation;
1420 private boolean mIsFinal;
1421 private boolean mIsIncluded;
1422 private String mName;
1423 private String mQualifiedName;
1424 private String mQualifiedTypeName;
1425 private boolean mIsPrimitive;
1426 private TypeInfo mTypeInfo;
1427 private String[] mNameParts;
1428
1429 // init
1430 private ClassInfo[] mRealInterfaces;
1431 private ClassInfo[] mInterfaces;
1432 private TypeInfo[] mRealInterfaceTypes;
1433 private ClassInfo[] mInnerClasses;
1434 private MethodInfo[] mAllConstructors;
1435 private MethodInfo[] mAllSelfMethods;
1436 private MethodInfo[] mAnnotationElements; // if this class is an annotation
1437 private FieldInfo[] mAllSelfFields;
1438 private FieldInfo[] mEnumConstants;
1439 private PackageInfo mContainingPackage;
1440 private ClassInfo mContainingClass;
1441 private ClassInfo mRealSuperclass;
1442 private TypeInfo mRealSuperclassType;
1443 private ClassInfo mSuperclass;
1444 private AnnotationInstanceInfo[] mAnnotations;
1445 private boolean mSuperclassInit;
1446 private boolean mDeprecatedKnown;
1447
1448 // lazy
1449 private MethodInfo[] mConstructors;
1450 private ClassInfo[] mRealInnerClasses;
1451 private MethodInfo[] mSelfMethods;
1452 private FieldInfo[] mSelfFields;
1453 private AttributeInfo[] mSelfAttributes;
1454 private MethodInfo[] mMethods;
1455 private FieldInfo[] mFields;
1456 private TypeInfo[] mTypeParameters;
1457 private MethodInfo[] mHiddenMethods;
1458 private int mHidden = -1;
1459 private int mCheckLevel = -1;
1460 private String mReasonIncluded;
1461 private MethodInfo[] mNonWrittenConstructors;
1462 private boolean mIsDeprecated;
1463}