blob: 81804361a05e17535eaa7c6fe1614781222eb530 [file] [log] [blame]
The Android Open Source Project88b60792009-03-03 19:28:42 -08001/*
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 {
The Android Open Source Project88b60792009-03-03 19:28:42 -0800381 // should we also do the interfaces?
Dirk Dougherty40a06d82009-05-05 13:41:56 -0700382 return comment().deprecatedTags();
The Android Open Source Project88b60792009-03-03 19:28:42 -0800383 }
384
385 public MethodInfo[] methods()
386 {
387 if (mMethods == null) {
388 TreeMap<String,MethodInfo> all = new TreeMap<String,MethodInfo>();
389
390 ClassInfo[] ifaces = interfaces();
391 for (ClassInfo iface: ifaces) {
392 if (iface != null) {
393 MethodInfo[] inhereted = iface.methods();
394 for (MethodInfo method: inhereted) {
395 String key = method.name() + method.signature();
396 all.put(key, method);
397 }
398 }
399 }
400
401 ClassInfo superclass = superclass();
402 if (superclass != null) {
403 MethodInfo[] inhereted = superclass.methods();
404 for (MethodInfo method: inhereted) {
405 String key = method.name() + method.signature();
406 all.put(key, method);
407 }
408 }
409
410 MethodInfo[] methods = selfMethods();
411 for (MethodInfo method: methods) {
412 String key = method.name() + method.signature();
413 MethodInfo old = all.put(key, method);
414 }
415
416 mMethods = all.values().toArray(new MethodInfo[all.size()]);
417 }
418 return mMethods;
419 }
420
421 public MethodInfo[] annotationElements()
422 {
423 return mAnnotationElements;
424 }
425
426 public AnnotationInstanceInfo[] annotations()
427 {
428 return mAnnotations;
429 }
430
431 private static void addFields(ClassInfo cl, TreeMap<String,FieldInfo> all)
432 {
433 FieldInfo[] fields = cl.fields();
434 int N = fields.length;
435 for (int i=0; i<N; i++) {
436 FieldInfo f = fields[i];
437 all.put(f.name(), f);
438 }
439 }
440
441 public FieldInfo[] fields()
442 {
443 if (mFields == null) {
444 int N;
445 TreeMap<String,FieldInfo> all = new TreeMap<String,FieldInfo>();
446
447 ClassInfo[] interfaces = interfaces();
448 N = interfaces.length;
449 for (int i=0; i<N; i++) {
450 addFields(interfaces[i], all);
451 }
452
453 ClassInfo superclass = superclass();
454 if (superclass != null) {
455 addFields(superclass, all);
456 }
457
458 FieldInfo[] fields = selfFields();
459 N = fields.length;
460 for (int i=0; i<N; i++) {
461 FieldInfo f = fields[i];
462 if (!f.isHidden()) {
463 String key = f.name();
464 all.put(key, f);
465 }
466 }
467
468 mFields = all.values().toArray(new FieldInfo[0]);
469 }
470 return mFields;
471 }
472
473 public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields) {
474 FieldInfo[] flds = cl.selfFields();
475 for (FieldInfo f: flds) {
476 if (f.checkLevel()) {
477 fields.put(f.name(), f.cloneForClass(owner));
478 }
479 }
480 }
481
482 public FieldInfo[] selfFields()
483 {
484 if (mSelfFields == null) {
485 HashMap<String,FieldInfo> fields = new HashMap<String,FieldInfo>();
486 // our hidden parents
487 if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
488 gatherFields(this, mRealSuperclass, fields);
489 }
490 for (ClassInfo iface: mRealInterfaces) {
491 if (!iface.checkLevel()) {
492 gatherFields(this, iface, fields);
493 }
494 }
495 // mine
496 FieldInfo[] selfFields = mAllSelfFields;
497 for (int i=0; i<selfFields.length; i++) {
498 FieldInfo f = selfFields[i];
499 if (!f.isHidden()) {
500 fields.put(f.name(), f);
501 }
502 }
503 // combine and return in
504 mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]);
505 Arrays.sort(mSelfFields, FieldInfo.comparator);
506 }
507 return mSelfFields;
508 }
509
510 public FieldInfo[] allSelfFields() {
511 return mAllSelfFields;
512 }
513
514 public void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods) {
515 MethodInfo[] meth = cl.selfMethods();
516 for (MethodInfo m: meth) {
517 if (m.checkLevel()) {
518 methods.put(m.name()+m.signature(), m.cloneForClass(owner));
519 }
520 }
521 }
522
523 public MethodInfo[] selfMethods()
524 {
525 if (mSelfMethods == null) {
526 HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>();
527 // our hidden parents
528 if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) {
529 gatherMethods(this, mRealSuperclass, methods);
530 }
531 for (ClassInfo iface: mRealInterfaces) {
532 if (!iface.checkLevel()) {
533 gatherMethods(this, iface, methods);
534 }
535 }
536 // mine
537 MethodInfo[] selfMethods = mAllSelfMethods;
538 for (int i=0; i<selfMethods.length; i++) {
539 MethodInfo m = selfMethods[i];
540 if (m.checkLevel()) {
541 methods.put(m.name()+m.signature(), m);
542 }
543 }
544 // combine and return it
545 mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]);
546 Arrays.sort(mSelfMethods, MethodInfo.comparator);
547 }
548 return mSelfMethods;
549 }
550
551 public MethodInfo[] allSelfMethods() {
552 return mAllSelfMethods;
553 }
554
555 public void addMethod(MethodInfo method) {
556 MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1];
557 int i = 0;
558 for (MethodInfo m : mAllSelfMethods) {
559 methods[i] = m;
560 i++;
561 }
562 methods[i] = method;
563 mAllSelfMethods = methods;
564 }
565
566 public AttributeInfo[] selfAttributes()
567 {
568 if (mSelfAttributes == null) {
569 TreeMap<FieldInfo,AttributeInfo> attrs = new TreeMap<FieldInfo,AttributeInfo>();
570
571 // the ones in the class comment won't have any methods
572 for (AttrTagInfo tag: comment().attrTags()) {
573 FieldInfo field = tag.reference();
574 if (field != null) {
575 AttributeInfo attr = attrs.get(field);
576 if (attr == null) {
577 attr = new AttributeInfo(this, field);
578 attrs.put(field, attr);
579 }
580 tag.setAttribute(attr);
581 }
582 }
583
584 // in the methods
585 for (MethodInfo m: selfMethods()) {
586 for (AttrTagInfo tag: m.comment().attrTags()) {
587 FieldInfo field = tag.reference();
588 if (field != null) {
589 AttributeInfo attr = attrs.get(field);
590 if (attr == null) {
591 attr = new AttributeInfo(this, field);
592 attrs.put(field, attr);
593 }
594 tag.setAttribute(attr);
595 attr.methods.add(m);
596 }
597 }
598 }
599
600 //constructors too
601 for (MethodInfo m: constructors()) {
602 for (AttrTagInfo tag: m.comment().attrTags()) {
603 FieldInfo field = tag.reference();
604 if (field != null) {
605 AttributeInfo attr = attrs.get(field);
606 if (attr == null) {
607 attr = new AttributeInfo(this, field);
608 attrs.put(field, attr);
609 }
610 tag.setAttribute(attr);
611 attr.methods.add(m);
612 }
613 }
614 }
615
616 mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]);
617 Arrays.sort(mSelfAttributes, AttributeInfo.comparator);
618 }
619 return mSelfAttributes;
620 }
621
622 public FieldInfo[] enumConstants()
623 {
624 return mEnumConstants;
625 }
626
627 public ClassInfo superclass()
628 {
629 if (!mSuperclassInit) {
630 if (this.checkLevel()) {
631 // rearrange our little inheritance hierarchy, because we need to hide classes that
632 // don't pass checkLevel
633 ClassInfo superclass = mRealSuperclass;
634 while (superclass != null && !superclass.checkLevel()) {
635 superclass = superclass.mRealSuperclass;
636 }
637 mSuperclass = superclass;
638 } else {
639 mSuperclass = mRealSuperclass;
640 }
641 }
642 return mSuperclass;
643 }
644
645 public ClassInfo realSuperclass()
646 {
647 return mRealSuperclass;
648 }
649
650 /** always the real superclass, not the collapsed one we get through superclass(),
651 * also has the type parameter info if it's generic.
652 */
653 public TypeInfo superclassType()
654 {
655 return mRealSuperclassType;
656 }
657
658 public TypeInfo asTypeInfo()
659 {
660 return mTypeInfo;
661 }
662
663 TypeInfo[] interfaceTypes()
664 {
665 ClassInfo[] infos = interfaces();
666 int len = infos.length;
667 TypeInfo[] types = new TypeInfo[len];
668 for (int i=0; i<len; i++) {
669 types[i] = infos[i].asTypeInfo();
670 }
671 return types;
672 }
673
674 public String htmlPage()
675 {
676 String s = containingPackage().name();
677 s = s.replace('.', '/');
678 s += '/';
679 s += name();
680 s += ".html";
681 s = DroidDoc.javadocDir + s;
682 return s;
683 }
684
685 /** Even indirectly */
686 public boolean isDerivedFrom(ClassInfo cl)
687 {
688 ClassInfo dad = this.superclass();
689 if (dad != null) {
690 if (dad.equals(cl)) {
691 return true;
692 } else {
693 if (dad.isDerivedFrom(cl)) {
694 return true;
695 }
696 }
697 }
698 for (ClassInfo iface: interfaces()) {
699 if (iface.equals(cl)) {
700 return true;
701 } else {
702 if (iface.isDerivedFrom(cl)) {
703 return true;
704 }
705 }
706 }
707 return false;
708 }
709
710 public void makeKeywordEntries(List<KeywordEntry> keywords)
711 {
712 if (!checkLevel()) {
713 return;
714 }
715
716 String htmlPage = htmlPage();
717 String qualifiedName = qualifiedName();
718
719 keywords.add(new KeywordEntry(name(), htmlPage,
720 "class in " + containingPackage().name()));
721
722 FieldInfo[] fields = selfFields();
723 FieldInfo[] enumConstants = enumConstants();
724 MethodInfo[] ctors = constructors();
725 MethodInfo[] methods = selfMethods();
726
727 // enum constants
728 for (FieldInfo field: enumConstants()) {
729 if (field.checkLevel()) {
730 keywords.add(new KeywordEntry(field.name(),
731 htmlPage + "#" + field.anchor(),
732 "enum constant in " + qualifiedName));
733 }
734 }
735
736 // constants
737 for (FieldInfo field: fields) {
738 if (field.isConstant() && field.checkLevel()) {
739 keywords.add(new KeywordEntry(field.name(),
740 htmlPage + "#" + field.anchor(),
741 "constant in " + qualifiedName));
742 }
743 }
744
745 // fields
746 for (FieldInfo field: fields) {
747 if (!field.isConstant() && field.checkLevel()) {
748 keywords.add(new KeywordEntry(field.name(),
749 htmlPage + "#" + field.anchor(),
750 "field in " + qualifiedName));
751 }
752 }
753
754 // public constructors
755 for (MethodInfo m: ctors) {
756 if (m.isPublic() && m.checkLevel()) {
757 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
758 htmlPage + "#" + m.anchor(),
759 "constructor in " + qualifiedName));
760 }
761 }
762
763 // protected constructors
764 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
765 for (MethodInfo m: ctors) {
766 if (m.isProtected() && m.checkLevel()) {
767 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
768 htmlPage + "#" + m.anchor(),
769 "constructor in " + qualifiedName));
770 }
771 }
772 }
773
774 // package private constructors
775 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
776 for (MethodInfo m: ctors) {
777 if (m.isPackagePrivate() && m.checkLevel()) {
778 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
779 htmlPage + "#" + m.anchor(),
780 "constructor in " + qualifiedName));
781 }
782 }
783 }
784
785 // private constructors
786 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
787 for (MethodInfo m: ctors) {
788 if (m.isPrivate() && m.checkLevel()) {
789 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
790 htmlPage + "#" + m.anchor(),
791 "constructor in " + qualifiedName));
792 }
793 }
794 }
795
796 // public methods
797 for (MethodInfo m: methods) {
798 if (m.isPublic() && m.checkLevel()) {
799 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
800 htmlPage + "#" + m.anchor(),
801 "method in " + qualifiedName));
802 }
803 }
804
805 // protected methods
806 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
807 for (MethodInfo m: methods) {
808 if (m.isProtected() && m.checkLevel()) {
809 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
810 htmlPage + "#" + m.anchor(),
811 "method in " + qualifiedName));
812 }
813 }
814 }
815
816 // package private methods
817 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
818 for (MethodInfo m: methods) {
819 if (m.isPackagePrivate() && m.checkLevel()) {
820 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
821 htmlPage + "#" + m.anchor(),
822 "method in " + qualifiedName));
823 }
824 }
825 }
826
827 // private methods
828 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
829 for (MethodInfo m: methods) {
830 if (m.isPrivate() && m.checkLevel()) {
831 keywords.add(new KeywordEntry(m.name() + m.prettySignature(),
832 htmlPage + "#" + m.anchor(),
833 "method in " + qualifiedName));
834 }
835 }
836 }
837 }
838
839 public void makeLink(HDF data, String base)
840 {
841 data.setValue(base + ".label", this.name());
842 if (!this.isPrimitive() && this.isIncluded() && this.checkLevel()) {
843 data.setValue(base + ".link", this.htmlPage());
844 }
845 }
846
847 public static void makeLinkListHDF(HDF data, String base, ClassInfo[] classes) {
848 final int N = classes.length;
849 for (int i=0; i<N; i++) {
850 ClassInfo cl = classes[i];
851 if (cl.checkLevel()) {
852 cl.asTypeInfo().makeHDF(data, base + "." + i);
853 }
854 }
855 }
856
857 /**
858 * Used in lists of this class (packages, nested classes, known subclasses)
859 */
860 public void makeShortDescrHDF(HDF data, String base)
861 {
862 mTypeInfo.makeHDF(data, base + ".type");
863 data.setValue(base + ".kind", this.kind());
864 TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags());
865 TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags());
Scott Main25fda192009-08-04 11:26:30 -0700866 data.setValue(base + ".since", getSince());
The Android Open Source Project88b60792009-03-03 19:28:42 -0800867 }
868
869 /**
870 * Turns into the main class page
871 */
872 public void makeHDF(HDF data)
873 {
874 int i, j, n;
875 String name = name();
876 String qualified = qualifiedName();
877 AttributeInfo[] selfAttributes = selfAttributes();
878 MethodInfo[] methods = selfMethods();
879 FieldInfo[] fields = selfFields();
880 FieldInfo[] enumConstants = enumConstants();
881 MethodInfo[] ctors = constructors();
882 ClassInfo[] inners = innerClasses();
883
884 // class name
885 mTypeInfo.makeHDF(data, "class.type");
886 mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType");
887 data.setValue("class.name", name);
888 data.setValue("class.qualified", qualified);
889 String scope = "";
890 if (isProtected()) {
891 data.setValue("class.scope", "protected");
892 }
893 else if (isPublic()) {
894 data.setValue("class.scope", "public");
895 }
896 if (isStatic()) {
897 data.setValue("class.static", "static");
898 }
899 if (isFinal()) {
900 data.setValue("class.final", "final");
901 }
902 if (isAbstract() && !isInterface()) {
903 data.setValue("class.abstract", "abstract");
904 }
905
906 // class info
907 String kind = kind();
908 if (kind != null) {
909 data.setValue("class.kind", kind);
910 }
Jesse Wilson289d80e2009-07-21 14:02:14 -0700911 data.setValue("class.since", getSince());
The Android Open Source Project88b60792009-03-03 19:28:42 -0800912
913 // the containing package -- note that this can be passed to type_link,
914 // but it also contains the list of all of the packages
915 containingPackage().makeClassLinkListHDF(data, "class.package");
916
917 // inheritance hierarchy
918 Vector<ClassInfo> superClasses = new Vector<ClassInfo>();
919 superClasses.add(this);
920 ClassInfo supr = superclass();
921 while (supr != null) {
922 superClasses.add(supr);
923 supr = supr.superclass();
924 }
925 n = superClasses.size();
926 for (i=0; i<n; i++) {
927 supr = superClasses.elementAt(n-i-1);
928
929 supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class");
930 supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class");
931 j = 0;
932 for (TypeInfo t: supr.interfaceTypes()) {
933 t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j);
934 j++;
935 }
936 }
937
938 // class description
939 TagInfo.makeHDF(data, "class.descr", inlineTags());
940 TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags());
941 TagInfo.makeHDF(data, "class.deprecated", deprecatedTags());
942
943 // known subclasses
944 TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>();
945 TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>();
946 ClassInfo[] all = Converter.rootClasses();
947 for (ClassInfo cl: all) {
948 if (cl.superclass() != null && cl.superclass().equals(this)) {
949 direct.put(cl.name(), cl);
950 }
951 else if (cl.isDerivedFrom(this)) {
952 indirect.put(cl.name(), cl);
953 }
954 }
955 // direct
956 i = 0;
957 for (ClassInfo cl: direct.values()) {
958 if (cl.checkLevel()) {
959 cl.makeShortDescrHDF(data, "class.subclasses.direct." + i);
960 }
961 i++;
962 }
963 // indirect
964 i = 0;
965 for (ClassInfo cl: indirect.values()) {
966 if (cl.checkLevel()) {
967 cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i);
968 }
969 i++;
970 }
971
972 // nested classes
973 i=0;
974 for (ClassInfo inner: inners) {
975 if (inner.checkLevel()) {
976 inner.makeShortDescrHDF(data, "class.inners." + i);
977 }
978 i++;
979 }
980
981 // enum constants
982 i=0;
983 for (FieldInfo field: enumConstants) {
984 if (field.isConstant()) {
985 field.makeHDF(data, "class.enumConstants." + i);
986 i++;
987 }
988 }
989
990 // constants
991 i=0;
992 for (FieldInfo field: fields) {
993 if (field.isConstant()) {
994 field.makeHDF(data, "class.constants." + i);
995 i++;
996 }
997 }
998
999 // fields
1000 i=0;
1001 for (FieldInfo field: fields) {
1002 if (!field.isConstant()) {
1003 field.makeHDF(data, "class.fields." + i);
1004 i++;
1005 }
1006 }
1007
1008 // public constructors
1009 i=0;
1010 for (MethodInfo ctor: ctors) {
1011 if (ctor.isPublic()) {
1012 ctor.makeHDF(data, "class.ctors.public." + i);
1013 i++;
1014 }
1015 }
1016
1017 // protected constructors
1018 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1019 i=0;
1020 for (MethodInfo ctor: ctors) {
1021 if (ctor.isProtected()) {
1022 ctor.makeHDF(data, "class.ctors.protected." + i);
1023 i++;
1024 }
1025 }
1026 }
1027
1028 // package private constructors
1029 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1030 i=0;
1031 for (MethodInfo ctor: ctors) {
1032 if (ctor.isPackagePrivate()) {
1033 ctor.makeHDF(data, "class.ctors.package." + i);
1034 i++;
1035 }
1036 }
1037 }
1038
1039 // private constructors
1040 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1041 i=0;
1042 for (MethodInfo ctor: ctors) {
1043 if (ctor.isPrivate()) {
1044 ctor.makeHDF(data, "class.ctors.private." + i);
1045 i++;
1046 }
1047 }
1048 }
1049
1050 // public methods
1051 i=0;
1052 for (MethodInfo method: methods) {
1053 if (method.isPublic()) {
1054 method.makeHDF(data, "class.methods.public." + i);
1055 i++;
1056 }
1057 }
1058
1059 // protected methods
1060 if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) {
1061 i=0;
1062 for (MethodInfo method: methods) {
1063 if (method.isProtected()) {
1064 method.makeHDF(data, "class.methods.protected." + i);
1065 i++;
1066 }
1067 }
1068 }
1069
1070 // package private methods
1071 if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) {
1072 i=0;
1073 for (MethodInfo method: methods) {
1074 if (method.isPackagePrivate()) {
1075 method.makeHDF(data, "class.methods.package." + i);
1076 i++;
1077 }
1078 }
1079 }
1080
1081 // private methods
1082 if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) {
1083 i=0;
1084 for (MethodInfo method: methods) {
1085 if (method.isPrivate()) {
1086 method.makeHDF(data, "class.methods.private." + i);
1087 i++;
1088 }
1089 }
1090 }
1091
1092 // xml attributes
1093 i=0;
1094 for (AttributeInfo attr: selfAttributes) {
1095 if (attr.checkLevel()) {
1096 attr.makeHDF(data, "class.attrs." + i);
1097 i++;
1098 }
1099 }
1100
1101 // inherited methods
1102 Set<ClassInfo> interfaces = new TreeSet<ClassInfo>();
1103 addInterfaces(interfaces(), interfaces);
1104 ClassInfo cl = superclass();
1105 i=0;
1106 while (cl != null) {
1107 addInterfaces(cl.interfaces(), interfaces);
1108 makeInheritedHDF(data, i, cl);
1109 cl = cl.superclass();
1110 i++;
1111 }
1112 for (ClassInfo iface: interfaces) {
1113 makeInheritedHDF(data, i, iface);
1114 i++;
1115 }
1116 }
1117
1118 private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out)
1119 {
1120 for (ClassInfo cl: ifaces) {
1121 out.add(cl);
1122 addInterfaces(cl.interfaces(), out);
1123 }
1124 }
1125
1126 private static void makeInheritedHDF(HDF data, int index, ClassInfo cl)
1127 {
1128 int i;
1129
1130 String base = "class.inherited." + index;
1131 data.setValue(base + ".qualified", cl.qualifiedName());
1132 if (cl.checkLevel()) {
1133 data.setValue(base + ".link", cl.htmlPage());
1134 }
1135 String kind = cl.kind();
1136 if (kind != null) {
1137 data.setValue(base + ".kind", kind);
1138 }
1139
1140 // xml attributes
1141 i=0;
1142 for (AttributeInfo attr: cl.selfAttributes()) {
1143 attr.makeHDF(data, base + ".attrs." + i);
1144 i++;
1145 }
1146
1147 // methods
1148 i=0;
1149 for (MethodInfo method: cl.selfMethods()) {
1150 method.makeHDF(data, base + ".methods." + i);
1151 i++;
1152 }
1153
1154 // fields
1155 i=0;
1156 for (FieldInfo field: cl.selfFields()) {
1157 if (!field.isConstant()) {
1158 field.makeHDF(data, base + ".fields." + i);
1159 i++;
1160 }
1161 }
1162
1163 // constants
1164 i=0;
1165 for (FieldInfo field: cl.selfFields()) {
1166 if (field.isConstant()) {
1167 field.makeHDF(data, base + ".constants." + i);
1168 i++;
1169 }
1170 }
1171 }
1172
1173 public boolean isHidden()
1174 {
1175 int val = mHidden;
1176 if (val >= 0) {
1177 return val != 0;
1178 } else {
1179 boolean v = isHiddenImpl();
1180 mHidden = v ? 1 : 0;
1181 return v;
1182 }
1183 }
1184
1185 public boolean isHiddenImpl()
1186 {
1187 ClassInfo cl = this;
1188 while (cl != null) {
1189 PackageInfo pkg = cl.containingPackage();
The Android Open Source Projectf122bec2009-03-18 17:39:42 -07001190 if (pkg != null && pkg.isHidden()) {
The Android Open Source Project88b60792009-03-03 19:28:42 -08001191 return true;
1192 }
1193 if (cl.comment().isHidden()) {
1194 return true;
1195 }
1196 cl = cl.containingClass();
1197 }
1198 return false;
1199 }
1200
1201 private MethodInfo matchMethod(MethodInfo[] methods, String name,
1202 String[] params, String[] dimensions)
1203 {
1204 int len = methods.length;
1205 for (int i=0; i<len; i++) {
1206 MethodInfo method = methods[i];
1207 if (method.name().equals(name)) {
1208 if (params == null) {
1209 return method;
1210 } else {
1211 if (method.matchesParams(params, dimensions)) {
1212 return method;
1213 }
1214 }
1215 }
1216 }
1217 return null;
1218 }
1219
1220 public MethodInfo findMethod(String name,
1221 String[] params, String[] dimensions)
1222 {
1223 // first look on our class, and our superclasses
1224
1225 // for methods
1226 MethodInfo rv;
1227 rv = matchMethod(methods(), name, params, dimensions);
1228
1229 if (rv != null) {
1230 return rv;
1231 }
1232
1233 // for constructors
1234 rv = matchMethod(constructors(), name, params, dimensions);
1235 if (rv != null) {
1236 return rv;
1237 }
1238
1239 // then recursively look at our containing class
1240 ClassInfo containing = containingClass();
1241 if (containing != null) {
1242 return containing.findMethod(name, params, dimensions);
1243 }
1244
1245 return null;
1246 }
1247
1248 private ClassInfo searchInnerClasses(String[] nameParts, int index)
1249 {
1250 String part = nameParts[index];
1251
1252 ClassInfo[] inners = mInnerClasses;
1253 for (ClassInfo in: inners) {
1254 String[] innerParts = in.nameParts();
1255 if (part.equals(innerParts[innerParts.length-1])) {
1256 if (index == nameParts.length-1) {
1257 return in;
1258 } else {
1259 return in.searchInnerClasses(nameParts, index+1);
1260 }
1261 }
1262 }
1263 return null;
1264 }
1265
1266 public ClassInfo extendedFindClass(String className)
1267 {
1268 // ClassDoc.findClass has this bug that we're working around here:
1269 // If you have a class PackageManager with an inner class PackageInfo
1270 // and you call it with "PackageInfo" it doesn't find it.
1271 return searchInnerClasses(className.split("\\."), 0);
1272 }
1273
1274 public ClassInfo findClass(String className)
1275 {
1276 return Converter.obtainClass(mClass.findClass(className));
1277 }
1278
1279 public ClassInfo findInnerClass(String className)
1280 {
1281 // ClassDoc.findClass won't find inner classes. To deal with that,
1282 // we try what they gave us first, but if that didn't work, then
1283 // we see if there are any periods in className, and start searching
1284 // from there.
1285 String[] nodes = className.split("\\.");
1286 ClassDoc cl = mClass;
1287 for (String n: nodes) {
1288 cl = cl.findClass(n);
1289 if (cl == null) {
1290 return null;
1291 }
1292 }
1293 return Converter.obtainClass(cl);
1294 }
1295
1296 public FieldInfo findField(String name)
1297 {
1298 // first look on our class, and our superclasses
1299 for (FieldInfo f: fields()) {
1300 if (f.name().equals(name)) {
1301 return f;
1302 }
1303 }
1304
1305 // then look at our enum constants (these are really fields, maybe
1306 // they should be mixed into fields(). not sure)
1307 for (FieldInfo f: enumConstants()) {
1308 if (f.name().equals(name)) {
1309 return f;
1310 }
1311 }
1312
1313 // then recursively look at our containing class
1314 ClassInfo containing = containingClass();
1315 if (containing != null) {
1316 return containing.findField(name);
1317 }
1318
1319 return null;
1320 }
1321
1322 public static ClassInfo[] sortByName(ClassInfo[] classes)
1323 {
1324 int i;
1325 Sorter[] sorted = new Sorter[classes.length];
1326 for (i=0; i<sorted.length; i++) {
1327 ClassInfo cl = classes[i];
1328 sorted[i] = new Sorter(cl.name(), cl);
1329 }
1330
1331 Arrays.sort(sorted);
1332
1333 ClassInfo[] rv = new ClassInfo[classes.length];
1334 for (i=0; i<rv.length; i++) {
1335 rv[i] = (ClassInfo)sorted[i].data;
1336 }
1337
1338 return rv;
1339 }
1340
1341 public boolean equals(ClassInfo that)
1342 {
1343 if (that != null) {
1344 return this.qualifiedName().equals(that.qualifiedName());
1345 } else {
1346 return false;
1347 }
1348 }
1349
1350 public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
1351 mNonWrittenConstructors = nonWritten;
1352 }
1353
1354 public MethodInfo[] getNonWrittenConstructors() {
1355 return mNonWrittenConstructors;
1356 }
1357
1358 public String kind()
1359 {
1360 if (isOrdinaryClass()) {
1361 return "class";
1362 }
1363 else if (isInterface()) {
1364 return "interface";
1365 }
1366 else if (isEnum()) {
1367 return "enum";
1368 }
1369 else if (isError()) {
1370 return "class";
1371 }
1372 else if (isException()) {
1373 return "class";
1374 }
1375 else if (isAnnotation()) {
1376 return "@interface";
1377 }
1378 return null;
1379 }
1380
1381 public void setHiddenMethods(MethodInfo[] mInfo){
1382 mHiddenMethods = mInfo;
1383 }
1384 public MethodInfo[] getHiddenMethods(){
1385 return mHiddenMethods;
1386 }
1387 public String toString(){
1388 return this.qualifiedName();
1389 }
1390
1391 public void setReasonIncluded(String reason) {
1392 mReasonIncluded = reason;
1393 }
1394
1395 public String getReasonIncluded() {
1396 return mReasonIncluded;
1397 }
1398
1399 private ClassDoc mClass;
1400
1401 // ctor
1402 private boolean mIsPublic;
1403 private boolean mIsProtected;
1404 private boolean mIsPackagePrivate;
1405 private boolean mIsPrivate;
1406 private boolean mIsStatic;
1407 private boolean mIsInterface;
1408 private boolean mIsAbstract;
1409 private boolean mIsOrdinaryClass;
1410 private boolean mIsException;
1411 private boolean mIsError;
1412 private boolean mIsEnum;
1413 private boolean mIsAnnotation;
1414 private boolean mIsFinal;
1415 private boolean mIsIncluded;
1416 private String mName;
1417 private String mQualifiedName;
1418 private String mQualifiedTypeName;
1419 private boolean mIsPrimitive;
1420 private TypeInfo mTypeInfo;
1421 private String[] mNameParts;
1422
1423 // init
1424 private ClassInfo[] mRealInterfaces;
1425 private ClassInfo[] mInterfaces;
1426 private TypeInfo[] mRealInterfaceTypes;
1427 private ClassInfo[] mInnerClasses;
1428 private MethodInfo[] mAllConstructors;
1429 private MethodInfo[] mAllSelfMethods;
1430 private MethodInfo[] mAnnotationElements; // if this class is an annotation
1431 private FieldInfo[] mAllSelfFields;
1432 private FieldInfo[] mEnumConstants;
1433 private PackageInfo mContainingPackage;
1434 private ClassInfo mContainingClass;
1435 private ClassInfo mRealSuperclass;
1436 private TypeInfo mRealSuperclassType;
1437 private ClassInfo mSuperclass;
1438 private AnnotationInstanceInfo[] mAnnotations;
1439 private boolean mSuperclassInit;
1440 private boolean mDeprecatedKnown;
1441
1442 // lazy
1443 private MethodInfo[] mConstructors;
1444 private ClassInfo[] mRealInnerClasses;
1445 private MethodInfo[] mSelfMethods;
1446 private FieldInfo[] mSelfFields;
1447 private AttributeInfo[] mSelfAttributes;
1448 private MethodInfo[] mMethods;
1449 private FieldInfo[] mFields;
1450 private TypeInfo[] mTypeParameters;
1451 private MethodInfo[] mHiddenMethods;
1452 private int mHidden = -1;
1453 private int mCheckLevel = -1;
1454 private String mReasonIncluded;
1455 private MethodInfo[] mNonWrittenConstructors;
1456 private boolean mIsDeprecated;
1457}