blob: 32078f9362e36ecc33dd6174c06192ba9f99d17a [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
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001141 // xml attributes
1142 i=0;
1143 for (AttributeInfo attr: cl.selfAttributes()) {
1144 attr.makeHDF(data, base + ".attrs." + i);
1145 i++;
1146 }
1147
1148 // methods
1149 i=0;
1150 for (MethodInfo method: cl.selfMethods()) {
1151 method.makeHDF(data, base + ".methods." + i);
1152 i++;
1153 }
1154
1155 // fields
1156 i=0;
1157 for (FieldInfo field: cl.selfFields()) {
1158 if (!field.isConstant()) {
1159 field.makeHDF(data, base + ".fields." + i);
1160 i++;
1161 }
1162 }
1163
1164 // constants
1165 i=0;
1166 for (FieldInfo field: cl.selfFields()) {
1167 if (field.isConstant()) {
1168 field.makeHDF(data, base + ".constants." + i);
1169 i++;
1170 }
1171 }
1172 }
1173
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001174 @Override
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001175 public boolean isHidden()
1176 {
1177 int val = mHidden;
1178 if (val >= 0) {
1179 return val != 0;
1180 } else {
1181 boolean v = isHiddenImpl();
1182 mHidden = v ? 1 : 0;
1183 return v;
1184 }
1185 }
1186
1187 public boolean isHiddenImpl()
1188 {
1189 ClassInfo cl = this;
1190 while (cl != null) {
1191 PackageInfo pkg = cl.containingPackage();
The Android Open Source Projectf122bec2009-03-18 17:39:42 -07001192 if (pkg != null && pkg.isHidden()) {
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001193 return true;
1194 }
1195 if (cl.comment().isHidden()) {
1196 return true;
1197 }
1198 cl = cl.containingClass();
1199 }
1200 return false;
1201 }
1202
1203 private MethodInfo matchMethod(MethodInfo[] methods, String name,
1204 String[] params, String[] dimensions)
1205 {
1206 int len = methods.length;
1207 for (int i=0; i<len; i++) {
1208 MethodInfo method = methods[i];
1209 if (method.name().equals(name)) {
1210 if (params == null) {
1211 return method;
1212 } else {
1213 if (method.matchesParams(params, dimensions)) {
1214 return method;
1215 }
1216 }
1217 }
1218 }
1219 return null;
1220 }
1221
1222 public MethodInfo findMethod(String name,
1223 String[] params, String[] dimensions)
1224 {
1225 // first look on our class, and our superclasses
1226
1227 // for methods
1228 MethodInfo rv;
1229 rv = matchMethod(methods(), name, params, dimensions);
1230
1231 if (rv != null) {
1232 return rv;
1233 }
1234
1235 // for constructors
1236 rv = matchMethod(constructors(), name, params, dimensions);
1237 if (rv != null) {
1238 return rv;
1239 }
1240
1241 // then recursively look at our containing class
1242 ClassInfo containing = containingClass();
1243 if (containing != null) {
1244 return containing.findMethod(name, params, dimensions);
1245 }
1246
1247 return null;
1248 }
1249
1250 private ClassInfo searchInnerClasses(String[] nameParts, int index)
1251 {
1252 String part = nameParts[index];
1253
1254 ClassInfo[] inners = mInnerClasses;
1255 for (ClassInfo in: inners) {
1256 String[] innerParts = in.nameParts();
1257 if (part.equals(innerParts[innerParts.length-1])) {
1258 if (index == nameParts.length-1) {
1259 return in;
1260 } else {
1261 return in.searchInnerClasses(nameParts, index+1);
1262 }
1263 }
1264 }
1265 return null;
1266 }
1267
1268 public ClassInfo extendedFindClass(String className)
1269 {
1270 // ClassDoc.findClass has this bug that we're working around here:
1271 // If you have a class PackageManager with an inner class PackageInfo
1272 // and you call it with "PackageInfo" it doesn't find it.
1273 return searchInnerClasses(className.split("\\."), 0);
1274 }
1275
1276 public ClassInfo findClass(String className)
1277 {
1278 return Converter.obtainClass(mClass.findClass(className));
1279 }
1280
1281 public ClassInfo findInnerClass(String className)
1282 {
1283 // ClassDoc.findClass won't find inner classes. To deal with that,
1284 // we try what they gave us first, but if that didn't work, then
1285 // we see if there are any periods in className, and start searching
1286 // from there.
1287 String[] nodes = className.split("\\.");
1288 ClassDoc cl = mClass;
1289 for (String n: nodes) {
1290 cl = cl.findClass(n);
1291 if (cl == null) {
1292 return null;
1293 }
1294 }
1295 return Converter.obtainClass(cl);
1296 }
1297
1298 public FieldInfo findField(String name)
1299 {
1300 // first look on our class, and our superclasses
1301 for (FieldInfo f: fields()) {
1302 if (f.name().equals(name)) {
1303 return f;
1304 }
1305 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001306
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001307 // then look at our enum constants (these are really fields, maybe
1308 // they should be mixed into fields(). not sure)
1309 for (FieldInfo f: enumConstants()) {
1310 if (f.name().equals(name)) {
1311 return f;
1312 }
1313 }
1314
1315 // then recursively look at our containing class
1316 ClassInfo containing = containingClass();
1317 if (containing != null) {
1318 return containing.findField(name);
1319 }
1320
1321 return null;
1322 }
1323
1324 public static ClassInfo[] sortByName(ClassInfo[] classes)
1325 {
1326 int i;
1327 Sorter[] sorted = new Sorter[classes.length];
1328 for (i=0; i<sorted.length; i++) {
1329 ClassInfo cl = classes[i];
1330 sorted[i] = new Sorter(cl.name(), cl);
1331 }
1332
1333 Arrays.sort(sorted);
1334
1335 ClassInfo[] rv = new ClassInfo[classes.length];
1336 for (i=0; i<rv.length; i++) {
1337 rv[i] = (ClassInfo)sorted[i].data;
1338 }
1339
1340 return rv;
1341 }
1342
1343 public boolean equals(ClassInfo that)
1344 {
1345 if (that != null) {
1346 return this.qualifiedName().equals(that.qualifiedName());
1347 } else {
1348 return false;
1349 }
1350 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001351
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001352 public void setNonWrittenConstructors(MethodInfo[] nonWritten) {
1353 mNonWrittenConstructors = nonWritten;
1354 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001355
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001356 public MethodInfo[] getNonWrittenConstructors() {
1357 return mNonWrittenConstructors;
1358 }
1359
1360 public String kind()
1361 {
1362 if (isOrdinaryClass()) {
1363 return "class";
1364 }
1365 else if (isInterface()) {
1366 return "interface";
1367 }
1368 else if (isEnum()) {
1369 return "enum";
1370 }
1371 else if (isError()) {
1372 return "class";
1373 }
1374 else if (isException()) {
1375 return "class";
1376 }
1377 else if (isAnnotation()) {
1378 return "@interface";
1379 }
1380 return null;
1381 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001382
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001383 public void setHiddenMethods(MethodInfo[] mInfo){
1384 mHiddenMethods = mInfo;
1385 }
1386 public MethodInfo[] getHiddenMethods(){
1387 return mHiddenMethods;
1388 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001389 @Override
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001390 public String toString(){
1391 return this.qualifiedName();
1392 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001393
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001394 public void setReasonIncluded(String reason) {
1395 mReasonIncluded = reason;
1396 }
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001397
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001398 public String getReasonIncluded() {
Xavier Ducrohet5ee390d2009-09-10 13:08:27 -07001399 return mReasonIncluded;
The Android Open Source Projectb6c1cf62008-10-21 07:00:00 -07001400 }
1401
1402 private ClassDoc mClass;
1403
1404 // ctor
1405 private boolean mIsPublic;
1406 private boolean mIsProtected;
1407 private boolean mIsPackagePrivate;
1408 private boolean mIsPrivate;
1409 private boolean mIsStatic;
1410 private boolean mIsInterface;
1411 private boolean mIsAbstract;
1412 private boolean mIsOrdinaryClass;
1413 private boolean mIsException;
1414 private boolean mIsError;
1415 private boolean mIsEnum;
1416 private boolean mIsAnnotation;
1417 private boolean mIsFinal;
1418 private boolean mIsIncluded;
1419 private String mName;
1420 private String mQualifiedName;
1421 private String mQualifiedTypeName;
1422 private boolean mIsPrimitive;
1423 private TypeInfo mTypeInfo;
1424 private String[] mNameParts;
1425
1426 // init
1427 private ClassInfo[] mRealInterfaces;
1428 private ClassInfo[] mInterfaces;
1429 private TypeInfo[] mRealInterfaceTypes;
1430 private ClassInfo[] mInnerClasses;
1431 private MethodInfo[] mAllConstructors;
1432 private MethodInfo[] mAllSelfMethods;
1433 private MethodInfo[] mAnnotationElements; // if this class is an annotation
1434 private FieldInfo[] mAllSelfFields;
1435 private FieldInfo[] mEnumConstants;
1436 private PackageInfo mContainingPackage;
1437 private ClassInfo mContainingClass;
1438 private ClassInfo mRealSuperclass;
1439 private TypeInfo mRealSuperclassType;
1440 private ClassInfo mSuperclass;
1441 private AnnotationInstanceInfo[] mAnnotations;
1442 private boolean mSuperclassInit;
1443 private boolean mDeprecatedKnown;
1444
1445 // lazy
1446 private MethodInfo[] mConstructors;
1447 private ClassInfo[] mRealInnerClasses;
1448 private MethodInfo[] mSelfMethods;
1449 private FieldInfo[] mSelfFields;
1450 private AttributeInfo[] mSelfAttributes;
1451 private MethodInfo[] mMethods;
1452 private FieldInfo[] mFields;
1453 private TypeInfo[] mTypeParameters;
1454 private MethodInfo[] mHiddenMethods;
1455 private int mHidden = -1;
1456 private int mCheckLevel = -1;
1457 private String mReasonIncluded;
1458 private MethodInfo[] mNonWrittenConstructors;
1459 private boolean mIsDeprecated;
1460}