diff options
Diffstat (limited to 'tools/droiddoc/src/Stubs.java')
-rw-r--r-- | tools/droiddoc/src/Stubs.java | 999 |
1 files changed, 0 insertions, 999 deletions
diff --git a/tools/droiddoc/src/Stubs.java b/tools/droiddoc/src/Stubs.java deleted file mode 100644 index b988ef5..0000000 --- a/tools/droiddoc/src/Stubs.java +++ /dev/null @@ -1,999 +0,0 @@ -/* - * 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 java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Set; -import java.util.Comparator; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.PrintStream; - -public class Stubs { - private static HashSet<ClassInfo> notStrippable; - public static void writeStubs(String stubsDir, Boolean writeXML, String xmlFile, - HashSet<String> stubPackages) { - // figure out which classes we need - notStrippable = new HashSet(); - ClassInfo[] all = Converter.allClasses(); - File xml = new File(xmlFile); - xml.getParentFile().mkdirs(); - PrintStream xmlWriter = null; - if (writeXML) { - try { - xmlWriter = new PrintStream(xml); - } catch (FileNotFoundException e) { - Errors.error(Errors.IO_ERROR, new SourcePositionInfo(xmlFile, 0, 0), - "Cannot open file for write."); - } - } - // If a class is public or protected, not hidden, and marked as included, - // then we can't strip it - for (ClassInfo cl: all) { - if (cl.checkLevel() && cl.isIncluded()) { - cantStripThis(cl, notStrippable, "0:0"); - } - } - - // complain about anything that looks includeable but is not supposed to - // be written, e.g. hidden things - for (ClassInfo cl: notStrippable) { - if (!cl.isHidden()) { - MethodInfo[] methods = cl.selfMethods(); - for (MethodInfo m: methods) { - if (m.isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, - m.position(), "Reference to hidden method " - + m.name()); - } else if (m.isDeprecated()) { - // don't bother reporting deprecated methods - // unless they are public - Errors.error(Errors.DEPRECATED, - m.position(), "Method " - + cl.qualifiedName() + "." + m.name() - + " is deprecated"); - } - - ClassInfo returnClass = m.returnType().asClassInfo(); - if (returnClass != null && returnClass.isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), - "Method " + cl.qualifiedName() + "." + m.name() - + " returns unavailable type " + returnClass.name()); - } - - ParameterInfo[] params = m.parameters(); - for (ParameterInfo p: params) { - TypeInfo t = p.type(); - if (!t.isPrimitive()) { - if (t.asClassInfo().isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, - m.position(), "Parameter of hidden type " - + t.fullName() + " in " - + cl.qualifiedName() + "." + m.name() + "()"); - } - } - } - } - - // annotations are handled like methods - methods = cl.annotationElements(); - for (MethodInfo m: methods) { - if (m.isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, - m.position(), "Reference to hidden annotation " - + m.name()); - } - - ClassInfo returnClass = m.returnType().asClassInfo(); - if (returnClass != null && returnClass.isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, - m.position(), "Annotation '" + m.name() - + "' returns unavailable type " + returnClass.name()); - } - - ParameterInfo[] params = m.parameters(); - for (ParameterInfo p: params) { - TypeInfo t = p.type(); - if (!t.isPrimitive()) { - if (t.asClassInfo().isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, - p.position(), "Reference to unavailable annotation class " - + t.fullName()); - } - } - } - } - } else if (cl.isDeprecated()) { - // not hidden, but deprecated - Errors.error(Errors.DEPRECATED, - cl.position(), "Class " + cl.qualifiedName() - + " is deprecated"); - } - } - - // write out the stubs - HashMap<PackageInfo, List<ClassInfo>> packages = new HashMap<PackageInfo, List<ClassInfo>>(); - for (ClassInfo cl: notStrippable) { - if (!cl.isDocOnly()) { - if (stubPackages == null || stubPackages.contains(cl.containingPackage().name())) { - writeClassFile(stubsDir, cl); - if (packages.containsKey(cl.containingPackage())) { - packages.get(cl.containingPackage()).add(cl); - } else { - ArrayList<ClassInfo> classes = new ArrayList<ClassInfo>(); - classes.add(cl); - packages.put(cl.containingPackage(), classes); - } - } - } - } - - // write out the XML - if (writeXML && xmlWriter != null) { - writeXML(xmlWriter, packages, notStrippable); - } - - if (xmlWriter != null) { - xmlWriter.close(); - } - - } - - public static void cantStripThis(ClassInfo cl, HashSet<ClassInfo> notStrippable, String why) { - - if (!notStrippable.add(cl)) { - // slight optimization: if it already contains cl, it already contains - // all of cl's parents - return; - } - cl.setReasonIncluded(why); - - // cant strip annotations - /*if (cl.annotations() != null){ - for (AnnotationInstanceInfo ai : cl.annotations()){ - if (ai.type() != null){ - cantStripThis(ai.type(), notStrippable, "1:" + cl.qualifiedName()); - } - } - }*/ - // cant strip any public fields or their generics - if (cl.allSelfFields() != null){ - for (FieldInfo fInfo : cl.allSelfFields()){ - if (fInfo.type() != null){ - if (fInfo.type().asClassInfo() != null){ - cantStripThis(fInfo.type().asClassInfo(), notStrippable, - "2:" + cl.qualifiedName()); - } - if (fInfo.type().typeArguments() != null){ - for (TypeInfo tTypeInfo : fInfo.type().typeArguments()){ - if (tTypeInfo.asClassInfo() != null){ - cantStripThis(tTypeInfo.asClassInfo(), notStrippable, - "3:" + cl.qualifiedName()); - } - } - } - } - } - } - //cant strip any of the type's generics - if (cl.asTypeInfo() != null){ - if (cl.asTypeInfo().typeArguments() != null){ - for (TypeInfo tInfo : cl.asTypeInfo().typeArguments()){ - if (tInfo.asClassInfo() != null){ - cantStripThis(tInfo.asClassInfo(), notStrippable, "4:" + cl.qualifiedName()); - } - } - } - } - //cant strip any of the annotation elements - //cantStripThis(cl.annotationElements(), notStrippable); - // take care of methods - cantStripThis(cl.allSelfMethods(), notStrippable); - cantStripThis(cl.allConstructors(), notStrippable); - // blow the outer class open if this is an inner class - if(cl.containingClass() != null){ - cantStripThis(cl.containingClass(), notStrippable, "5:" + cl.qualifiedName()); - } - // blow open super class and interfaces - ClassInfo supr = cl.realSuperclass(); - if (supr != null) { - if (supr.isHidden()) { - // cl is a public class declared as extending a hidden superclass. - // this is not a desired practice but it's happened, so we deal - // with it by stripping off the superclass relation for purposes of - // generating the doc & stub information, and proceeding normally. - cl.init(cl.asTypeInfo(), cl.realInterfaces(), cl.realInterfaceTypes(), - cl.innerClasses(), cl.allConstructors(), cl.allSelfMethods(), - cl.annotationElements(), cl.allSelfFields(), cl.enumConstants(), - cl.containingPackage(), cl.containingClass(), - null, null, cl.annotations()); - Errors.error(Errors.HIDDEN_SUPERCLASS, - cl.position(), "Public class " + cl.qualifiedName() - + " stripped of unavailable superclass " - + supr.qualifiedName()); - } else { - cantStripThis(supr, notStrippable, "6:" + cl.realSuperclass().name() - + cl.qualifiedName()); - } - } - } - - private static void cantStripThis(MethodInfo[] mInfos , HashSet<ClassInfo> notStrippable) { - //for each method, blow open the parameters, throws and return types. also blow open their generics - if (mInfos != null){ - for (MethodInfo mInfo : mInfos){ - if (mInfo.getTypeParameters() != null){ - for (TypeInfo tInfo : mInfo.getTypeParameters()){ - if (tInfo.asClassInfo() != null){ - cantStripThis(tInfo.asClassInfo(), notStrippable, "8:" + - mInfo.realContainingClass().qualifiedName() + ":" + - mInfo.name()); - } - } - } - if (mInfo.parameters() != null){ - for (ParameterInfo pInfo : mInfo.parameters()){ - if (pInfo.type() != null && pInfo.type().asClassInfo() != null){ - cantStripThis(pInfo.type().asClassInfo(), notStrippable, - "9:"+ mInfo.realContainingClass().qualifiedName() - + ":" + mInfo.name()); - if (pInfo.type().typeArguments() != null){ - for (TypeInfo tInfoType : pInfo.type().typeArguments()){ - if (tInfoType.asClassInfo() != null){ - ClassInfo tcl = tInfoType.asClassInfo(); - if (tcl.isHidden()) { - Errors.error(Errors.UNAVAILABLE_SYMBOL, mInfo.position(), - "Parameter of hidden type " - + tInfoType.fullName() + " in " - + mInfo.containingClass().qualifiedName() - + '.' + mInfo.name() + "()"); - } else { - cantStripThis(tcl, notStrippable, - "10:" + - mInfo.realContainingClass().qualifiedName() + ":" + - mInfo.name()); - } - } - } - } - } - } - } - for (ClassInfo thrown : mInfo.thrownExceptions()){ - cantStripThis(thrown, notStrippable, "11:" + - mInfo.realContainingClass().qualifiedName() - +":" + mInfo.name()); - } - if (mInfo.returnType() != null && mInfo.returnType().asClassInfo() != null){ - cantStripThis(mInfo.returnType().asClassInfo(), notStrippable, - "12:" + mInfo.realContainingClass().qualifiedName() + - ":" + mInfo.name()); - if (mInfo.returnType().typeArguments() != null){ - for (TypeInfo tyInfo: mInfo.returnType().typeArguments() ){ - if (tyInfo.asClassInfo() != null){ - cantStripThis(tyInfo.asClassInfo(), notStrippable, - "13:" + - mInfo.realContainingClass().qualifiedName() - + ":" + mInfo.name()); - } - } - } - } - } - } - } - - static String javaFileName(ClassInfo cl) { - String dir = ""; - PackageInfo pkg = cl.containingPackage(); - if (pkg != null) { - dir = pkg.name(); - dir = dir.replace('.', '/') + '/'; - } - return dir + cl.name() + ".java"; - } - - static void writeClassFile(String stubsDir, ClassInfo cl) { - // inner classes are written by their containing class - if (cl.containingClass() != null) { - return; - } - - // Work around the bogus "Array" class we invent for - // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505) - if (cl.containingPackage() != null && cl.containingPackage().name().equals("")) { - return; - } - - String filename = stubsDir + '/' + javaFileName(cl); - File file = new File(filename); - ClearPage.ensureDirectory(file); - - PrintStream stream = null; - try { - stream = new PrintStream(file); - writeClassFile(stream, cl); - } - catch (FileNotFoundException e) { - System.err.println("error writing file: " + filename); - } - finally { - if (stream != null) { - stream.close(); - } - } - } - - static void writeClassFile(PrintStream stream, ClassInfo cl) { - PackageInfo pkg = cl.containingPackage(); - if (pkg != null) { - stream.println("package " + pkg.name() + ";"); - } - writeClass(stream, cl); - } - - static void writeClass(PrintStream stream, ClassInfo cl) { - writeAnnotations(stream, cl.annotations()); - - stream.print(DroidDoc.scope(cl) + " "); - if (cl.isAbstract() && !cl.isAnnotation() && !cl.isInterface()) { - stream.print("abstract "); - } - if (cl.isStatic()){ - stream.print("static "); - } - if (cl.isFinal() && !cl.isEnum()) { - stream.print("final "); - } - if (false) { - stream.print("strictfp "); - } - - HashSet<String> classDeclTypeVars = new HashSet(); - String leafName = cl.asTypeInfo().fullName(classDeclTypeVars); - int bracket = leafName.indexOf('<'); - if (bracket < 0) bracket = leafName.length() - 1; - int period = leafName.lastIndexOf('.', bracket); - if (period < 0) period = -1; - leafName = leafName.substring(period+1); - - String kind = cl.kind(); - stream.println(kind + " " + leafName); - - TypeInfo base = cl.superclassType(); - - if (!"enum".equals(kind)) { - if (base != null && !"java.lang.Object".equals(base.qualifiedTypeName())) { - stream.println(" extends " + base.fullName(classDeclTypeVars)); - } - } - - TypeInfo[] interfaces = cl.realInterfaceTypes(); - List<TypeInfo> usedInterfaces = new ArrayList<TypeInfo>(); - for (TypeInfo iface : interfaces) { - if (notStrippable.contains(iface.asClassInfo()) - && !iface.asClassInfo().isDocOnly()) { - usedInterfaces.add(iface); - } - } - if (usedInterfaces.size() > 0 && !cl.isAnnotation()) { - // can java annotations extend other ones? - if (cl.isInterface() || cl.isAnnotation()) { - stream.print(" extends "); - } else { - stream.print(" implements "); - } - String comma = ""; - for (TypeInfo iface: usedInterfaces) { - stream.print(comma + iface.fullName(classDeclTypeVars)); - comma = ", "; - } - stream.println(); - } - - stream.println("{"); - - FieldInfo[] enumConstants = cl.enumConstants(); - int N = enumConstants.length; - for (int i=0; i<N; i++) { - FieldInfo field = enumConstants[i]; - if (!field.constantLiteralValue().equals("null")){ - stream.println(field.name() + "(" + field.constantLiteralValue() - + (i==N-1 ? ");" : "),")); - }else{ - stream.println(field.name() + "(" + (i==N-1 ? ");" : "),")); - } - } - - for (ClassInfo inner: cl.getRealInnerClasses()) { - if (notStrippable.contains(inner) - && !inner.isDocOnly()){ - writeClass(stream, inner); - } - } - - - for (MethodInfo method: cl.constructors()) { - if (!method.isDocOnly()) { - writeMethod(stream, method, true); - } - } - - boolean fieldNeedsInitialization = false; - boolean staticFieldNeedsInitialization = false; - for (FieldInfo field: cl.allSelfFields()) { - if (!field.isDocOnly()) { - if (!field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) { - fieldNeedsInitialization = true; - } - if (field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) { - staticFieldNeedsInitialization = true; - } - } - } - - // The compiler includes a default public constructor that calls the super classes - // default constructor in the case where there are no written constructors. - // So, if we hide all the constructors, java may put in a constructor - // that calls a nonexistent super class constructor. So, if there are no constructors, - // and the super class doesn't have a default constructor, write in a private constructor - // that works. TODO -- we generate this as protected, but we really should generate - // it as private unless it also exists in the real code. - if ((cl.constructors().length == 0 && (cl.getNonWrittenConstructors().length != 0 - || fieldNeedsInitialization)) - && !cl.isAnnotation() - && !cl.isInterface() - && !cl.isEnum() ) { - //Errors.error(Errors.HIDDEN_CONSTRUCTOR, - // cl.position(), "No constructors " + - // "found and superclass has no parameterless constructor. A constructor " + - // "that calls an appropriate superclass constructor " + - // "was automatically written to stubs.\n"); - stream.println(cl.leafName() - + "() { " + superCtorCall(cl,null) - + "throw new" + " RuntimeException(\"Stub!\"); }"); - } - - for (MethodInfo method: cl.allSelfMethods()) { - if (cl.isEnum()) { - if (("values".equals(method.name()) - && "()".equals(method.signature())) - || ("valueOf".equals(method.name()) - && "(java.lang.String)".equals(method.signature()))) { - // skip these two methods on enums, because they're synthetic, - // although for some reason javadoc doesn't mark them as synthetic, - // maybe because they still want them documented - continue; - } - } - if (!method.isDocOnly()) { - writeMethod(stream, method, false); - } - } - //Write all methods that are hidden, but override abstract methods or interface methods. - //These can't be hidden. - for (MethodInfo method : cl.getHiddenMethods()){ - MethodInfo overriddenMethod = method.findRealOverriddenMethod(method.name(), method.signature(), notStrippable); - ClassInfo classContainingMethod = method.findRealOverriddenClass(method.name(), - method.signature()); - if (overriddenMethod != null && !overriddenMethod.isHidden() - && !overriddenMethod.isDocOnly() && - (overriddenMethod.isAbstract() || - overriddenMethod.containingClass().isInterface())) { - method.setReason("1:" + classContainingMethod.qualifiedName()); - cl.addMethod(method); - writeMethod(stream, method, false); - } - } - - for (MethodInfo element: cl.annotationElements()) { - if (!element.isDocOnly()) { - writeAnnotationElement(stream, element); - } - } - - for (FieldInfo field: cl.allSelfFields()) { - if (!field.isDocOnly()) { - writeField(stream, field); - } - } - - if (staticFieldNeedsInitialization) { - stream.print("static { "); - for (FieldInfo field: cl.allSelfFields()) { - if (!field.isDocOnly() && field.isStatic() && field.isFinal() - && !fieldIsInitialized(field) && field.constantValue() == null) { - stream.print(field.name() + " = " + field.type().defaultValue() - + "; "); - } - } - stream.println("}"); - } - - stream.println("}"); - } - - - static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) { - String comma; - - stream.print(DroidDoc.scope(method) + " "); - if (method.isStatic()) { - stream.print("static "); - } - if (method.isFinal()) { - stream.print("final "); - } - if (method.isAbstract()) { - stream.print("abstract "); - } - if (method.isSynchronized()) { - stream.print("synchronized "); - } - if (method.isNative()) { - stream.print("native "); - } - if (false /*method.isStictFP()*/) { - stream.print("strictfp "); - } - - stream.print(method.typeArgumentsName(new HashSet()) + " "); - - if (!isConstructor) { - stream.print(method.returnType().fullName(method.typeVariables()) + " "); - } - String n = method.name(); - int pos = n.lastIndexOf('.'); - if (pos >= 0) { - n = n.substring(pos + 1); - } - stream.print(n + "("); - comma = ""; - int count = 1; - int size = method.parameters().length; - for (ParameterInfo param: method.parameters()) { - stream.print(comma + fullParameterTypeName(method, param.type(), count == size) - + " " + param.name()); - comma = ", "; - count++; - } - stream.print(")"); - - comma = ""; - if (method.thrownExceptions().length > 0) { - stream.print(" throws "); - for (ClassInfo thrown: method.thrownExceptions()) { - stream.print(comma + thrown.qualifiedName()); - comma = ", "; - } - } - if (method.isAbstract() || method.isNative() || method.containingClass().isInterface()) { - stream.println(";"); - } else { - stream.print(" { "); - if (isConstructor) { - stream.print(superCtorCall(method.containingClass(), method.thrownExceptions())); - } - stream.println("throw new RuntimeException(\"Stub!\"); }"); - } - } - - static void writeField(PrintStream stream, FieldInfo field) { - stream.print(DroidDoc.scope(field) + " "); - if (field.isStatic()) { - stream.print("static "); - } - if (field.isFinal()) { - stream.print("final "); - } - if (field.isTransient()) { - stream.print("transient "); - } - if (field.isVolatile()) { - stream.print("volatile "); - } - - stream.print(field.type().fullName()); - stream.print(" "); - stream.print(field.name()); - - if (fieldIsInitialized(field)) { - stream.print(" = " + field.constantLiteralValue()); - } - - stream.println(";"); - } - - static boolean fieldIsInitialized(FieldInfo field) { - return (field.isFinal() && field.constantValue() != null) - || !field.type().dimension().equals("") - || field.containingClass().isInterface(); - } - - // Returns 'true' if the method is an @Override of a visible parent - // method implementation, and thus does not affect the API. - static boolean methodIsOverride(MethodInfo mi) { - // Abstract/static/final methods are always listed in the API description - if (mi.isAbstract() || mi.isStatic() || mi.isFinal()) { - return false; - } - - // Find any relevant ancestor declaration and inspect it - MethodInfo om = mi.findSuperclassImplementation(notStrippable); - if (om != null) { - // Visibility mismatch is an API change, so check for it - if (mi.mIsPrivate == om.mIsPrivate - && mi.mIsPublic == om.mIsPublic - && mi.mIsProtected == om.mIsProtected) { - // Look only for overrides of an ancestor class implementation, - // not of e.g. an abstract or interface method declaration - if (!om.isAbstract()) { - // If the parent is hidden, we can't rely on it to provide - // the API - if (!om.isHidden()) { - // If the only "override" turns out to be in our own class - // (which sometimes happens in concrete subclasses of - // abstract base classes), it's not really an override - if (!mi.mContainingClass.equals(om.mContainingClass)) { - return true; - } - } - } - } - } - return false; - } - - static boolean canCallMethod(ClassInfo from, MethodInfo m) { - if (m.isPublic() || m.isProtected()) { - return true; - } - if (m.isPackagePrivate()) { - String fromPkg = from.containingPackage().name(); - String pkg = m.containingClass().containingPackage().name(); - if (fromPkg.equals(pkg)) { - return true; - } - } - return false; - } - - // call a constructor, any constructor on this class's superclass. - static String superCtorCall(ClassInfo cl, ClassInfo[] thrownExceptions) { - ClassInfo base = cl.realSuperclass(); - if (base == null) { - return ""; - } - HashSet<String> exceptionNames = new HashSet<String>(); - if (thrownExceptions != null ){ - for (ClassInfo thrown : thrownExceptions){ - exceptionNames.add(thrown.name()); - } - } - MethodInfo[] ctors = base.constructors(); - MethodInfo ctor = null; - //bad exception indicates that the exceptions thrown by the super constructor - //are incompatible with the constructor we're using for the sub class. - Boolean badException = false; - for (MethodInfo m: ctors) { - if (canCallMethod(cl, m)) { - if (m.thrownExceptions() != null){ - for (ClassInfo thrown : m.thrownExceptions()){ - if (!exceptionNames.contains(thrown.name())){ - badException = true; - } - } - } - if (badException){ - badException = false; - continue; - } - // if it has no args, we're done - if (m.parameters().length == 0) { - return ""; - } - ctor = m; - } - } - if (ctor != null) { - String result = ""; - result+= "super("; - ParameterInfo[] params = ctor.parameters(); - int N = params.length; - for (int i=0; i<N; i++) { - TypeInfo t = params[i].type(); - if (t.isPrimitive() && t.dimension().equals("")) { - String n = t.simpleTypeName(); - if (("byte".equals(n) - || "short".equals(n) - || "int".equals(n) - || "long".equals(n) - || "float".equals(n) - || "double".equals(n)) && t.dimension().equals("")) { - result += "0"; - } - else if ("char".equals(n)) { - result += "'\\0'"; - } - else if ("boolean".equals(n)) { - result += "false"; - } - else { - result += "<<unknown-" + n + ">>"; - } - } else { - //put null in each super class method. Cast null to the correct type - //to avoid collisions with other constructors. If the type is generic - //don't cast it - result += (!t.isTypeVariable() ? "(" + t.qualifiedTypeName() + t.dimension() + - ")" : "") + "null"; - } - if (i != N-1) { - result += ","; - } - } - result += "); "; - return result; - } else { - return ""; - } - } - - static void writeAnnotations(PrintStream stream, AnnotationInstanceInfo[] annotations) { - for (AnnotationInstanceInfo ann: annotations) { - if (!ann.type().isHidden()) { - stream.println(ann.toString()); - } - } - } - - static void writeAnnotationElement(PrintStream stream, MethodInfo ann) { - stream.print(ann.returnType().fullName()); - stream.print(" "); - stream.print(ann.name()); - stream.print("()"); - AnnotationValueInfo def = ann.defaultAnnotationElementValue(); - if (def != null) { - stream.print(" default "); - stream.print(def.valueString()); - } - stream.println(";"); - } - - static void writeXML(PrintStream xmlWriter, HashMap<PackageInfo, List<ClassInfo>> allClasses, - HashSet notStrippable) { - // extract the set of packages, sort them by name, and write them out in that order - Set<PackageInfo> allClassKeys = allClasses.keySet(); - PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]); - Arrays.sort(allPackages, PackageInfo.comparator); - - xmlWriter.println("<api>"); - for (PackageInfo pack : allPackages) { - writePackageXML(xmlWriter, pack, allClasses.get(pack), notStrippable); - } - xmlWriter.println("</api>"); - } - - static void writePackageXML(PrintStream xmlWriter, PackageInfo pack, List<ClassInfo> classList, - HashSet notStrippable) { - ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]); - Arrays.sort(classes, ClassInfo.comparator); - // Work around the bogus "Array" class we invent for - // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505) - if (pack.name().equals("")) { - return; - } - xmlWriter.println("<package name=\"" + pack.name() + "\"\n" - //+ " source=\"" + pack.position() + "\"\n" - + ">"); - for (ClassInfo cl : classes) { - writeClassXML(xmlWriter, cl, notStrippable); - } - xmlWriter.println("</package>"); - - - } - - static void writeClassXML(PrintStream xmlWriter, ClassInfo cl, HashSet notStrippable) { - String scope = DroidDoc.scope(cl); - String deprecatedString = ""; - String declString = (cl.isInterface()) ? "interface" : "class"; - if (cl.isDeprecated()) { - deprecatedString = "deprecated"; - } else { - deprecatedString = "not deprecated"; - } - xmlWriter.println("<" + declString + " name=\"" + cl.name() + "\""); - if (!cl.isInterface() && !cl.qualifiedName().equals("java.lang.Object")) { - xmlWriter.println(" extends=\"" + ((cl.realSuperclass() == null) - ? "java.lang.Object" - : cl.realSuperclass().qualifiedName()) + "\""); - } - xmlWriter.println(" abstract=\"" + cl.isAbstract() + "\"\n" - + " static=\"" + cl.isStatic() + "\"\n" - + " final=\"" + cl.isFinal() + "\"\n" - + " deprecated=\"" + deprecatedString + "\"\n" - + " visibility=\"" + scope + "\"\n" - //+ " source=\"" + cl.position() + "\"\n" - + ">"); - - ClassInfo[] interfaces = cl.realInterfaces(); - Arrays.sort(interfaces, ClassInfo.comparator); - for (ClassInfo iface : interfaces) { - if (notStrippable.contains(iface)) { - xmlWriter.println("<implements name=\"" + iface.qualifiedName() + "\">"); - xmlWriter.println("</implements>"); - } - } - - MethodInfo[] constructors = cl.constructors(); - Arrays.sort(constructors, MethodInfo.comparator); - for (MethodInfo mi : constructors) { - writeConstructorXML(xmlWriter, mi); - } - - MethodInfo[] methods = cl.allSelfMethods(); - Arrays.sort(methods, MethodInfo.comparator); - for (MethodInfo mi : methods) { - if (!methodIsOverride(mi)) { - writeMethodXML(xmlWriter, mi); - } - } - - FieldInfo[] fields = cl.allSelfFields(); - Arrays.sort(fields, FieldInfo.comparator); - for (FieldInfo fi : fields) { - writeFieldXML(xmlWriter, fi); - } - xmlWriter.println("</" + declString + ">"); - - } - - static void writeMethodXML(PrintStream xmlWriter, MethodInfo mi) { - String scope = DroidDoc.scope(mi); - - String deprecatedString = ""; - if (mi.isDeprecated()) { - deprecatedString = "deprecated"; - } else { - deprecatedString = "not deprecated"; - } - xmlWriter.println("<method name=\"" + mi.name() + "\"\n" - + ((mi.returnType() != null) - ? " return=\"" + makeXMLcompliant(fullParameterTypeName(mi, mi.returnType(), false)) + "\"\n" - : "") - + " abstract=\"" + mi.isAbstract() + "\"\n" - + " native=\"" + mi.isNative() + "\"\n" - + " synchronized=\"" + mi.isSynchronized() + "\"\n" - + " static=\"" + mi.isStatic() + "\"\n" - + " final=\"" + mi.isFinal() + "\"\n" - + " deprecated=\""+ deprecatedString + "\"\n" - + " visibility=\"" + scope + "\"\n" - //+ " source=\"" + mi.position() + "\"\n" - + ">"); - - // write parameters in declaration order - int numParameters = mi.parameters().length; - int count = 0; - for (ParameterInfo pi : mi.parameters()) { - count++; - writeParameterXML(xmlWriter, mi, pi, count == numParameters); - } - - // but write exceptions in canonicalized order - ClassInfo[] exceptions = mi.thrownExceptions(); - Arrays.sort(exceptions, ClassInfo.comparator); - for (ClassInfo pi : exceptions) { - xmlWriter.println("<exception name=\"" + pi.name() +"\" type=\"" + pi.qualifiedName() - + "\">"); - xmlWriter.println("</exception>"); - } - xmlWriter.println("</method>"); - } - - static void writeConstructorXML(PrintStream xmlWriter, MethodInfo mi) { - String scope = DroidDoc.scope(mi); - String deprecatedString = ""; - if (mi.isDeprecated()) { - deprecatedString = "deprecated"; - } else { - deprecatedString = "not deprecated"; - } - xmlWriter.println("<constructor name=\"" + mi.name() + "\"\n" - + " type=\"" + mi.containingClass().qualifiedName() + "\"\n" - + " static=\"" + mi.isStatic() + "\"\n" - + " final=\"" + mi.isFinal() + "\"\n" - + " deprecated=\"" + deprecatedString + "\"\n" - + " visibility=\"" + scope +"\"\n" - //+ " source=\"" + mi.position() + "\"\n" - + ">"); - - int numParameters = mi.parameters().length; - int count = 0; - for (ParameterInfo pi : mi.parameters()) { - count++; - writeParameterXML(xmlWriter, mi, pi, count == numParameters); - } - - ClassInfo[] exceptions = mi.thrownExceptions(); - Arrays.sort(exceptions, ClassInfo.comparator); - for (ClassInfo pi : exceptions) { - xmlWriter.println("<exception name=\"" + pi.name() +"\" type=\"" + pi.qualifiedName() - + "\">"); - xmlWriter.println("</exception>"); - } - xmlWriter.println("</constructor>"); - } - - static void writeParameterXML(PrintStream xmlWriter, MethodInfo method, - ParameterInfo pi, boolean isLast) { - xmlWriter.println("<parameter name=\"" + pi.name() + "\" type=\"" + - makeXMLcompliant(fullParameterTypeName(method, pi.type(), isLast)) + "\">"); - xmlWriter.println("</parameter>"); - } - - static void writeFieldXML(PrintStream xmlWriter, FieldInfo fi) { - String scope = DroidDoc.scope(fi); - String deprecatedString = ""; - if (fi.isDeprecated()) { - deprecatedString = "deprecated"; - } else { - deprecatedString = "not deprecated"; - } - //need to make sure value is valid XML - String value = makeXMLcompliant(fi.constantLiteralValue()); - - String fullTypeName = makeXMLcompliant(fi.type().qualifiedTypeName()) - + fi.type().dimension(); - - xmlWriter.println("<field name=\"" + fi.name() +"\"\n" - + " type=\"" + fullTypeName + "\"\n" - + " transient=\"" + fi.isTransient() + "\"\n" - + " volatile=\"" + fi.isVolatile() + "\"\n" - + (fieldIsInitialized(fi) ? " value=\"" + value + "\"\n" : "") - + " static=\"" + fi.isStatic() + "\"\n" - + " final=\"" + fi.isFinal() + "\"\n" - + " deprecated=\"" + deprecatedString + "\"\n" - + " visibility=\"" + scope + "\"\n" - //+ " source=\"" + fi.position() + "\"\n" - + ">"); - xmlWriter.println("</field>"); - } - - static String makeXMLcompliant(String s) { - String returnString = ""; - returnString = s.replaceAll("&", "&"); - returnString = returnString.replaceAll("<", "<"); - returnString = returnString.replaceAll(">", ">"); - returnString = returnString.replaceAll("\"", """); - returnString = returnString.replaceAll("'", "&pos;"); - return returnString; - } - - static String fullParameterTypeName(MethodInfo method, TypeInfo type, boolean isLast) { - String fullTypeName = type.fullName(method.typeVariables()); - if (isLast && method.isVarArgs()) { - // TODO: note that this does not attempt to handle hypothetical - // vararg methods whose last parameter is a list of arrays, e.g. - // "Object[]...". - fullTypeName = type.fullNameNoDimension(method.typeVariables()) + "..."; - } - return fullTypeName; - } -} |