1920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson/*
2920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Copyright (C) 2010 Google Inc.
3920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
4920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Licensed under the Apache License, Version 2.0 (the "License");
5920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * you may not use this file except in compliance with the License.
6920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * You may obtain a copy of the License at
7920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
8920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * http://www.apache.org/licenses/LICENSE-2.0
9920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson *
10920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * Unless required by applicable law or agreed to in writing, software
11920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * distributed under the License is distributed on an "AS IS" BASIS,
12920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * See the License for the specific language governing permissions and
14920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson * limitations under the License.
15920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson */
16920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
17920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonpackage com.google.doclava;
18920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
19ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstromimport java.io.BufferedOutputStream;
20920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.File;
21920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.FileNotFoundException;
22ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstromimport java.io.FileOutputStream;
23920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonimport java.io.PrintStream;
24d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.ArrayList;
25d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.Arrays;
26d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.Collection;
27d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.Collections;
28d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.HashMap;
29d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.HashSet;
30d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.List;
31d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sappersteinimport java.util.Set;
32920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
33920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodsonpublic class Stubs {
34970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  public static void writeStubsAndApi(String stubsDir, String apiFile, String keepListFile,
35920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      HashSet<String> stubPackages) {
36920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // figure out which classes we need
37040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final HashSet<ClassInfo> notStrippable = new HashSet<ClassInfo>();
38920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo[] all = Converter.allClasses();
39040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    PrintStream apiWriter = null;
40970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    PrintStream keepListWriter = null;
41040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (apiFile != null) {
42920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      try {
43040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        File xml = new File(apiFile);
44920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        xml.getParentFile().mkdirs();
45ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstrom        apiWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(xml)));
46920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } catch (FileNotFoundException e) {
47040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        Errors.error(Errors.IO_ERROR, new SourcePositionInfo(apiFile, 0, 0),
48920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            "Cannot open file for write.");
49920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
50920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
51970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (keepListFile != null) {
52970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      try {
53970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        File keepList = new File(keepListFile);
54970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        keepList.getParentFile().mkdirs();
55970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        keepListWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(keepList)));
56970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      } catch (FileNotFoundException e) {
57970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        Errors.error(Errors.IO_ERROR, new SourcePositionInfo(keepListFile, 0, 0),
58970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton            "Cannot open file for write.");
59970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
60970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
61920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // If a class is public or protected, not hidden, and marked as included,
62920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // then we can't strip it
63920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : all) {
64920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.checkLevel() && cl.isIncluded()) {
65920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cantStripThis(cl, notStrippable, "0:0");
66920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
67920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
68920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
69920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // complain about anything that looks includeable but is not supposed to
70920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // be written, e.g. hidden things
71920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : notStrippable) {
72920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!cl.isHidden()) {
73d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (MethodInfo m : cl.selfMethods()) {
74920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (m.isHidden()) {
75920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Reference to hidden method "
76920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + m.name());
77920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if (m.isDeprecated()) {
78920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // don't bother reporting deprecated methods
79920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // unless they are public
80920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.DEPRECATED, m.position(), "Method " + cl.qualifiedName() + "."
81920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + m.name() + " is deprecated");
82920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
83920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
84920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          ClassInfo returnClass = m.returnType().asClassInfo();
85920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (returnClass != null && returnClass.isHidden()) {
86920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Method " + cl.qualifiedName()
87920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + "." + m.name() + " returns unavailable type " + returnClass.name());
88920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
89920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
90d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          for (ParameterInfo p :  m.parameters()) {
91920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            TypeInfo t = p.type();
92920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!t.isPrimitive()) {
93920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (t.asClassInfo().isHidden()) {
94920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Parameter of hidden type "
95920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    + t.fullName() + " in " + cl.qualifiedName() + "." + m.name() + "()");
96920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
97920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
98920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
99920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
100920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
101920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // annotations are handled like methods
102d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (MethodInfo m : cl.annotationElements()) {
103920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (m.isHidden()) {
104920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Reference to hidden annotation "
105920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + m.name());
106920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
107920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
108920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          ClassInfo returnClass = m.returnType().asClassInfo();
109920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (returnClass != null && returnClass.isHidden()) {
110920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Annotation '" + m.name()
111920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + "' returns unavailable type " + returnClass.name());
112920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
113920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
114d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          for (ParameterInfo p :  m.parameters()) {
115920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            TypeInfo t = p.type();
116920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!t.isPrimitive()) {
117920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (t.asClassInfo().isHidden()) {
118920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                Errors.error(Errors.UNAVAILABLE_SYMBOL, p.position(),
119920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    "Reference to unavailable annotation class " + t.fullName());
120920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
121920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
122920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
123920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
124920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else if (cl.isDeprecated()) {
125920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // not hidden, but deprecated
126920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        Errors.error(Errors.DEPRECATED, cl.position(), "Class " + cl.qualifiedName()
127920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + " is deprecated");
128920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
129920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
130920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
131920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    HashMap<PackageInfo, List<ClassInfo>> packages = new HashMap<PackageInfo, List<ClassInfo>>();
132920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : notStrippable) {
133920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!cl.isDocOnly()) {
134920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (stubPackages == null || stubPackages.contains(cl.containingPackage().name())) {
135920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // write out the stubs
136920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (stubsDir != null) {
137040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            writeClassFile(stubsDir, notStrippable, cl);
138920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
139970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton          // build class list for api file or keep list file
140970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton          if (apiWriter != null || keepListWriter != null) {
141920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (packages.containsKey(cl.containingPackage())) {
142920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              packages.get(cl.containingPackage()).add(cl);
143920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            } else {
144920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              ArrayList<ClassInfo> classes = new ArrayList<ClassInfo>();
145920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              classes.add(cl);
146920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              packages.put(cl.containingPackage(), classes);
147920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
148920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
149920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
150920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
151920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
152920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
153040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // write out the Api
154040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (apiWriter != null) {
155040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeApi(apiWriter, packages, notStrippable);
156040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.close();
157920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
158970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
159970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // write out the keep list
160970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (keepListWriter != null) {
161970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeKeepList(keepListWriter, packages, notStrippable);
162970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.close();
163970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
164920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
165920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
166920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public static void cantStripThis(ClassInfo cl, HashSet<ClassInfo> notStrippable, String why) {
167920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
168920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!notStrippable.add(cl)) {
169920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // slight optimization: if it already contains cl, it already contains
170920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // all of cl's parents
171920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
172920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
173920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    cl.setReasonIncluded(why);
174920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
175920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip annotations
176920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    /*
177920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     * if (cl.annotations() != null){ for (AnnotationInstanceInfo ai : cl.annotations()){ if
178920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     * (ai.type() != null){ cantStripThis(ai.type(), notStrippable, "1:" + cl.qualifiedName()); } }
179920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     * }
180920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     */
181920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip any public fields or their generics
182920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.allSelfFields() != null) {
183920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (FieldInfo fInfo : cl.allSelfFields()) {
184920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (fInfo.type() != null) {
185920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (fInfo.type().asClassInfo() != null) {
186920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cantStripThis(fInfo.type().asClassInfo(), notStrippable, "2:" + cl.qualifiedName());
187920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
188920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (fInfo.type().typeArguments() != null) {
189920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            for (TypeInfo tTypeInfo : fInfo.type().typeArguments()) {
190920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (tTypeInfo.asClassInfo() != null) {
191920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                cantStripThis(tTypeInfo.asClassInfo(), notStrippable, "3:" + cl.qualifiedName());
192920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
193920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
194920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
195920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
196920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
197920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
198920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip any of the type's generics
199920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.asTypeInfo() != null) {
200920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.asTypeInfo().typeArguments() != null) {
201920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        for (TypeInfo tInfo : cl.asTypeInfo().typeArguments()) {
202920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (tInfo.asClassInfo() != null) {
203920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cantStripThis(tInfo.asClassInfo(), notStrippable, "4:" + cl.qualifiedName());
204920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
205920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
206920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
207920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
208920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip any of the annotation elements
209920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cantStripThis(cl.annotationElements(), notStrippable);
210920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // take care of methods
211920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    cantStripThis(cl.allSelfMethods(), notStrippable);
212920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    cantStripThis(cl.allConstructors(), notStrippable);
213920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // blow the outer class open if this is an inner class
214920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.containingClass() != null) {
215920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      cantStripThis(cl.containingClass(), notStrippable, "5:" + cl.qualifiedName());
216920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
217920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // blow open super class and interfaces
218920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo supr = cl.realSuperclass();
219920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (supr != null) {
220920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (supr.isHidden()) {
221920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // cl is a public class declared as extending a hidden superclass.
222920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // this is not a desired practice but it's happened, so we deal
223920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // with it by stripping off the superclass relation for purposes of
224920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // generating the doc & stub information, and proceeding normally.
225920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cl.init(cl.asTypeInfo(), cl.realInterfaces(), cl.realInterfaceTypes(), cl.innerClasses(),
226920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cl.allConstructors(), cl.allSelfMethods(), cl.annotationElements(), cl.allSelfFields(),
227920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cl.enumConstants(), cl.containingPackage(), cl.containingClass(), null, null, cl
228920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                .annotations());
229920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        Errors.error(Errors.HIDDEN_SUPERCLASS, cl.position(), "Public class " + cl.qualifiedName()
230920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + " stripped of unavailable superclass " + supr.qualifiedName());
231920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
232920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cantStripThis(supr, notStrippable, "6:" + cl.realSuperclass().name() + cl.qualifiedName());
233920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
234920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
235920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
236920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
237d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  private static void cantStripThis(ArrayList<MethodInfo> mInfos, HashSet<ClassInfo> notStrippable) {
238920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // for each method, blow open the parameters, throws and return types. also blow open their
239920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // generics
240920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mInfos != null) {
241920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (MethodInfo mInfo : mInfos) {
242920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (mInfo.getTypeParameters() != null) {
243920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (TypeInfo tInfo : mInfo.getTypeParameters()) {
244920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (tInfo.asClassInfo() != null) {
245920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              cantStripThis(tInfo.asClassInfo(), notStrippable, "8:"
246920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
247920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
248920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
249920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
250920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (mInfo.parameters() != null) {
251920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (ParameterInfo pInfo : mInfo.parameters()) {
252920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (pInfo.type() != null && pInfo.type().asClassInfo() != null) {
253920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              cantStripThis(pInfo.type().asClassInfo(), notStrippable, "9:"
254920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
255920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (pInfo.type().typeArguments() != null) {
256920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                for (TypeInfo tInfoType : pInfo.type().typeArguments()) {
257920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  if (tInfoType.asClassInfo() != null) {
258920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    ClassInfo tcl = tInfoType.asClassInfo();
259920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    if (tcl.isHidden()) {
260920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                      Errors
261920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                          .error(Errors.UNAVAILABLE_SYMBOL, mInfo.position(),
262920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                              "Parameter of hidden type " + tInfoType.fullName() + " in "
263920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                                  + mInfo.containingClass().qualifiedName() + '.' + mInfo.name()
264920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                                  + "()");
265920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    } else {
266920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                      cantStripThis(tcl, notStrippable, "10:"
267920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                          + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
268920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    }
269920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  }
270920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                }
271920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
272920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
273920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
274920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
275920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        for (ClassInfo thrown : mInfo.thrownExceptions()) {
276920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          cantStripThis(thrown, notStrippable, "11:" + mInfo.realContainingClass().qualifiedName()
277920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              + ":" + mInfo.name());
278920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
279920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (mInfo.returnType() != null && mInfo.returnType().asClassInfo() != null) {
280920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          cantStripThis(mInfo.returnType().asClassInfo(), notStrippable, "12:"
281920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
282920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (mInfo.returnType().typeArguments() != null) {
283920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            for (TypeInfo tyInfo : mInfo.returnType().typeArguments()) {
284920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (tyInfo.asClassInfo() != null) {
285920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                cantStripThis(tyInfo.asClassInfo(), notStrippable, "13:"
286920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
287920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
288920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
289920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
290920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
291920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
292920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
293920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
294920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
295920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static String javaFileName(ClassInfo cl) {
296920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String dir = "";
297920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PackageInfo pkg = cl.containingPackage();
298920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pkg != null) {
299920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      dir = pkg.name();
300920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      dir = dir.replace('.', '/') + '/';
301920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
302920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return dir + cl.name() + ".java";
303920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
304920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
305040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassFile(String stubsDir, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
306920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // inner classes are written by their containing class
307920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.containingClass() != null) {
308920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
309920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
310920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
311920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Work around the bogus "Array" class we invent for
312920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
313920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.containingPackage() != null
314920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        && cl.containingPackage().name().equals(PackageInfo.DEFAULT_PACKAGE)) {
315920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
316920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
317920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
318920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String filename = stubsDir + '/' + javaFileName(cl);
319920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    File file = new File(filename);
320920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClearPage.ensureDirectory(file);
321920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
322920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PrintStream stream = null;
323920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
324ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstrom      stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
325040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeClassFile(stream, notStrippable, cl);
326920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (FileNotFoundException e) {
327920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      System.err.println("error writing file: " + filename);
328920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } finally {
329920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (stream != null) {
330920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.close();
331920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
332920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
333920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
334920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
335040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassFile(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
336920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PackageInfo pkg = cl.containingPackage();
337920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pkg != null) {
338920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println("package " + pkg.name() + ";");
339920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
340040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeClass(stream, notStrippable, cl);
341920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
342920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
343040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClass(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
34473934887ea87fca353449f0fd476d6c07b349521Tor Norbye    writeAnnotations(stream, cl.annotations(), cl.isDeprecated());
345920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
346920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(cl.scope() + " ");
347920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isAbstract() && !cl.isAnnotation() && !cl.isInterface()) {
348920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("abstract ");
349920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
350920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isStatic()) {
351920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static ");
352920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
353920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isFinal() && !cl.isEnum()) {
354920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("final ");
355920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
356920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (false) {
357920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("strictfp ");
358920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
359920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
360920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    HashSet<String> classDeclTypeVars = new HashSet();
361920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String leafName = cl.asTypeInfo().fullName(classDeclTypeVars);
362920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int bracket = leafName.indexOf('<');
363920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (bracket < 0) bracket = leafName.length() - 1;
364920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int period = leafName.lastIndexOf('.', bracket);
365920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (period < 0) period = -1;
366920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    leafName = leafName.substring(period + 1);
367920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
368920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String kind = cl.kind();
369920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println(kind + " " + leafName);
370920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
371920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    TypeInfo base = cl.superclassType();
372920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
373920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!"enum".equals(kind)) {
374920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (base != null && !"java.lang.Object".equals(base.qualifiedTypeName())) {
375920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println("  extends " + base.fullName(classDeclTypeVars));
376920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
377920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
378920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
379920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<TypeInfo> usedInterfaces = new ArrayList<TypeInfo>();
380d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (TypeInfo iface : cl.realInterfaceTypes()) {
381920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (notStrippable.contains(iface.asClassInfo()) && !iface.asClassInfo().isDocOnly()) {
382920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        usedInterfaces.add(iface);
383920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
384920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
385920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (usedInterfaces.size() > 0 && !cl.isAnnotation()) {
386920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // can java annotations extend other ones?
387920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.isInterface() || cl.isAnnotation()) {
388920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print("  extends ");
389920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
390920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print("  implements ");
391920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
392920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String comma = "";
393920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (TypeInfo iface : usedInterfaces) {
394920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print(comma + iface.fullName(classDeclTypeVars));
395920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        comma = ", ";
396920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
397920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println();
398920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
399920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
400920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println("{");
401920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
402d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<FieldInfo> enumConstants = cl.enumConstants();
403d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int N = enumConstants.size();
404d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int i = 0;
405d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (FieldInfo field : enumConstants) {
406920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!field.constantLiteralValue().equals("null")) {
407920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println(field.name() + "(" + field.constantLiteralValue()
408920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + (i == N - 1 ? ");" : "),"));
409920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
410920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println(field.name() + "(" + (i == N - 1 ? ");" : "),"));
411920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
412d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      i++;
413920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
414920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
415920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo inner : cl.getRealInnerClasses()) {
416920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (notStrippable.contains(inner) && !inner.isDocOnly()) {
417040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        writeClass(stream, notStrippable, inner);
418920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
419920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
420920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
421920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
422920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo method : cl.constructors()) {
423920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!method.isDocOnly()) {
424920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethod(stream, method, true);
425920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
426920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
427920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
428920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    boolean fieldNeedsInitialization = false;
429920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    boolean staticFieldNeedsInitialization = false;
430920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FieldInfo field : cl.allSelfFields()) {
431920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!field.isDocOnly()) {
432920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (!field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
433920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          fieldNeedsInitialization = true;
434920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
435920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
436920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          staticFieldNeedsInitialization = true;
437920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
438920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
439920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
440920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
441920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // The compiler includes a default public constructor that calls the super classes
442920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // default constructor in the case where there are no written constructors.
443920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // So, if we hide all the constructors, java may put in a constructor
444920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // that calls a nonexistent super class constructor. So, if there are no constructors,
445920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // and the super class doesn't have a default constructor, write in a private constructor
446920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // that works. TODO -- we generate this as protected, but we really should generate
447920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // it as private unless it also exists in the real code.
448d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    if ((cl.constructors().isEmpty() && (!cl.getNonWrittenConstructors().isEmpty() || fieldNeedsInitialization))
449920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        && !cl.isAnnotation() && !cl.isInterface() && !cl.isEnum()) {
450920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // Errors.error(Errors.HIDDEN_CONSTRUCTOR,
451920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // cl.position(), "No constructors " +
452920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "found and superclass has no parameterless constructor.  A constructor " +
453920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "that calls an appropriate superclass constructor " +
454920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "was automatically written to stubs.\n");
455920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println(cl.leafName() + "() { " + superCtorCall(cl, null) + "throw new"
456920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + " RuntimeException(\"Stub!\"); }");
457920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
458920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
459920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo method : cl.allSelfMethods()) {
460920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.isEnum()) {
461920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (("values".equals(method.name()) && "()".equals(method.signature()))
462920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            || ("valueOf".equals(method.name()) && "(java.lang.String)".equals(method.signature()))) {
463920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // skip these two methods on enums, because they're synthetic,
464920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // although for some reason javadoc doesn't mark them as synthetic,
465920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // maybe because they still want them documented
466920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          continue;
467920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
468920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
469920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!method.isDocOnly()) {
470920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethod(stream, method, false);
471920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
472920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
473920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Write all methods that are hidden, but override abstract methods or interface methods.
474920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // These can't be hidden.
475920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo method : cl.getHiddenMethods()) {
476920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      MethodInfo overriddenMethod =
477920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          method.findRealOverriddenMethod(method.name(), method.signature(), notStrippable);
478920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      ClassInfo classContainingMethod =
479920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          method.findRealOverriddenClass(method.name(), method.signature());
480920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (overriddenMethod != null && !overriddenMethod.isHidden() && !overriddenMethod.isDocOnly()
481920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          && (overriddenMethod.isAbstract() || overriddenMethod.containingClass().isInterface())) {
482920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        method.setReason("1:" + classContainingMethod.qualifiedName());
483920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cl.addMethod(method);
484920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethod(stream, method, false);
485920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
486920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
487920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
488920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo element : cl.annotationElements()) {
489920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!element.isDocOnly()) {
490920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeAnnotationElement(stream, element);
491920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
492920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
493920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
494920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FieldInfo field : cl.allSelfFields()) {
495920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!field.isDocOnly()) {
496920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeField(stream, field);
497920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
498920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
499920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
500920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (staticFieldNeedsInitialization) {
501920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static { ");
502920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (FieldInfo field : cl.allSelfFields()) {
503920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (!field.isDocOnly() && field.isStatic() && field.isFinal() && !fieldIsInitialized(field)
504920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            && field.constantValue() == null) {
505920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          stream.print(field.name() + " = " + field.type().defaultValue() + "; ");
506920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
507920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
508920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println("}");
509920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
510920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
511920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println("}");
512920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
513920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
514920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
515920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) {
516920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String comma;
517920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
51873934887ea87fca353449f0fd476d6c07b349521Tor Norbye    writeAnnotations(stream, method.annotations(), method.isDeprecated());
51973934887ea87fca353449f0fd476d6c07b349521Tor Norbye
520920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(method.scope() + " ");
521920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isStatic()) {
522920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static ");
523920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
524920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isFinal()) {
525920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("final ");
526920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
527920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isAbstract()) {
528920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("abstract ");
529920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
530920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isSynchronized()) {
531920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("synchronized ");
532920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
533920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isNative()) {
534920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("native ");
535920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
536920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (false /* method.isStictFP() */) {
537920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("strictfp ");
538920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
539920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
540920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(method.typeArgumentsName(new HashSet()) + " ");
541920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
542920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!isConstructor) {
543920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(method.returnType().fullName(method.typeVariables()) + " ");
544920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
545920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String n = method.name();
546920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int pos = n.lastIndexOf('.');
547920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pos >= 0) {
548920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      n = n.substring(pos + 1);
549920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
550920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(n + "(");
551920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    comma = "";
552920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int count = 1;
553d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int size = method.parameters().size();
554920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ParameterInfo param : method.parameters()) {
555920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(comma + fullParameterTypeName(method, param.type(), count == size) + " "
556920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + param.name());
557920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      comma = ", ";
558920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      count++;
559920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
560920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(")");
561920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
562920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    comma = "";
563d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    if (method.thrownExceptions().size() > 0) {
564920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" throws ");
565920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (ClassInfo thrown : method.thrownExceptions()) {
566920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print(comma + thrown.qualifiedName());
567920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        comma = ", ";
568920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
569920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
570920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isAbstract() || method.isNative() || method.containingClass().isInterface()) {
571920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println(";");
572920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
573920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" { ");
574920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (isConstructor) {
575920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print(superCtorCall(method.containingClass(), method.thrownExceptions()));
576920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
577920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println("throw new RuntimeException(\"Stub!\"); }");
578920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
579920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
580920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
581920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeField(PrintStream stream, FieldInfo field) {
58273934887ea87fca353449f0fd476d6c07b349521Tor Norbye    writeAnnotations(stream, field.annotations(), field.isDeprecated());
58373934887ea87fca353449f0fd476d6c07b349521Tor Norbye
584920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(field.scope() + " ");
585920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isStatic()) {
586920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static ");
587920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
588920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isFinal()) {
589920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("final ");
590920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
591920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isTransient()) {
592920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("transient ");
593920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
594920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isVolatile()) {
595920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("volatile ");
596920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
597920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
598920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(field.type().fullName());
599920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(" ");
600920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(field.name());
601920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
602920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (fieldIsInitialized(field)) {
603920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" = " + field.constantLiteralValue());
604920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
605920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
606920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println(";");
607920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
608920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
609920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static boolean fieldIsInitialized(FieldInfo field) {
610920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return (field.isFinal() && field.constantValue() != null)
611920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        || !field.type().dimension().equals("") || field.containingClass().isInterface();
612920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
613920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
614920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // Returns 'true' if the method is an @Override of a visible parent
615920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // method implementation, and thus does not affect the API.
616040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static boolean methodIsOverride(HashSet<ClassInfo> notStrippable, MethodInfo mi) {
617920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Abstract/static/final methods are always listed in the API description
618920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mi.isAbstract() || mi.isStatic() || mi.isFinal()) {
619920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return false;
620920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
621920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
622920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Find any relevant ancestor declaration and inspect it
623920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    MethodInfo om = mi.findSuperclassImplementation(notStrippable);
624920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (om != null) {
625920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // Visibility mismatch is an API change, so check for it
626920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (mi.mIsPrivate == om.mIsPrivate && mi.mIsPublic == om.mIsPublic
627920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          && mi.mIsProtected == om.mIsProtected) {
628920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // Look only for overrides of an ancestor class implementation,
629920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // not of e.g. an abstract or interface method declaration
630920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (!om.isAbstract()) {
631920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // If the parent is hidden, we can't rely on it to provide
632920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // the API
633920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (!om.isHidden()) {
634920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // If the only "override" turns out to be in our own class
635920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // (which sometimes happens in concrete subclasses of
636920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // abstract base classes), it's not really an override
637920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!mi.mContainingClass.equals(om.mContainingClass)) {
638920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              return true;
639920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
640920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
641920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
642920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
643920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
644920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return false;
645920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
646920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
647920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static boolean canCallMethod(ClassInfo from, MethodInfo m) {
648920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (m.isPublic() || m.isProtected()) {
649920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return true;
650920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
651920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (m.isPackagePrivate()) {
652920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String fromPkg = from.containingPackage().name();
653920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String pkg = m.containingClass().containingPackage().name();
654920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (fromPkg.equals(pkg)) {
655920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return true;
656920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
657920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
658920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return false;
659920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
660920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
661920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // call a constructor, any constructor on this class's superclass.
662d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  static String superCtorCall(ClassInfo cl, ArrayList<ClassInfo> thrownExceptions) {
663920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo base = cl.realSuperclass();
664920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (base == null) {
665920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return "";
666920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
667920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    HashSet<String> exceptionNames = new HashSet<String>();
668920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (thrownExceptions != null) {
669920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (ClassInfo thrown : thrownExceptions) {
670920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        exceptionNames.add(thrown.name());
671920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
672920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
673d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> ctors = base.constructors();
674920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    MethodInfo ctor = null;
675920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // bad exception indicates that the exceptions thrown by the super constructor
676920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // are incompatible with the constructor we're using for the sub class.
677920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Boolean badException = false;
678920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo m : ctors) {
679920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (canCallMethod(cl, m)) {
680920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (m.thrownExceptions() != null) {
681920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (ClassInfo thrown : m.thrownExceptions()) {
682920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!exceptionNames.contains(thrown.name())) {
683920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              badException = true;
684920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
685920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
686920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
687920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (badException) {
688920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          badException = false;
689920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          continue;
690920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
691920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // if it has no args, we're done
692d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (m.parameters().isEmpty()) {
693920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          return "";
694920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
695920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        ctor = m;
696920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
697920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
698920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (ctor != null) {
699920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String result = "";
700920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      result += "super(";
701d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      ArrayList<ParameterInfo> params = ctor.parameters();
702d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      for (ParameterInfo param : params) {
703d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        TypeInfo t = param.type();
704920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (t.isPrimitive() && t.dimension().equals("")) {
705920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          String n = t.simpleTypeName();
706920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (("byte".equals(n) || "short".equals(n) || "int".equals(n) || "long".equals(n)
707920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              || "float".equals(n) || "double".equals(n))
708920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              && t.dimension().equals("")) {
709920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "0";
710920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if ("char".equals(n)) {
711920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "'\\0'";
712920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if ("boolean".equals(n)) {
713920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "false";
714920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else {
715920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "<<unknown-" + n + ">>";
716920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
717920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        } else {
718920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // put null in each super class method. Cast null to the correct type
719920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // to avoid collisions with other constructors. If the type is generic
720920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // don't cast it
721920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          result +=
722920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              (!t.isTypeVariable() ? "(" + t.qualifiedTypeName() + t.dimension() + ")" : "")
723920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  + "null";
724920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
725d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (param != params.get(params.size()-1)) {
726920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          result += ",";
727920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
728920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
729920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      result += "); ";
730920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return result;
731920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
732920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return "";
733920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
734920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
735920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
73673934887ea87fca353449f0fd476d6c07b349521Tor Norbye    /**
73773934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * Write out the given list of annotations. If the {@code isDeprecated}
73873934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * flag is true also write out a {@code @Deprecated} annotation if it did not
73973934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * already appear in the list of annotations. (This covers APIs that mention
74073934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * {@code @deprecated} in their documentation but fail to add
74173934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * {@code @Deprecated} as an annotation.
74273934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * <p>
74373934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * {@code @Override} annotations are deliberately skipped.
74473934887ea87fca353449f0fd476d6c07b349521Tor Norbye     */
74573934887ea87fca353449f0fd476d6c07b349521Tor Norbye  static void writeAnnotations(PrintStream stream, List<AnnotationInstanceInfo> annotations,
74673934887ea87fca353449f0fd476d6c07b349521Tor Norbye          boolean isDeprecated) {
74773934887ea87fca353449f0fd476d6c07b349521Tor Norbye    assert annotations != null;
748920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (AnnotationInstanceInfo ann : annotations) {
74973934887ea87fca353449f0fd476d6c07b349521Tor Norbye      // Skip @Override annotations: the stubs do not need it and in some cases it leads
75073934887ea87fca353449f0fd476d6c07b349521Tor Norbye      // to compilation errors with the way the stubs are generated
75173934887ea87fca353449f0fd476d6c07b349521Tor Norbye      if (ann.type() != null && ann.type().qualifiedName().equals("java.lang.Override")) {
75273934887ea87fca353449f0fd476d6c07b349521Tor Norbye        continue;
75373934887ea87fca353449f0fd476d6c07b349521Tor Norbye      }
754920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!ann.type().isHidden()) {
755920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println(ann.toString());
75673934887ea87fca353449f0fd476d6c07b349521Tor Norbye        if (isDeprecated && ann.type() != null
75773934887ea87fca353449f0fd476d6c07b349521Tor Norbye            && ann.type().qualifiedName().equals("java.lang.Deprecated")) {
75873934887ea87fca353449f0fd476d6c07b349521Tor Norbye          isDeprecated = false; // Prevent duplicate annotations
75973934887ea87fca353449f0fd476d6c07b349521Tor Norbye        }
760920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
761920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
76273934887ea87fca353449f0fd476d6c07b349521Tor Norbye    if (isDeprecated) {
76373934887ea87fca353449f0fd476d6c07b349521Tor Norbye      stream.println("@Deprecated");
76473934887ea87fca353449f0fd476d6c07b349521Tor Norbye    }
765920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
766920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
767920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeAnnotationElement(PrintStream stream, MethodInfo ann) {
768920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(ann.returnType().fullName());
769920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(" ");
770920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(ann.name());
771920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print("()");
772920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    AnnotationValueInfo def = ann.defaultAnnotationElementValue();
773920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (def != null) {
774920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" default ");
775920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(def.valueString());
776920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
777920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println(";");
778920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
779920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
780920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeXML(PrintStream xmlWriter, HashMap<PackageInfo, List<ClassInfo>> allClasses,
781040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      HashSet<ClassInfo> notStrippable) {
782920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // extract the set of packages, sort them by name, and write them out in that order
783920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Set<PackageInfo> allClassKeys = allClasses.keySet();
784920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
785920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Arrays.sort(allPackages, PackageInfo.comparator);
786920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
787920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<api>");
788920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (PackageInfo pack : allPackages) {
789920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writePackageXML(xmlWriter, pack, allClasses.get(pack), notStrippable);
790920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
791920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</api>");
792920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
793920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
794040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static void writeXml(PrintStream xmlWriter, Collection<PackageInfo> pkgs) {
795040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final PackageInfo[] packages = pkgs.toArray(new PackageInfo[pkgs.size()]);
796040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(packages, PackageInfo.comparator);
797040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
798040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    HashSet<ClassInfo> notStrippable = new HashSet();
799040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
800040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      for (ClassInfo cl: pkg.allClasses().values()) {
801040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        notStrippable.add(cl);
802040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
803040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
804040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    xmlWriter.println("<api>");
805040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
806040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writePackageXML(xmlWriter, pkg, pkg.allClasses().values(), notStrippable);
807040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
808040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    xmlWriter.println("</api>");
809040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
810040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
811040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writePackageXML(PrintStream xmlWriter, PackageInfo pack,
812040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
813920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
814920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Arrays.sort(classes, ClassInfo.comparator);
815920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Work around the bogus "Array" class we invent for
816920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
817920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
818920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
819920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
820920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<package name=\"" + pack.name() + "\"\n"
821920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // + " source=\"" + pack.position() + "\"\n"
822920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
823920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : classes) {
824920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeClassXML(xmlWriter, cl, notStrippable);
825920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
826920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</package>");
827920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
828920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
829920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
830920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
831040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassXML(PrintStream xmlWriter, ClassInfo cl, HashSet<ClassInfo> notStrippable) {
832920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = cl.scope();
833920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
834920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String declString = (cl.isInterface()) ? "interface" : "class";
835920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isDeprecated()) {
836920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
837920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
838920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
839920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
840920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<" + declString + " name=\"" + cl.name() + "\"");
841920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!cl.isInterface() && !cl.qualifiedName().equals("java.lang.Object")) {
842920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println(" extends=\""
843920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + ((cl.realSuperclass() == null) ? "java.lang.Object" : cl.realSuperclass()
844920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              .qualifiedName()) + "\"");
845920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
846920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println(" abstract=\"" + cl.isAbstract() + "\"\n" + " static=\"" + cl.isStatic()
847920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + "\"\n" + " final=\"" + cl.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString
848920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + "\"\n" + " visibility=\"" + scope + "\"\n"
849920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + cl.position() + "\"\n"
850920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
851920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
852d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> interfaces = cl.realInterfaces();
853d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(interfaces, ClassInfo.comparator);
854920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo iface : interfaces) {
855920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (notStrippable.contains(iface)) {
856920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        xmlWriter.println("<implements name=\"" + iface.qualifiedName() + "\">");
857920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        xmlWriter.println("</implements>");
858920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
859920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
860920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
861d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> constructors = cl.constructors();
862d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(constructors, MethodInfo.comparator);
863920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo mi : constructors) {
864920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeConstructorXML(xmlWriter, mi);
865920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
866920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
867d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> methods = cl.allSelfMethods();
868d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(methods, MethodInfo.comparator);
869920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo mi : methods) {
870040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (!methodIsOverride(notStrippable, mi)) {
871920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethodXML(xmlWriter, mi);
872920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
873920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
874920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
875d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<FieldInfo> fields = cl.allSelfFields();
876d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(fields, FieldInfo.comparator);
877920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FieldInfo fi : fields) {
878920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeFieldXML(xmlWriter, fi);
879920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
880920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</" + declString + ">");
881920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
882920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
883920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
884920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeMethodXML(PrintStream xmlWriter, MethodInfo mi) {
885920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = mi.scope();
886920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
887920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
888920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mi.isDeprecated()) {
889920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
890920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
891920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
892920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
893920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<method name=\""
894920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + mi.name()
895920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + "\"\n"
896920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ((mi.returnType() != null) ? " return=\""
897920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + makeXMLcompliant(fullParameterTypeName(mi, mi.returnType(), false)) + "\"\n" : "")
898920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " abstract=\"" + mi.isAbstract() + "\"\n" + " native=\"" + mi.isNative() + "\"\n"
899920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " synchronized=\"" + mi.isSynchronized() + "\"\n" + " static=\"" + mi.isStatic() + "\"\n"
900920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " final=\"" + mi.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString + "\"\n"
901920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " visibility=\"" + scope + "\"\n"
902920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + mi.position() + "\"\n"
903920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
904920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
905920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // write parameters in declaration order
906d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int numParameters = mi.parameters().size();
907920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int count = 0;
908920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ParameterInfo pi : mi.parameters()) {
909920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      count++;
910920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeParameterXML(xmlWriter, mi, pi, count == numParameters);
911920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
912920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
913920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // but write exceptions in canonicalized order
914d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> exceptions = mi.thrownExceptions();
915d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(exceptions, ClassInfo.comparator);
916920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo pi : exceptions) {
917920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("<exception name=\"" + pi.name() + "\" type=\"" + pi.qualifiedName()
918920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + "\">");
919920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("</exception>");
920920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
921920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</method>");
922920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
923920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
924920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeConstructorXML(PrintStream xmlWriter, MethodInfo mi) {
925920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = mi.scope();
926920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
927920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mi.isDeprecated()) {
928920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
929920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
930920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
931920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
932920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<constructor name=\"" + mi.name() + "\"\n" + " type=\""
933920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + mi.containingClass().qualifiedName() + "\"\n" + " static=\"" + mi.isStatic() + "\"\n"
934920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " final=\"" + mi.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString + "\"\n"
935920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " visibility=\"" + scope + "\"\n"
936920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + mi.position() + "\"\n"
937920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
938920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
939d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int numParameters = mi.parameters().size();
940920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int count = 0;
941920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ParameterInfo pi : mi.parameters()) {
942920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      count++;
943920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeParameterXML(xmlWriter, mi, pi, count == numParameters);
944920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
945920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
946d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> exceptions = mi.thrownExceptions();
947d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(exceptions, ClassInfo.comparator);
948920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo pi : exceptions) {
949920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("<exception name=\"" + pi.name() + "\" type=\"" + pi.qualifiedName()
950920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + "\">");
951920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("</exception>");
952920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
953920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</constructor>");
954920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
955920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
956920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeParameterXML(PrintStream xmlWriter, MethodInfo method, ParameterInfo pi,
957920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      boolean isLast) {
958920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<parameter name=\"" + pi.name() + "\" type=\""
959920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + makeXMLcompliant(fullParameterTypeName(method, pi.type(), isLast)) + "\">");
960920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</parameter>");
961920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
962920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
963920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeFieldXML(PrintStream xmlWriter, FieldInfo fi) {
964920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = fi.scope();
965920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
966920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (fi.isDeprecated()) {
967920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
968920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
969920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
970920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
971920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // need to make sure value is valid XML
972920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String value = makeXMLcompliant(fi.constantLiteralValue());
973920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
974920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String fullTypeName = makeXMLcompliant(fi.type().qualifiedTypeName()) + fi.type().dimension();
975920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
976920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<field name=\"" + fi.name() + "\"\n" + " type=\"" + fullTypeName + "\"\n"
977920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " transient=\"" + fi.isTransient() + "\"\n" + " volatile=\"" + fi.isVolatile() + "\"\n"
978920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + (fieldIsInitialized(fi) ? " value=\"" + value + "\"\n" : "") + " static=\""
979920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + fi.isStatic() + "\"\n" + " final=\"" + fi.isFinal() + "\"\n" + " deprecated=\""
980920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + deprecatedString + "\"\n" + " visibility=\"" + scope + "\"\n"
981920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + fi.position() + "\"\n"
982920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
983920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</field>");
984920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
985920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
986920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static String makeXMLcompliant(String s) {
987920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String returnString = "";
988920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = s.replaceAll("&", "&amp;");
989920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll("<", "&lt;");
990920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll(">", "&gt;");
991920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll("\"", "&quot;");
992920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll("'", "&pos;");
993920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return returnString;
994920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
995920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
996040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static void writeApi(PrintStream apiWriter, Collection<PackageInfo> pkgs) {
997040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final PackageInfo[] packages = pkgs.toArray(new PackageInfo[pkgs.size()]);
998040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(packages, PackageInfo.comparator);
999040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1000040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    HashSet<ClassInfo> notStrippable = new HashSet();
1001040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
1002040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      for (ClassInfo cl: pkg.allClasses().values()) {
1003040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        notStrippable.add(cl);
1004040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1005040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1006040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
1007040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writePackageApi(apiWriter, pkg, pkg.allClasses().values(), notStrippable);
1008040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1009040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1010040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1011040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeApi(PrintStream apiWriter, HashMap<PackageInfo, List<ClassInfo>> allClasses,
1012040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      HashSet<ClassInfo> notStrippable) {
1013040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // extract the set of packages, sort them by name, and write them out in that order
1014040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Set<PackageInfo> allClassKeys = allClasses.keySet();
1015040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
1016040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(allPackages, PackageInfo.comparator);
1017040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1018040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pack : allPackages) {
1019040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writePackageApi(apiWriter, pack, allClasses.get(pack), notStrippable);
1020040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1021040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1022040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1023040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writePackageApi(PrintStream apiWriter, PackageInfo pack,
1024040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
1025040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // Work around the bogus "Array" class we invent for
1026040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
1027040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
1028040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return;
1029040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1030040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1031040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("package ");
1032040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(pack.qualifiedName());
1033040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" {\n\n");
1034040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1035040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
1036040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(classes, ClassInfo.comparator);
1037040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (ClassInfo cl : classes) {
1038040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeClassApi(apiWriter, cl, notStrippable);
1039040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1040040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1041040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("}\n\n");
1042040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1043040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1044040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassApi(PrintStream apiWriter, ClassInfo cl, HashSet<ClassInfo> notStrippable) {
1045040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean first;
1046040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1047040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("  ");
1048040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(cl.scope());
1049040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isStatic()) {
1050040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" static");
1051040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1052040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isFinal()) {
1053040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" final");
1054040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1055040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isAbstract()) {
1056040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" abstract");
1057040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1058040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isDeprecated()) {
1059040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1060040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1061040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1062040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(cl.isInterface() ? "interface" : "class");
1063040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1064040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(cl.name());
1065040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1066040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!cl.isInterface()
1067040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        && !"java.lang.Object".equals(cl.qualifiedName())
1068040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        && cl.realSuperclass() != null
1069040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        && !"java.lang.Object".equals(cl.realSuperclass().qualifiedName())) {
1070040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" extends ");
1071040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(cl.realSuperclass().qualifiedName());
1072040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1073040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1074d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> interfaces = cl.realInterfaces();
1075d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(interfaces, ClassInfo.comparator);
1076040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    first = true;
1077040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (ClassInfo iface : interfaces) {
1078040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (notStrippable.contains(iface)) {
1079040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (first) {
1080040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          apiWriter.print(" implements");
1081040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          first = false;
1082040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
1083040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(" ");
1084040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(iface.qualifiedName());
1085040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1086040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1087040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1088040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" {\n");
1089040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1090d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> constructors = cl.constructors();
1091d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(constructors, MethodInfo.comparator);
1092040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (MethodInfo mi : constructors) {
1093040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeConstructorApi(apiWriter, mi);
1094040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1095040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1096d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> methods = cl.allSelfMethods();
1097d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(methods, MethodInfo.comparator);
1098040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (MethodInfo mi : methods) {
1099040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (!methodIsOverride(notStrippable, mi)) {
1100040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        writeMethodApi(apiWriter, mi);
1101040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1102040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1103040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1104d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<FieldInfo> enums = cl.enumConstants();
1105d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(enums, FieldInfo.comparator);
1106132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    for (FieldInfo fi : enums) {
1107132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      writeFieldApi(apiWriter, fi, "enum_constant");
1108132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    }
1109132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato
1110d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<FieldInfo> fields = cl.allSelfFields();
1111d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(fields, FieldInfo.comparator);
1112040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (FieldInfo fi : fields) {
1113132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      writeFieldApi(apiWriter, fi, "field");
1114040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1115040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1116040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("  }\n\n");
1117040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1118040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1119040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeConstructorApi(PrintStream apiWriter, MethodInfo mi) {
1120040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("    ctor ");
1121040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.scope());
1122040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isDeprecated()) {
1123040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1124040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1125040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1126040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.name());
1127040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1128040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeParametersApi(apiWriter, mi, mi.parameters());
1129040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeThrowsApi(apiWriter, mi.thrownExceptions());
1130040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(";\n");
1131040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1132040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1133040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeMethodApi(PrintStream apiWriter, MethodInfo mi) {
1134040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("    method ");
1135040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.scope());
1136040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isStatic()) {
1137040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" static");
1138040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1139040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isFinal()) {
1140040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" final");
1141040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1142040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isAbstract()) {
1143040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" abstract");
1144040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1145040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isDeprecated()) {
1146040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1147040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1148040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isSynchronized()) {
1149040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" synchronized");
1150040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1151040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1152040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.returnType() == null) {
1153040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print("void");
1154040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
1155040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(fullParameterTypeName(mi, mi.returnType(), false));
1156040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1157040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1158040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.name());
1159040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1160040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeParametersApi(apiWriter, mi, mi.parameters());
1161040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeThrowsApi(apiWriter, mi.thrownExceptions());
1162040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1163040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(";\n");
1164040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1165040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1166d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  static void writeParametersApi(PrintStream apiWriter, MethodInfo method, ArrayList<ParameterInfo> params) {
1167040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("(");
1168040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1169d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (ParameterInfo pi : params) {
1170d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      if (pi != params.get(0)) {
1171040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(", ");
1172040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1173d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      apiWriter.print(fullParameterTypeName(method, pi.type(), pi == params.get(params.size()-1)));
1174040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      // turn on to write the names too
1175040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (false) {
1176040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(" ");
1177040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(pi.name());
1178040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1179040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1180040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1181040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(")");
1182040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1183040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1184d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  static void writeThrowsApi(PrintStream apiWriter, ArrayList<ClassInfo> exceptions) {
1185040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // write in a canonical order
1186d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    exceptions = (ArrayList<ClassInfo>) exceptions.clone();
1187d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(exceptions, ClassInfo.comparator);
1188d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    //final int N = exceptions.length;
1189040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean first = true;
1190d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (ClassInfo ex : exceptions) {
1191040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      // Turn this off, b/c we need to regenrate the old xml files.
1192040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (true || !"java.lang.RuntimeException".equals(ex.qualifiedName())
1193040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          && !ex.isDerivedFrom("java.lang.RuntimeException")) {
1194040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (first) {
1195040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          apiWriter.print(" throws ");
1196040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          first = false;
1197040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
1198040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          apiWriter.print(", ");
1199040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
1200040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(ex.qualifiedName());
1201040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1202040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1203040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1204040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1205132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato  static void writeFieldApi(PrintStream apiWriter, FieldInfo fi, String label) {
1206132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    apiWriter.print("    ");
1207132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    apiWriter.print(label);
1208132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    apiWriter.print(" ");
1209040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(fi.scope());
1210040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isStatic()) {
1211040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" static");
1212040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1213040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isFinal()) {
1214040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" final");
1215040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1216040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isDeprecated()) {
1217040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1218040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1219040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isTransient()) {
1220040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" transient");
1221040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1222040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isVolatile()) {
1223040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" volatile");
1224040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1225040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1226040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1227040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(fi.type().qualifiedTypeName() + fi.type().dimension());
1228040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1229040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1230040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(fi.name());
1231040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1232040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Object val = null;
1233040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isConstant() && fieldIsInitialized(fi)) {
1234040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" = ");
1235040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(fi.constantLiteralValue());
1236040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      val = fi.constantValue();
1237040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1238040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1239040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(";");
1240040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1241040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (val != null) {
1242040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (val instanceof Integer && "char".equals(fi.type().qualifiedTypeName())) {
1243040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.format(" // 0x%04x '%s'", val,
1244040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            FieldInfo.javaEscapeString("" + ((char)((Integer)val).intValue())));
1245040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (val instanceof Byte || val instanceof Short || val instanceof Integer) {
1246040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.format(" // 0x%x", val);
1247040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (val instanceof Long) {
1248040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.format(" // 0x%xL", val);
1249040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1250040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1251040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1252040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("\n");
1253040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1254040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1255970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeKeepList(PrintStream keepListWriter,
1256970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      HashMap<PackageInfo, List<ClassInfo>> allClasses, HashSet<ClassInfo> notStrippable) {
1257970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // extract the set of packages, sort them by name, and write them out in that order
1258970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Set<PackageInfo> allClassKeys = allClasses.keySet();
1259970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
1260970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Arrays.sort(allPackages, PackageInfo.comparator);
1261970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1262970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (PackageInfo pack : allPackages) {
1263970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writePackageKeepList(keepListWriter, pack, allClasses.get(pack), notStrippable);
1264970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1265970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1266970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1267970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writePackageKeepList(PrintStream keepListWriter, PackageInfo pack,
1268970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
1269970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // Work around the bogus "Array" class we invent for
1270970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
1271970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
1272970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      return;
1273970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1274970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1275970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
1276970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Arrays.sort(classes, ClassInfo.comparator);
1277970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (ClassInfo cl : classes) {
1278970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeClassKeepList(keepListWriter, cl, notStrippable);
1279970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1280970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1281970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1282970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeClassKeepList(PrintStream keepListWriter, ClassInfo cl,
1283970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      HashSet<ClassInfo> notStrippable) {
1284970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("-keep class ");
1285970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(to$Class(cl.qualifiedName()));
1286970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1287970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" {\n");
1288970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1289970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<MethodInfo> constructors = cl.constructors();
1290970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(constructors, MethodInfo.comparator);
1291970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (MethodInfo mi : constructors) {
1292970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeConstructorKeepList(keepListWriter, mi);
1293970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1294970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1295970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("\n");
1296970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1297970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<MethodInfo> methods = cl.allSelfMethods();
1298970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(methods, MethodInfo.comparator);
1299970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (MethodInfo mi : methods) {
1300970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      if (!methodIsOverride(notStrippable, mi)) {
1301970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        writeMethodKeepList(keepListWriter, mi);
1302970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
1303970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1304970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1305970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("\n");
1306970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1307970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<FieldInfo> enums = cl.enumConstants();
1308970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(enums, FieldInfo.comparator);
1309970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (FieldInfo fi : enums) {
1310970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeFieldKeepList(keepListWriter, fi);
1311970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1312970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1313970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("\n");
1314970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1315970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<FieldInfo> fields = cl.allSelfFields();
1316970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(fields, FieldInfo.comparator);
1317970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (FieldInfo fi : fields) {
1318970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeFieldKeepList(keepListWriter, fi);
1319970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1320970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1321970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("}\n\n");
1322970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1323970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1324970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeConstructorKeepList(PrintStream keepListWriter, MethodInfo mi) {
1325970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("    ");
1326970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    String name = mi.name();
1327970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    name = name.replace(".", "$");
1328970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(name);
1329970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1330970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    writeParametersKeepList(keepListWriter, mi, mi.parameters());
1331970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(";\n");
1332970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1333970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1334970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeMethodKeepList(PrintStream keepListWriter, MethodInfo mi) {
1335970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("    ");
1336970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(mi.scope());
1337970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.isStatic()) {
1338970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" static");
1339970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1340970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.isAbstract()) {
1341970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" abstract");
1342970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1343970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.isSynchronized()) {
1344970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" synchronized");
1345970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1346970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1347970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.returnType() == null) {
1348970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print("void");
1349970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    } else {
1350970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(getCleanTypeName(mi.returnType()));
1351970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1352970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1353970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(mi.name());
1354970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1355970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    writeParametersKeepList(keepListWriter, mi, mi.parameters());
1356970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1357970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(";\n");
1358970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1359970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1360970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeParametersKeepList(PrintStream keepListWriter, MethodInfo method,
1361970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      ArrayList<ParameterInfo> params) {
1362970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("(");
1363970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1364970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (ParameterInfo pi : params) {
1365970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      if (pi != params.get(0)) {
1366970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        keepListWriter.print(", ");
1367970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
1368550a9de05d89f19d1f824fbbb04ba7cd8a1ff86eJeff Hamilton      keepListWriter.print(getCleanTypeName(pi.type()));
1369970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1370970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1371970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(")");
1372970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1373970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1374970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeFieldKeepList(PrintStream keepListWriter, FieldInfo fi) {
1375970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("    ");
1376970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(fi.scope());
1377970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (fi.isStatic()) {
1378970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" static");
1379970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1380970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (fi.isTransient()) {
1381970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" transient");
1382970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1383970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (fi.isVolatile()) {
1384970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" volatile");
1385970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1386970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1387970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1388970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(getCleanTypeName(fi.type()) + fi.type().dimension());
1389970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1390970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1391970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(fi.name());
1392970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1393970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(";\n");
1394970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1395970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1396920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static String fullParameterTypeName(MethodInfo method, TypeInfo type, boolean isLast) {
1397920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String fullTypeName = type.fullName(method.typeVariables());
1398920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (isLast && method.isVarArgs()) {
1399920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // TODO: note that this does not attempt to handle hypothetical
1400920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // vararg methods whose last parameter is a list of arrays, e.g.
1401920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "Object[]...".
1402920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      fullTypeName = type.fullNameNoDimension(method.typeVariables()) + "...";
1403920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
1404920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return fullTypeName;
1405920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
1406970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1407970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static String to$Class(String name) {
1408970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    int pos = 0;
1409970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    while ((pos = name.indexOf('.', pos)) > 0) {
1410970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      String n = name.substring(0, pos);
1411970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      if (Converter.obtainClass(n) != null) {
1412970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        return n + (name.substring(pos).replace('.', '$'));
1413970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
1414970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      pos = pos + 1;
1415970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1416970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    return name;
1417970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1418970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1419970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static String getCleanTypeName(TypeInfo t) {
1420d6f2c2b6edce46c86581be1f508981742e20fb51Jeff Hamilton      return t.isPrimitive() ? t.simpleTypeName() + t.dimension() :
14211e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton              to$Class(t.asClassInfo().qualifiedName() + t.dimension());
1422970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1423920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson}
1424