diff options
Diffstat (limited to 'tools/droiddoc/src/ClassInfo.java')
-rw-r--r-- | tools/droiddoc/src/ClassInfo.java | 1463 |
1 files changed, 1463 insertions, 0 deletions
diff --git a/tools/droiddoc/src/ClassInfo.java b/tools/droiddoc/src/ClassInfo.java new file mode 100644 index 0000000..36edbf8 --- /dev/null +++ b/tools/droiddoc/src/ClassInfo.java @@ -0,0 +1,1463 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import com.sun.javadoc.*; +import com.sun.tools.doclets.*; +import org.clearsilver.HDF; +import org.clearsilver.CS; +import java.util.*; +import java.io.*; + +public class ClassInfo extends DocInfo implements ContainerInfo, Comparable, Scoped +{ + public static final Comparator<ClassInfo> comparator = new Comparator<ClassInfo>() { + public int compare(ClassInfo a, ClassInfo b) { + return a.name().compareTo(b.name()); + } + }; + + public static final Comparator<ClassInfo> qualifiedComparator = new Comparator<ClassInfo>() { + public int compare(ClassInfo a, ClassInfo b) { + return a.qualifiedName().compareTo(b.qualifiedName()); + } + }; + + public ClassInfo( + ClassDoc cl, + String rawCommentText, SourcePositionInfo position, + boolean isPublic, boolean isProtected, boolean isPackagePrivate, + boolean isPrivate, boolean isStatic, + boolean isInterface, boolean isAbstract, boolean isOrdinaryClass, + boolean isException, boolean isError, boolean isEnum, boolean isAnnotation, + boolean isFinal, boolean isIncluded, String name, + String qualifiedName, String qualifiedTypeName, boolean isPrimitive) + { + super(rawCommentText, position); + + mClass = cl; + mIsPublic = isPublic; + mIsProtected = isProtected; + mIsPackagePrivate = isPackagePrivate; + mIsPrivate = isPrivate; + mIsStatic = isStatic; + mIsInterface = isInterface; + mIsAbstract = isAbstract; + mIsOrdinaryClass = isOrdinaryClass; + mIsException = isException; + mIsError = isError; + mIsEnum = isEnum; + mIsAnnotation = isAnnotation; + mIsFinal = isFinal; + mIsIncluded = isIncluded; + mName = name; + mQualifiedName = qualifiedName; + mQualifiedTypeName = qualifiedTypeName; + mIsPrimitive = isPrimitive; + mNameParts = name.split("\\."); + } + + public void init(TypeInfo typeInfo, ClassInfo[] interfaces, TypeInfo[] interfaceTypes, + ClassInfo[] innerClasses, + MethodInfo[] constructors, MethodInfo[] methods, MethodInfo[] annotationElements, + FieldInfo[] fields, FieldInfo[] enumConstants, + PackageInfo containingPackage, ClassInfo containingClass, + ClassInfo superclass, TypeInfo superclassType, AnnotationInstanceInfo[] annotations) + { + mTypeInfo = typeInfo; + mRealInterfaces = interfaces; + mRealInterfaceTypes = interfaceTypes; + mInnerClasses = innerClasses; + mAllConstructors = constructors; + mAllSelfMethods = methods; + mAnnotationElements = annotationElements; + mAllSelfFields = fields; + mEnumConstants = enumConstants; + mContainingPackage = containingPackage; + mContainingClass = containingClass; + mRealSuperclass = superclass; + mRealSuperclassType = superclassType; + mAnnotations = annotations; + + // after providing new methods and new superclass info,clear any cached + // lists of self + superclass methods, ctors, etc. + mSuperclassInit = false; + mConstructors = null; + mMethods = null; + mSelfMethods = null; + mFields = null; + mSelfFields = null; + mSelfAttributes = null; + mDeprecatedKnown = false; + + Arrays.sort(mEnumConstants, FieldInfo.comparator); + Arrays.sort(mInnerClasses, ClassInfo.comparator); + } + + public void init2() { + // calling this here forces the AttrTagInfo objects to be linked to the AttribtueInfo + // objects + selfAttributes(); + } + + public void init3(TypeInfo[] types, ClassInfo[] realInnerClasses){ + mTypeParameters = types; + mRealInnerClasses = realInnerClasses; + } + + public ClassInfo[] getRealInnerClasses(){ + return mRealInnerClasses; + } + + public TypeInfo[] getTypeParameters(){ + return mTypeParameters; + } + + public boolean checkLevel() + { + int val = mCheckLevel; + if (val >= 0) { + return val != 0; + } else { + boolean v = DroidDoc.checkLevel(mIsPublic, mIsProtected, + mIsPackagePrivate, mIsPrivate, isHidden()); + mCheckLevel = v ? 1 : 0; + return v; + } + } + + public int compareTo(Object that) { + if (that instanceof ClassInfo) { + return mQualifiedName.compareTo(((ClassInfo)that).mQualifiedName); + } else { + return this.hashCode() - that.hashCode(); + } + } + + public ContainerInfo parent() + { + return this; + } + + public boolean isPublic() + { + return mIsPublic; + } + + public boolean isProtected() + { + return mIsProtected; + } + + public boolean isPackagePrivate() + { + return mIsPackagePrivate; + } + + public boolean isPrivate() + { + return mIsPrivate; + } + + public boolean isStatic() + { + return mIsStatic; + } + + public boolean isInterface() + { + return mIsInterface; + } + + public boolean isAbstract() + { + return mIsAbstract; + } + + public PackageInfo containingPackage() + { + return mContainingPackage; + } + + public ClassInfo containingClass() + { + return mContainingClass; + } + + public boolean isOrdinaryClass() + { + return mIsOrdinaryClass; + } + + public boolean isException() + { + return mIsException; + } + + public boolean isError() + { + return mIsError; + } + + public boolean isEnum() + { + return mIsEnum; + } + + public boolean isAnnotation() + { + return mIsAnnotation; + } + + public boolean isFinal() + { + return mIsFinal; + } + + public boolean isIncluded() + { + return mIsIncluded; + } + + public HashSet<String> typeVariables() + { + HashSet<String> result = TypeInfo.typeVariables(mTypeInfo.typeArguments()); + ClassInfo cl = containingClass(); + while (cl != null) { + TypeInfo[] types = cl.asTypeInfo().typeArguments(); + if (types != null) { + TypeInfo.typeVariables(types, result); + } + cl = cl.containingClass(); + } + return result; + } + + private static void gatherHiddenInterfaces(ClassInfo cl, HashSet<ClassInfo> interfaces) { + for (ClassInfo iface: cl.mRealInterfaces) { + if (iface.checkLevel()) { + interfaces.add(iface); + } else { + gatherHiddenInterfaces(iface, interfaces); + } + } + } + + public ClassInfo[] interfaces() + { + if (mInterfaces == null) { + if (checkLevel()) { + HashSet<ClassInfo> interfaces = new HashSet<ClassInfo>(); + ClassInfo superclass = mRealSuperclass; + while (superclass != null && !superclass.checkLevel()) { + gatherHiddenInterfaces(superclass, interfaces); + superclass = superclass.mRealSuperclass; + } + gatherHiddenInterfaces(this, interfaces); + mInterfaces = interfaces.toArray(new ClassInfo[interfaces.size()]); + } else { + // put something here in case someone uses it + mInterfaces = mRealInterfaces; + } + Arrays.sort(mInterfaces, ClassInfo.qualifiedComparator); + } + return mInterfaces; + } + + public ClassInfo[] realInterfaces() + { + return mRealInterfaces; + } + + TypeInfo[] realInterfaceTypes() + { + return mRealInterfaceTypes; + } + + public String name() + { + return mName; + } + + public String[] nameParts() + { + return mNameParts; + } + + public String leafName() + { + return mNameParts[mNameParts.length-1]; + } + + public String qualifiedName() + { + return mQualifiedName; + } + + public String qualifiedTypeName() + { + return mQualifiedTypeName; + } + + public boolean isPrimitive() + { + return mIsPrimitive; + } + + public MethodInfo[] allConstructors() { + return mAllConstructors; + } + + public MethodInfo[] constructors() + { + if (mConstructors == null) { + MethodInfo[] methods = mAllConstructors; + ArrayList<MethodInfo> ctors = new ArrayList<MethodInfo>(); + for (int i=0; i<methods.length; i++) { + MethodInfo m = methods[i]; + if (!m.isHidden()) { + ctors.add(m); + } + } + mConstructors = ctors.toArray(new MethodInfo[ctors.size()]); + Arrays.sort(mConstructors, MethodInfo.comparator); + } + return mConstructors; + } + + public ClassInfo[] innerClasses() + { + return mInnerClasses; + } + + public TagInfo[] inlineTags() + { + return comment().tags(); + } + + public TagInfo[] firstSentenceTags() + { + return comment().briefTags(); + } + + public boolean isDeprecated() { + boolean deprecated = false; + if (!mDeprecatedKnown) { + boolean commentDeprecated = (comment().deprecatedTags().length > 0); + boolean annotationDeprecated = false; + for (AnnotationInstanceInfo annotation : annotations()) { + if (annotation.type().qualifiedName().equals("java.lang.Deprecated")) { + annotationDeprecated = true; + break; + } + } + + if (commentDeprecated != annotationDeprecated) { + Errors.error(Errors.DEPRECATION_MISMATCH, position(), + "Class " + qualifiedName() + + ": @Deprecated annotation and @deprecated comment do not match"); + } + + mIsDeprecated = commentDeprecated | annotationDeprecated; + mDeprecatedKnown = true; + } + return mIsDeprecated; + } + + public TagInfo[] deprecatedTags() + { + TagInfo[] result = comment().deprecatedTags(); + if (result.length == 0) { + if (comment().undeprecateTags().length == 0) { + if (superclass() != null) { + result = superclass().deprecatedTags(); + } + } + } + // should we also do the interfaces? + return result; + } + + public MethodInfo[] methods() + { + if (mMethods == null) { + TreeMap<String,MethodInfo> all = new TreeMap<String,MethodInfo>(); + + ClassInfo[] ifaces = interfaces(); + for (ClassInfo iface: ifaces) { + if (iface != null) { + MethodInfo[] inhereted = iface.methods(); + for (MethodInfo method: inhereted) { + String key = method.name() + method.signature(); + all.put(key, method); + } + } + } + + ClassInfo superclass = superclass(); + if (superclass != null) { + MethodInfo[] inhereted = superclass.methods(); + for (MethodInfo method: inhereted) { + String key = method.name() + method.signature(); + all.put(key, method); + } + } + + MethodInfo[] methods = selfMethods(); + for (MethodInfo method: methods) { + String key = method.name() + method.signature(); + MethodInfo old = all.put(key, method); + } + + mMethods = all.values().toArray(new MethodInfo[all.size()]); + } + return mMethods; + } + + public MethodInfo[] annotationElements() + { + return mAnnotationElements; + } + + public AnnotationInstanceInfo[] annotations() + { + return mAnnotations; + } + + private static void addFields(ClassInfo cl, TreeMap<String,FieldInfo> all) + { + FieldInfo[] fields = cl.fields(); + int N = fields.length; + for (int i=0; i<N; i++) { + FieldInfo f = fields[i]; + all.put(f.name(), f); + } + } + + public FieldInfo[] fields() + { + if (mFields == null) { + int N; + TreeMap<String,FieldInfo> all = new TreeMap<String,FieldInfo>(); + + ClassInfo[] interfaces = interfaces(); + N = interfaces.length; + for (int i=0; i<N; i++) { + addFields(interfaces[i], all); + } + + ClassInfo superclass = superclass(); + if (superclass != null) { + addFields(superclass, all); + } + + FieldInfo[] fields = selfFields(); + N = fields.length; + for (int i=0; i<N; i++) { + FieldInfo f = fields[i]; + if (!f.isHidden()) { + String key = f.name(); + all.put(key, f); + } + } + + mFields = all.values().toArray(new FieldInfo[0]); + } + return mFields; + } + + public void gatherFields(ClassInfo owner, ClassInfo cl, HashMap<String,FieldInfo> fields) { + FieldInfo[] flds = cl.selfFields(); + for (FieldInfo f: flds) { + if (f.checkLevel()) { + fields.put(f.name(), f.cloneForClass(owner)); + } + } + } + + public FieldInfo[] selfFields() + { + if (mSelfFields == null) { + HashMap<String,FieldInfo> fields = new HashMap<String,FieldInfo>(); + // our hidden parents + if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) { + gatherFields(this, mRealSuperclass, fields); + } + for (ClassInfo iface: mRealInterfaces) { + if (!iface.checkLevel()) { + gatherFields(this, iface, fields); + } + } + // mine + FieldInfo[] selfFields = mAllSelfFields; + for (int i=0; i<selfFields.length; i++) { + FieldInfo f = selfFields[i]; + if (!f.isHidden()) { + fields.put(f.name(), f); + } + } + // combine and return in + mSelfFields = fields.values().toArray(new FieldInfo[fields.size()]); + Arrays.sort(mSelfFields, FieldInfo.comparator); + } + return mSelfFields; + } + + public FieldInfo[] allSelfFields() { + return mAllSelfFields; + } + + public void gatherMethods(ClassInfo owner, ClassInfo cl, HashMap<String,MethodInfo> methods) { + MethodInfo[] meth = cl.selfMethods(); + for (MethodInfo m: meth) { + if (m.checkLevel()) { + methods.put(m.name()+m.signature(), m.cloneForClass(owner)); + } + } + } + + public MethodInfo[] selfMethods() + { + if (mSelfMethods == null) { + HashMap<String,MethodInfo> methods = new HashMap<String,MethodInfo>(); + // our hidden parents + if (mRealSuperclass != null && !mRealSuperclass.checkLevel()) { + gatherMethods(this, mRealSuperclass, methods); + } + for (ClassInfo iface: mRealInterfaces) { + if (!iface.checkLevel()) { + gatherMethods(this, iface, methods); + } + } + // mine + MethodInfo[] selfMethods = mAllSelfMethods; + for (int i=0; i<selfMethods.length; i++) { + MethodInfo m = selfMethods[i]; + if (m.checkLevel()) { + methods.put(m.name()+m.signature(), m); + } + } + // combine and return it + mSelfMethods = methods.values().toArray(new MethodInfo[methods.size()]); + Arrays.sort(mSelfMethods, MethodInfo.comparator); + } + return mSelfMethods; + } + + public MethodInfo[] allSelfMethods() { + return mAllSelfMethods; + } + + public void addMethod(MethodInfo method) { + MethodInfo[] methods = new MethodInfo[mAllSelfMethods.length + 1]; + int i = 0; + for (MethodInfo m : mAllSelfMethods) { + methods[i] = m; + i++; + } + methods[i] = method; + mAllSelfMethods = methods; + } + + public AttributeInfo[] selfAttributes() + { + if (mSelfAttributes == null) { + TreeMap<FieldInfo,AttributeInfo> attrs = new TreeMap<FieldInfo,AttributeInfo>(); + + // the ones in the class comment won't have any methods + for (AttrTagInfo tag: comment().attrTags()) { + FieldInfo field = tag.reference(); + if (field != null) { + AttributeInfo attr = attrs.get(field); + if (attr == null) { + attr = new AttributeInfo(this, field); + attrs.put(field, attr); + } + tag.setAttribute(attr); + } + } + + // in the methods + for (MethodInfo m: selfMethods()) { + for (AttrTagInfo tag: m.comment().attrTags()) { + FieldInfo field = tag.reference(); + if (field != null) { + AttributeInfo attr = attrs.get(field); + if (attr == null) { + attr = new AttributeInfo(this, field); + attrs.put(field, attr); + } + tag.setAttribute(attr); + attr.methods.add(m); + } + } + } + + //constructors too + for (MethodInfo m: constructors()) { + for (AttrTagInfo tag: m.comment().attrTags()) { + FieldInfo field = tag.reference(); + if (field != null) { + AttributeInfo attr = attrs.get(field); + if (attr == null) { + attr = new AttributeInfo(this, field); + attrs.put(field, attr); + } + tag.setAttribute(attr); + attr.methods.add(m); + } + } + } + + mSelfAttributes = attrs.values().toArray(new AttributeInfo[attrs.size()]); + Arrays.sort(mSelfAttributes, AttributeInfo.comparator); + } + return mSelfAttributes; + } + + public FieldInfo[] enumConstants() + { + return mEnumConstants; + } + + public ClassInfo superclass() + { + if (!mSuperclassInit) { + if (this.checkLevel()) { + // rearrange our little inheritance hierarchy, because we need to hide classes that + // don't pass checkLevel + ClassInfo superclass = mRealSuperclass; + while (superclass != null && !superclass.checkLevel()) { + superclass = superclass.mRealSuperclass; + } + mSuperclass = superclass; + } else { + mSuperclass = mRealSuperclass; + } + } + return mSuperclass; + } + + public ClassInfo realSuperclass() + { + return mRealSuperclass; + } + + /** always the real superclass, not the collapsed one we get through superclass(), + * also has the type parameter info if it's generic. + */ + public TypeInfo superclassType() + { + return mRealSuperclassType; + } + + public TypeInfo asTypeInfo() + { + return mTypeInfo; + } + + TypeInfo[] interfaceTypes() + { + ClassInfo[] infos = interfaces(); + int len = infos.length; + TypeInfo[] types = new TypeInfo[len]; + for (int i=0; i<len; i++) { + types[i] = infos[i].asTypeInfo(); + } + return types; + } + + public String htmlPage() + { + String s = containingPackage().name(); + s = s.replace('.', '/'); + s += '/'; + s += name(); + s += ".html"; + s = DroidDoc.javadocDir + s; + return s; + } + + /** Even indirectly */ + public boolean isDerivedFrom(ClassInfo cl) + { + ClassInfo dad = this.superclass(); + if (dad != null) { + if (dad.equals(cl)) { + return true; + } else { + if (dad.isDerivedFrom(cl)) { + return true; + } + } + } + for (ClassInfo iface: interfaces()) { + if (iface.equals(cl)) { + return true; + } else { + if (iface.isDerivedFrom(cl)) { + return true; + } + } + } + return false; + } + + public void makeKeywordEntries(List<KeywordEntry> keywords) + { + if (!checkLevel()) { + return; + } + + String htmlPage = htmlPage(); + String qualifiedName = qualifiedName(); + + keywords.add(new KeywordEntry(name(), htmlPage, + "class in " + containingPackage().name())); + + FieldInfo[] fields = selfFields(); + FieldInfo[] enumConstants = enumConstants(); + MethodInfo[] ctors = constructors(); + MethodInfo[] methods = selfMethods(); + + // enum constants + for (FieldInfo field: enumConstants()) { + if (field.checkLevel()) { + keywords.add(new KeywordEntry(field.name(), + htmlPage + "#" + field.anchor(), + "enum constant in " + qualifiedName)); + } + } + + // constants + for (FieldInfo field: fields) { + if (field.isConstant() && field.checkLevel()) { + keywords.add(new KeywordEntry(field.name(), + htmlPage + "#" + field.anchor(), + "constant in " + qualifiedName)); + } + } + + // fields + for (FieldInfo field: fields) { + if (!field.isConstant() && field.checkLevel()) { + keywords.add(new KeywordEntry(field.name(), + htmlPage + "#" + field.anchor(), + "field in " + qualifiedName)); + } + } + + // public constructors + for (MethodInfo m: ctors) { + if (m.isPublic() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "constructor in " + qualifiedName)); + } + } + + // protected constructors + if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) { + for (MethodInfo m: ctors) { + if (m.isProtected() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "constructor in " + qualifiedName)); + } + } + } + + // package private constructors + if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) { + for (MethodInfo m: ctors) { + if (m.isPackagePrivate() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "constructor in " + qualifiedName)); + } + } + } + + // private constructors + if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) { + for (MethodInfo m: ctors) { + if (m.isPrivate() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "constructor in " + qualifiedName)); + } + } + } + + // public methods + for (MethodInfo m: methods) { + if (m.isPublic() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "method in " + qualifiedName)); + } + } + + // protected methods + if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) { + for (MethodInfo m: methods) { + if (m.isProtected() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "method in " + qualifiedName)); + } + } + } + + // package private methods + if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) { + for (MethodInfo m: methods) { + if (m.isPackagePrivate() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "method in " + qualifiedName)); + } + } + } + + // private methods + if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) { + for (MethodInfo m: methods) { + if (m.isPrivate() && m.checkLevel()) { + keywords.add(new KeywordEntry(m.name() + m.prettySignature(), + htmlPage + "#" + m.anchor(), + "method in " + qualifiedName)); + } + } + } + } + + public void makeLink(HDF data, String base) + { + data.setValue(base + ".label", this.name()); + if (!this.isPrimitive() && this.isIncluded() && this.checkLevel()) { + data.setValue(base + ".link", this.htmlPage()); + } + } + + public static void makeLinkListHDF(HDF data, String base, ClassInfo[] classes) { + final int N = classes.length; + for (int i=0; i<N; i++) { + ClassInfo cl = classes[i]; + if (cl.checkLevel()) { + cl.asTypeInfo().makeHDF(data, base + "." + i); + } + } + } + + /** + * Used in lists of this class (packages, nested classes, known subclasses) + */ + public void makeShortDescrHDF(HDF data, String base) + { + mTypeInfo.makeHDF(data, base + ".type"); + data.setValue(base + ".kind", this.kind()); + TagInfo.makeHDF(data, base + ".shortDescr", this.firstSentenceTags()); + TagInfo.makeHDF(data, base + ".deprecated", deprecatedTags()); + } + + /** + * Turns into the main class page + */ + public void makeHDF(HDF data) + { + int i, j, n; + String name = name(); + String qualified = qualifiedName(); + AttributeInfo[] selfAttributes = selfAttributes(); + MethodInfo[] methods = selfMethods(); + FieldInfo[] fields = selfFields(); + FieldInfo[] enumConstants = enumConstants(); + MethodInfo[] ctors = constructors(); + ClassInfo[] inners = innerClasses(); + + // class name + mTypeInfo.makeHDF(data, "class.type"); + mTypeInfo.makeQualifiedHDF(data, "class.qualifiedType"); + data.setValue("class.name", name); + data.setValue("class.qualified", qualified); + String scope = ""; + if (isProtected()) { + data.setValue("class.scope", "protected"); + } + else if (isPublic()) { + data.setValue("class.scope", "public"); + } + if (isStatic()) { + data.setValue("class.static", "static"); + } + if (isFinal()) { + data.setValue("class.final", "final"); + } + if (isAbstract() && !isInterface()) { + data.setValue("class.abstract", "abstract"); + } + + // class info + String kind = kind(); + if (kind != null) { + data.setValue("class.kind", kind); + } + + // the containing package -- note that this can be passed to type_link, + // but it also contains the list of all of the packages + containingPackage().makeClassLinkListHDF(data, "class.package"); + + // inheritance hierarchy + Vector<ClassInfo> superClasses = new Vector<ClassInfo>(); + superClasses.add(this); + ClassInfo supr = superclass(); + while (supr != null) { + superClasses.add(supr); + supr = supr.superclass(); + } + n = superClasses.size(); + for (i=0; i<n; i++) { + supr = superClasses.elementAt(n-i-1); + + supr.asTypeInfo().makeQualifiedHDF(data, "class.inheritance." + i + ".class"); + supr.asTypeInfo().makeHDF(data, "class.inheritance." + i + ".short_class"); + j = 0; + for (TypeInfo t: supr.interfaceTypes()) { + t.makeHDF(data, "class.inheritance." + i + ".interfaces." + j); + j++; + } + } + + // class description + TagInfo.makeHDF(data, "class.descr", inlineTags()); + TagInfo.makeHDF(data, "class.seeAlso", comment().seeTags()); + TagInfo.makeHDF(data, "class.deprecated", deprecatedTags()); + + // known subclasses + TreeMap<String, ClassInfo> direct = new TreeMap<String, ClassInfo>(); + TreeMap<String, ClassInfo> indirect = new TreeMap<String, ClassInfo>(); + ClassInfo[] all = Converter.rootClasses(); + for (ClassInfo cl: all) { + if (cl.superclass() != null && cl.superclass().equals(this)) { + direct.put(cl.name(), cl); + } + else if (cl.isDerivedFrom(this)) { + indirect.put(cl.name(), cl); + } + } + // direct + i = 0; + for (ClassInfo cl: direct.values()) { + if (cl.checkLevel()) { + cl.makeShortDescrHDF(data, "class.subclasses.direct." + i); + } + i++; + } + // indirect + i = 0; + for (ClassInfo cl: indirect.values()) { + if (cl.checkLevel()) { + cl.makeShortDescrHDF(data, "class.subclasses.indirect." + i); + } + i++; + } + + // nested classes + i=0; + for (ClassInfo inner: inners) { + if (inner.checkLevel()) { + inner.makeShortDescrHDF(data, "class.inners." + i); + } + i++; + } + + // enum constants + i=0; + for (FieldInfo field: enumConstants) { + if (field.isConstant()) { + field.makeHDF(data, "class.enumConstants." + i); + i++; + } + } + + // constants + i=0; + for (FieldInfo field: fields) { + if (field.isConstant()) { + field.makeHDF(data, "class.constants." + i); + i++; + } + } + + // fields + i=0; + for (FieldInfo field: fields) { + if (!field.isConstant()) { + field.makeHDF(data, "class.fields." + i); + i++; + } + } + + // public constructors + i=0; + for (MethodInfo ctor: ctors) { + if (ctor.isPublic()) { + ctor.makeHDF(data, "class.ctors.public." + i); + i++; + } + } + + // protected constructors + if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) { + i=0; + for (MethodInfo ctor: ctors) { + if (ctor.isProtected()) { + ctor.makeHDF(data, "class.ctors.protected." + i); + i++; + } + } + } + + // package private constructors + if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) { + i=0; + for (MethodInfo ctor: ctors) { + if (ctor.isPackagePrivate()) { + ctor.makeHDF(data, "class.ctors.package." + i); + i++; + } + } + } + + // private constructors + if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) { + i=0; + for (MethodInfo ctor: ctors) { + if (ctor.isPrivate()) { + ctor.makeHDF(data, "class.ctors.private." + i); + i++; + } + } + } + + // public methods + i=0; + for (MethodInfo method: methods) { + if (method.isPublic()) { + method.makeHDF(data, "class.methods.public." + i); + i++; + } + } + + // protected methods + if (DroidDoc.checkLevel(DroidDoc.SHOW_PROTECTED)) { + i=0; + for (MethodInfo method: methods) { + if (method.isProtected()) { + method.makeHDF(data, "class.methods.protected." + i); + i++; + } + } + } + + // package private methods + if (DroidDoc.checkLevel(DroidDoc.SHOW_PACKAGE)) { + i=0; + for (MethodInfo method: methods) { + if (method.isPackagePrivate()) { + method.makeHDF(data, "class.methods.package." + i); + i++; + } + } + } + + // private methods + if (DroidDoc.checkLevel(DroidDoc.SHOW_PRIVATE)) { + i=0; + for (MethodInfo method: methods) { + if (method.isPrivate()) { + method.makeHDF(data, "class.methods.private." + i); + i++; + } + } + } + + // xml attributes + i=0; + for (AttributeInfo attr: selfAttributes) { + if (attr.checkLevel()) { + attr.makeHDF(data, "class.attrs." + i); + i++; + } + } + + // inherited methods + Set<ClassInfo> interfaces = new TreeSet<ClassInfo>(); + addInterfaces(interfaces(), interfaces); + ClassInfo cl = superclass(); + i=0; + while (cl != null) { + addInterfaces(cl.interfaces(), interfaces); + makeInheritedHDF(data, i, cl); + cl = cl.superclass(); + i++; + } + for (ClassInfo iface: interfaces) { + makeInheritedHDF(data, i, iface); + i++; + } + } + + private static void addInterfaces(ClassInfo[] ifaces, Set<ClassInfo> out) + { + for (ClassInfo cl: ifaces) { + out.add(cl); + addInterfaces(cl.interfaces(), out); + } + } + + private static void makeInheritedHDF(HDF data, int index, ClassInfo cl) + { + int i; + + String base = "class.inherited." + index; + data.setValue(base + ".qualified", cl.qualifiedName()); + if (cl.checkLevel()) { + data.setValue(base + ".link", cl.htmlPage()); + } + String kind = cl.kind(); + if (kind != null) { + data.setValue(base + ".kind", kind); + } + + // xml attributes + i=0; + for (AttributeInfo attr: cl.selfAttributes()) { + attr.makeHDF(data, base + ".attrs." + i); + i++; + } + + // methods + i=0; + for (MethodInfo method: cl.selfMethods()) { + method.makeHDF(data, base + ".methods." + i); + i++; + } + + // fields + i=0; + for (FieldInfo field: cl.selfFields()) { + if (!field.isConstant()) { + field.makeHDF(data, base + ".fields." + i); + i++; + } + } + + // constants + i=0; + for (FieldInfo field: cl.selfFields()) { + if (field.isConstant()) { + field.makeHDF(data, base + ".constants." + i); + i++; + } + } + } + + public boolean isHidden() + { + int val = mHidden; + if (val >= 0) { + return val != 0; + } else { + boolean v = isHiddenImpl(); + mHidden = v ? 1 : 0; + return v; + } + } + + public boolean isHiddenImpl() + { + ClassInfo cl = this; + while (cl != null) { + PackageInfo pkg = cl.containingPackage(); + if (pkg.isHidden()) { + return true; + } + if (cl.comment().isHidden()) { + return true; + } + cl = cl.containingClass(); + } + return false; + } + + private MethodInfo matchMethod(MethodInfo[] methods, String name, + String[] params, String[] dimensions) + { + int len = methods.length; + for (int i=0; i<len; i++) { + MethodInfo method = methods[i]; + if (method.name().equals(name)) { + if (params == null) { + return method; + } else { + if (method.matchesParams(params, dimensions)) { + return method; + } + } + } + } + return null; + } + + public MethodInfo findMethod(String name, + String[] params, String[] dimensions) + { + // first look on our class, and our superclasses + + // for methods + MethodInfo rv; + rv = matchMethod(methods(), name, params, dimensions); + + if (rv != null) { + return rv; + } + + // for constructors + rv = matchMethod(constructors(), name, params, dimensions); + if (rv != null) { + return rv; + } + + // then recursively look at our containing class + ClassInfo containing = containingClass(); + if (containing != null) { + return containing.findMethod(name, params, dimensions); + } + + return null; + } + + private ClassInfo searchInnerClasses(String[] nameParts, int index) + { + String part = nameParts[index]; + + ClassInfo[] inners = mInnerClasses; + for (ClassInfo in: inners) { + String[] innerParts = in.nameParts(); + if (part.equals(innerParts[innerParts.length-1])) { + if (index == nameParts.length-1) { + return in; + } else { + return in.searchInnerClasses(nameParts, index+1); + } + } + } + return null; + } + + public ClassInfo extendedFindClass(String className) + { + // ClassDoc.findClass has this bug that we're working around here: + // If you have a class PackageManager with an inner class PackageInfo + // and you call it with "PackageInfo" it doesn't find it. + return searchInnerClasses(className.split("\\."), 0); + } + + public ClassInfo findClass(String className) + { + return Converter.obtainClass(mClass.findClass(className)); + } + + public ClassInfo findInnerClass(String className) + { + // ClassDoc.findClass won't find inner classes. To deal with that, + // we try what they gave us first, but if that didn't work, then + // we see if there are any periods in className, and start searching + // from there. + String[] nodes = className.split("\\."); + ClassDoc cl = mClass; + for (String n: nodes) { + cl = cl.findClass(n); + if (cl == null) { + return null; + } + } + return Converter.obtainClass(cl); + } + + public FieldInfo findField(String name) + { + // first look on our class, and our superclasses + for (FieldInfo f: fields()) { + if (f.name().equals(name)) { + return f; + } + } + + // then look at our enum constants (these are really fields, maybe + // they should be mixed into fields(). not sure) + for (FieldInfo f: enumConstants()) { + if (f.name().equals(name)) { + return f; + } + } + + // then recursively look at our containing class + ClassInfo containing = containingClass(); + if (containing != null) { + return containing.findField(name); + } + + return null; + } + + public static ClassInfo[] sortByName(ClassInfo[] classes) + { + int i; + Sorter[] sorted = new Sorter[classes.length]; + for (i=0; i<sorted.length; i++) { + ClassInfo cl = classes[i]; + sorted[i] = new Sorter(cl.name(), cl); + } + + Arrays.sort(sorted); + + ClassInfo[] rv = new ClassInfo[classes.length]; + for (i=0; i<rv.length; i++) { + rv[i] = (ClassInfo)sorted[i].data; + } + + return rv; + } + + public boolean equals(ClassInfo that) + { + if (that != null) { + return this.qualifiedName().equals(that.qualifiedName()); + } else { + return false; + } + } + + public void setNonWrittenConstructors(MethodInfo[] nonWritten) { + mNonWrittenConstructors = nonWritten; + } + + public MethodInfo[] getNonWrittenConstructors() { + return mNonWrittenConstructors; + } + + public String kind() + { + if (isOrdinaryClass()) { + return "class"; + } + else if (isInterface()) { + return "interface"; + } + else if (isEnum()) { + return "enum"; + } + else if (isError()) { + return "class"; + } + else if (isException()) { + return "class"; + } + else if (isAnnotation()) { + return "@interface"; + } + return null; + } + + public void setHiddenMethods(MethodInfo[] mInfo){ + mHiddenMethods = mInfo; + } + public MethodInfo[] getHiddenMethods(){ + return mHiddenMethods; + } + public String toString(){ + return this.qualifiedName(); + } + + public void setReasonIncluded(String reason) { + mReasonIncluded = reason; + } + + public String getReasonIncluded() { + return mReasonIncluded; + } + + private ClassDoc mClass; + + // ctor + private boolean mIsPublic; + private boolean mIsProtected; + private boolean mIsPackagePrivate; + private boolean mIsPrivate; + private boolean mIsStatic; + private boolean mIsInterface; + private boolean mIsAbstract; + private boolean mIsOrdinaryClass; + private boolean mIsException; + private boolean mIsError; + private boolean mIsEnum; + private boolean mIsAnnotation; + private boolean mIsFinal; + private boolean mIsIncluded; + private String mName; + private String mQualifiedName; + private String mQualifiedTypeName; + private boolean mIsPrimitive; + private TypeInfo mTypeInfo; + private String[] mNameParts; + + // init + private ClassInfo[] mRealInterfaces; + private ClassInfo[] mInterfaces; + private TypeInfo[] mRealInterfaceTypes; + private ClassInfo[] mInnerClasses; + private MethodInfo[] mAllConstructors; + private MethodInfo[] mAllSelfMethods; + private MethodInfo[] mAnnotationElements; // if this class is an annotation + private FieldInfo[] mAllSelfFields; + private FieldInfo[] mEnumConstants; + private PackageInfo mContainingPackage; + private ClassInfo mContainingClass; + private ClassInfo mRealSuperclass; + private TypeInfo mRealSuperclassType; + private ClassInfo mSuperclass; + private AnnotationInstanceInfo[] mAnnotations; + private boolean mSuperclassInit; + private boolean mDeprecatedKnown; + + // lazy + private MethodInfo[] mConstructors; + private ClassInfo[] mRealInnerClasses; + private MethodInfo[] mSelfMethods; + private FieldInfo[] mSelfFields; + private AttributeInfo[] mSelfAttributes; + private MethodInfo[] mMethods; + private FieldInfo[] mFields; + private TypeInfo[] mTypeParameters; + private MethodInfo[] mHiddenMethods; + private int mHidden = -1; + private int mCheckLevel = -1; + private String mReasonIncluded; + private MethodInfo[] mNonWrittenConstructors; + private boolean mIsDeprecated; +} |