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,
355118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      String removedApiFile, 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;
415118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    PrintStream removedApiWriter = null;
425118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
43040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (apiFile != null) {
44920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      try {
45040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        File xml = new File(apiFile);
46920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        xml.getParentFile().mkdirs();
47ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstrom        apiWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(xml)));
48920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } catch (FileNotFoundException e) {
49040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        Errors.error(Errors.IO_ERROR, new SourcePositionInfo(apiFile, 0, 0),
50920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            "Cannot open file for write.");
51920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
52920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
53970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (keepListFile != null) {
54970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      try {
55970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        File keepList = new File(keepListFile);
56970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        keepList.getParentFile().mkdirs();
57970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        keepListWriter = new PrintStream(new BufferedOutputStream(new FileOutputStream(keepList)));
58970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      } catch (FileNotFoundException e) {
59970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        Errors.error(Errors.IO_ERROR, new SourcePositionInfo(keepListFile, 0, 0),
60970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton            "Cannot open file for write.");
61970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
62970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
635118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (removedApiFile != null) {
645118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      try {
655118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        File removedApi = new File(removedApiFile);
665118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        removedApi.getParentFile().mkdirs();
675118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        removedApiWriter = new PrintStream(
685118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            new BufferedOutputStream(new FileOutputStream(removedApi)));
695118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      } catch (FileNotFoundException e) {
705118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        Errors.error(Errors.IO_ERROR, new SourcePositionInfo(removedApiFile, 0, 0),
715118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            "Cannot open file for write");
725118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      }
735118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
74920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // If a class is public or protected, not hidden, and marked as included,
75920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // then we can't strip it
76920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : all) {
77920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.checkLevel() && cl.isIncluded()) {
78920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cantStripThis(cl, notStrippable, "0:0");
79920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
80920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
81920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
82920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // complain about anything that looks includeable but is not supposed to
83920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // be written, e.g. hidden things
84920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : notStrippable) {
855118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (!cl.isHiddenOrRemoved()) {
86d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (MethodInfo m : cl.selfMethods()) {
875118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          if (m.isHiddenOrRemoved()) {
885118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Reference to unavailable method "
89920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + m.name());
90920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if (m.isDeprecated()) {
91920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // don't bother reporting deprecated methods
92920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // unless they are public
93920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.DEPRECATED, m.position(), "Method " + cl.qualifiedName() + "."
94920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + m.name() + " is deprecated");
95920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
96920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
97920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          ClassInfo returnClass = m.returnType().asClassInfo();
985118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          if (returnClass != null && returnClass.isHiddenOrRemoved()) {
99920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Method " + cl.qualifiedName()
100920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + "." + m.name() + " returns unavailable type " + returnClass.name());
101920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
102920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
103d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          for (ParameterInfo p :  m.parameters()) {
104920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            TypeInfo t = p.type();
105920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!t.isPrimitive()) {
1065118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu              if (t.asClassInfo().isHiddenOrRemoved()) {
1075118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu                Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Parameter of unavailable type "
108920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    + t.fullName() + " in " + cl.qualifiedName() + "." + m.name() + "()");
109920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
110920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
111920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
112920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
113920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
114920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // annotations are handled like methods
115d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        for (MethodInfo m : cl.annotationElements()) {
1165118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          if (m.isHiddenOrRemoved()) {
1175118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Reference to unavailable annotation "
118920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + m.name());
119920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
120920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
121920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          ClassInfo returnClass = m.returnType().asClassInfo();
1225118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          if (returnClass != null && returnClass.isHiddenOrRemoved()) {
123920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            Errors.error(Errors.UNAVAILABLE_SYMBOL, m.position(), "Annotation '" + m.name()
124920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                + "' returns unavailable type " + returnClass.name());
125920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
126920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
127d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein          for (ParameterInfo p :  m.parameters()) {
128920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            TypeInfo t = p.type();
129920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!t.isPrimitive()) {
1305118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu              if (t.asClassInfo().isHiddenOrRemoved()) {
131920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                Errors.error(Errors.UNAVAILABLE_SYMBOL, p.position(),
132920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    "Reference to unavailable annotation class " + t.fullName());
133920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
134920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
135920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
136920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
137920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else if (cl.isDeprecated()) {
138920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // not hidden, but deprecated
139920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        Errors.error(Errors.DEPRECATED, cl.position(), "Class " + cl.qualifiedName()
140920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + " is deprecated");
141920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
142920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
143920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
1445118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    // packages contains all the notStrippable classes mapped by their containing packages
145920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    HashMap<PackageInfo, List<ClassInfo>> packages = new HashMap<PackageInfo, List<ClassInfo>>();
146920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : notStrippable) {
147920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!cl.isDocOnly()) {
148920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (stubPackages == null || stubPackages.contains(cl.containingPackage().name())) {
149920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // write out the stubs
150920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (stubsDir != null) {
151040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            writeClassFile(stubsDir, notStrippable, cl);
152920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
153970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton          // build class list for api file or keep list file
154970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton          if (apiWriter != null || keepListWriter != null) {
155920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (packages.containsKey(cl.containingPackage())) {
156920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              packages.get(cl.containingPackage()).add(cl);
157920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            } else {
158920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              ArrayList<ClassInfo> classes = new ArrayList<ClassInfo>();
159920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              classes.add(cl);
160920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              packages.put(cl.containingPackage(), classes);
161920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
162920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
163920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
164920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
165920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
166040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // write out the Api
167040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (apiWriter != null) {
168040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeApi(apiWriter, packages, notStrippable);
169040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.close();
170920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
171970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
172970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // write out the keep list
173970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (keepListWriter != null) {
174970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeKeepList(keepListWriter, packages, notStrippable);
175970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.close();
176970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1775118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
1785118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    HashMap<PackageInfo, List<ClassInfo>> allPackageClassMap =
1795118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        new HashMap<PackageInfo, List<ClassInfo>>();
1805118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (ClassInfo cl : Converter.allClasses()) {
1815118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (allPackageClassMap.containsKey(cl.containingPackage())) {
1825118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        allPackageClassMap.get(cl.containingPackage()).add(cl);
1835118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      } else {
1845118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        ArrayList<ClassInfo> classes = new ArrayList<ClassInfo>();
1855118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        classes.add(cl);
1865118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        allPackageClassMap.put(cl.containingPackage(), classes);
1875118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      }
1885118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
1895118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    // write out the removed Api
1905118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (removedApiWriter != null) {
1915118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      writeRemovedApi(removedApiWriter, allPackageClassMap, notStrippable);
1925118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      removedApiWriter.close();
1935118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
194920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
195920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
196920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  public static void cantStripThis(ClassInfo cl, HashSet<ClassInfo> notStrippable, String why) {
197920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
198920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!notStrippable.add(cl)) {
199920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // slight optimization: if it already contains cl, it already contains
200920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // all of cl's parents
201920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
202920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
203920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    cl.setReasonIncluded(why);
204920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
205920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip annotations
206920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    /*
207920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     * if (cl.annotations() != null){ for (AnnotationInstanceInfo ai : cl.annotations()){ if
208920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     * (ai.type() != null){ cantStripThis(ai.type(), notStrippable, "1:" + cl.qualifiedName()); } }
209920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     * }
210920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson     */
211920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip any public fields or their generics
212ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang    if (cl.selfFields() != null) {
213ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang      for (FieldInfo fInfo : cl.selfFields()) {
214920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (fInfo.type() != null) {
215920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (fInfo.type().asClassInfo() != null) {
216920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cantStripThis(fInfo.type().asClassInfo(), notStrippable, "2:" + cl.qualifiedName());
217920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
218920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (fInfo.type().typeArguments() != null) {
219920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            for (TypeInfo tTypeInfo : fInfo.type().typeArguments()) {
220920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (tTypeInfo.asClassInfo() != null) {
221920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                cantStripThis(tTypeInfo.asClassInfo(), notStrippable, "3:" + cl.qualifiedName());
222920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
223920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
224920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
225920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
226920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
227920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
228920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip any of the type's generics
229920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.asTypeInfo() != null) {
230920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.asTypeInfo().typeArguments() != null) {
231920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        for (TypeInfo tInfo : cl.asTypeInfo().typeArguments()) {
232920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (tInfo.asClassInfo() != null) {
233920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cantStripThis(tInfo.asClassInfo(), notStrippable, "4:" + cl.qualifiedName());
234920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
235920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
236920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
237920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
238920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cant strip any of the annotation elements
239920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // cantStripThis(cl.annotationElements(), notStrippable);
240920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // take care of methods
241920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    cantStripThis(cl.allSelfMethods(), notStrippable);
242920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    cantStripThis(cl.allConstructors(), notStrippable);
243920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // blow the outer class open if this is an inner class
244920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.containingClass() != null) {
245920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      cantStripThis(cl.containingClass(), notStrippable, "5:" + cl.qualifiedName());
246920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
247920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // blow open super class and interfaces
248920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo supr = cl.realSuperclass();
249920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (supr != null) {
2505118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (supr.isHiddenOrRemoved()) {
251920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // cl is a public class declared as extending a hidden superclass.
252920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // this is not a desired practice but it's happened, so we deal
2532da2d64196a401f664644619160f8a33eda77d9aMathieu Chartier        // with it by finding the first super class which passes checklevel for purposes of
254920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // generating the doc & stub information, and proceeding normally.
255920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cl.init(cl.asTypeInfo(), cl.realInterfaces(), cl.realInterfaceTypes(), cl.innerClasses(),
256920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            cl.allConstructors(), cl.allSelfMethods(), cl.annotationElements(), cl.allSelfFields(),
2572da2d64196a401f664644619160f8a33eda77d9aMathieu Chartier            cl.enumConstants(), cl.containingPackage(), cl.containingClass(),
258bf322c1b64a9a7f2aade8ba499fcec4bd141a688Elliott Hughes            supr.superclass(), supr.superclassType(), cl.annotations());
259920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        Errors.error(Errors.HIDDEN_SUPERCLASS, cl.position(), "Public class " + cl.qualifiedName()
260920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + " stripped of unavailable superclass " + supr.qualifiedName());
261920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
262920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cantStripThis(supr, notStrippable, "6:" + cl.realSuperclass().name() + cl.qualifiedName());
263920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
264920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
265920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
266920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
267d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  private static void cantStripThis(ArrayList<MethodInfo> mInfos, HashSet<ClassInfo> notStrippable) {
268920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // for each method, blow open the parameters, throws and return types. also blow open their
269920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // generics
270920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mInfos != null) {
271920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (MethodInfo mInfo : mInfos) {
272920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (mInfo.getTypeParameters() != null) {
273920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (TypeInfo tInfo : mInfo.getTypeParameters()) {
274920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (tInfo.asClassInfo() != null) {
275920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              cantStripThis(tInfo.asClassInfo(), notStrippable, "8:"
276920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
277920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
278920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
279920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
280920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (mInfo.parameters() != null) {
281920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (ParameterInfo pInfo : mInfo.parameters()) {
282920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (pInfo.type() != null && pInfo.type().asClassInfo() != null) {
283920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              cantStripThis(pInfo.type().asClassInfo(), notStrippable, "9:"
284920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
285920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (pInfo.type().typeArguments() != null) {
286920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                for (TypeInfo tInfoType : pInfo.type().typeArguments()) {
287920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  if (tInfoType.asClassInfo() != null) {
288920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    ClassInfo tcl = tInfoType.asClassInfo();
2895118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu                    if (tcl.isHiddenOrRemoved()) {
290920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                      Errors
291920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                          .error(Errors.UNAVAILABLE_SYMBOL, mInfo.position(),
292920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                              "Parameter of hidden type " + tInfoType.fullName() + " in "
293920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                                  + mInfo.containingClass().qualifiedName() + '.' + mInfo.name()
294920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                                  + "()");
295920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    } else {
296920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                      cantStripThis(tcl, notStrippable, "10:"
297920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                          + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
298920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    }
299920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  }
300920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                }
301920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
302920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
303920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
304920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
305920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        for (ClassInfo thrown : mInfo.thrownExceptions()) {
306920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          cantStripThis(thrown, notStrippable, "11:" + mInfo.realContainingClass().qualifiedName()
307920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              + ":" + mInfo.name());
308920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
309920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (mInfo.returnType() != null && mInfo.returnType().asClassInfo() != null) {
310920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          cantStripThis(mInfo.returnType().asClassInfo(), notStrippable, "12:"
311920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
312920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (mInfo.returnType().typeArguments() != null) {
313920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            for (TypeInfo tyInfo : mInfo.returnType().typeArguments()) {
314920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              if (tyInfo.asClassInfo() != null) {
315920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                cantStripThis(tyInfo.asClassInfo(), notStrippable, "13:"
316920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                    + mInfo.realContainingClass().qualifiedName() + ":" + mInfo.name());
317920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              }
318920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
319920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
320920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
321920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
322920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
323920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
324920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
325920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static String javaFileName(ClassInfo cl) {
326920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String dir = "";
327920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PackageInfo pkg = cl.containingPackage();
328920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pkg != null) {
329920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      dir = pkg.name();
330920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      dir = dir.replace('.', '/') + '/';
331920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
332920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return dir + cl.name() + ".java";
333920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
334920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
335040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassFile(String stubsDir, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
336920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // inner classes are written by their containing class
337920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.containingClass() != null) {
338920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
339920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
340920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
341920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Work around the bogus "Array" class we invent for
342920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
343920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.containingPackage() != null
344920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        && cl.containingPackage().name().equals(PackageInfo.DEFAULT_PACKAGE)) {
345920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
346920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
347920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
348920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String filename = stubsDir + '/' + javaFileName(cl);
349920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    File file = new File(filename);
350920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClearPage.ensureDirectory(file);
351920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
352920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PrintStream stream = null;
353920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    try {
354ed8f79791885c3ac15401d88a147aee551e1039eBrian Carlstrom      stream = new PrintStream(new BufferedOutputStream(new FileOutputStream(file)));
355040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeClassFile(stream, notStrippable, cl);
356920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } catch (FileNotFoundException e) {
357920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      System.err.println("error writing file: " + filename);
358920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } finally {
359920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (stream != null) {
360920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.close();
361920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
362920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
363920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
364920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
365040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassFile(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
366920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PackageInfo pkg = cl.containingPackage();
367920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pkg != null) {
368920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println("package " + pkg.name() + ";");
369920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
370040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeClass(stream, notStrippable, cl);
371920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
372920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
373040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClass(PrintStream stream, HashSet<ClassInfo> notStrippable, ClassInfo cl) {
37473934887ea87fca353449f0fd476d6c07b349521Tor Norbye    writeAnnotations(stream, cl.annotations(), cl.isDeprecated());
375920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
376920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(cl.scope() + " ");
377920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isAbstract() && !cl.isAnnotation() && !cl.isInterface()) {
378920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("abstract ");
379920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
380920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isStatic()) {
381920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static ");
382920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
383920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isFinal() && !cl.isEnum()) {
384920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("final ");
385920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
386920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (false) {
387920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("strictfp ");
388920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
389920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
390920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    HashSet<String> classDeclTypeVars = new HashSet();
391920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String leafName = cl.asTypeInfo().fullName(classDeclTypeVars);
392920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int bracket = leafName.indexOf('<');
393920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (bracket < 0) bracket = leafName.length() - 1;
394920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int period = leafName.lastIndexOf('.', bracket);
395920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (period < 0) period = -1;
396920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    leafName = leafName.substring(period + 1);
397920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
398920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String kind = cl.kind();
399920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println(kind + " " + leafName);
400920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
401920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    TypeInfo base = cl.superclassType();
402920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
403920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!"enum".equals(kind)) {
404920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (base != null && !"java.lang.Object".equals(base.qualifiedTypeName())) {
405920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println("  extends " + base.fullName(classDeclTypeVars));
406920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
407920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
408920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
409920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    List<TypeInfo> usedInterfaces = new ArrayList<TypeInfo>();
410d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (TypeInfo iface : cl.realInterfaceTypes()) {
411920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (notStrippable.contains(iface.asClassInfo()) && !iface.asClassInfo().isDocOnly()) {
412920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        usedInterfaces.add(iface);
413920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
414920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
415920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (usedInterfaces.size() > 0 && !cl.isAnnotation()) {
416920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // can java annotations extend other ones?
417920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.isInterface() || cl.isAnnotation()) {
418920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print("  extends ");
419920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
420920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print("  implements ");
421920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
422920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String comma = "";
423920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (TypeInfo iface : usedInterfaces) {
424920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print(comma + iface.fullName(classDeclTypeVars));
425920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        comma = ", ";
426920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
427920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println();
428920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
429920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
430920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println("{");
431920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
432d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<FieldInfo> enumConstants = cl.enumConstants();
433d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int N = enumConstants.size();
434d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int i = 0;
435d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (FieldInfo field : enumConstants) {
436920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!field.constantLiteralValue().equals("null")) {
437920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println(field.name() + "(" + field.constantLiteralValue()
438920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + (i == N - 1 ? ");" : "),"));
439920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      } else {
440920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println(field.name() + "(" + (i == N - 1 ? ");" : "),"));
441920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
442d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      i++;
443920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
444920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
445920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo inner : cl.getRealInnerClasses()) {
446920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (notStrippable.contains(inner) && !inner.isDocOnly()) {
447040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        writeClass(stream, notStrippable, inner);
448920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
449920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
450920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
451920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
452920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo method : cl.constructors()) {
453920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!method.isDocOnly()) {
454920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethod(stream, method, true);
455920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
456920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
457920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
458920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    boolean fieldNeedsInitialization = false;
459920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    boolean staticFieldNeedsInitialization = false;
460ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang    for (FieldInfo field : cl.selfFields()) {
461920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!field.isDocOnly()) {
462920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (!field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
463920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          fieldNeedsInitialization = true;
464920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
465920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (field.isStatic() && field.isFinal() && !fieldIsInitialized(field)) {
466920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          staticFieldNeedsInitialization = true;
467920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
468920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
469920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
470920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
471920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // The compiler includes a default public constructor that calls the super classes
472920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // default constructor in the case where there are no written constructors.
473920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // So, if we hide all the constructors, java may put in a constructor
474920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // that calls a nonexistent super class constructor. So, if there are no constructors,
475920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // and the super class doesn't have a default constructor, write in a private constructor
476920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // that works. TODO -- we generate this as protected, but we really should generate
477920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // it as private unless it also exists in the real code.
4785118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if ((cl.constructors().isEmpty() && (!cl.getNonWrittenConstructors().isEmpty() ||
4795118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        fieldNeedsInitialization)) && !cl.isAnnotation() && !cl.isInterface() && !cl.isEnum()) {
480920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // Errors.error(Errors.HIDDEN_CONSTRUCTOR,
481920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // cl.position(), "No constructors " +
482920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "found and superclass has no parameterless constructor.  A constructor " +
483920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "that calls an appropriate superclass constructor " +
484920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "was automatically written to stubs.\n");
485920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println(cl.leafName() + "() { " + superCtorCall(cl, null) + "throw new"
486920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + " RuntimeException(\"Stub!\"); }");
487920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
488920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
489920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo method : cl.allSelfMethods()) {
490920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (cl.isEnum()) {
4915118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        if (("values".equals(method.name()) && "()".equals(method.signature())) ||
4925118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            ("valueOf".equals(method.name()) &&
4935118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            "(java.lang.String)".equals(method.signature()))) {
494920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // skip these two methods on enums, because they're synthetic,
495920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // although for some reason javadoc doesn't mark them as synthetic,
496920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // maybe because they still want them documented
497920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          continue;
498920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
499920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
500920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!method.isDocOnly()) {
501920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethod(stream, method, false);
502920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
503920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
5045118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    // Write all methods that are hidden or removed, but override abstract methods or interface methods.
505920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // These can't be hidden.
5065118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    List<MethodInfo> hiddenAndRemovedMethods = cl.getHiddenMethods();
5075118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    hiddenAndRemovedMethods.addAll(cl.getRemovedMethods());
5085118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (MethodInfo method : hiddenAndRemovedMethods) {
509920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      MethodInfo overriddenMethod =
510920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          method.findRealOverriddenMethod(method.name(), method.signature(), notStrippable);
511920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      ClassInfo classContainingMethod =
512920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          method.findRealOverriddenClass(method.name(), method.signature());
5135118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (overriddenMethod != null && !overriddenMethod.isHiddenOrRemoved() &&
5145118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          !overriddenMethod.isDocOnly() &&
5155118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          (overriddenMethod.isAbstract() || overriddenMethod.containingClass().isInterface())) {
516920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        method.setReason("1:" + classContainingMethod.qualifiedName());
517920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        cl.addMethod(method);
518920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethod(stream, method, false);
519920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
520920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
521920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
522920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo element : cl.annotationElements()) {
523920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!element.isDocOnly()) {
524920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeAnnotationElement(stream, element);
525920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
526920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
527920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
528ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang    for (FieldInfo field : cl.selfFields()) {
529920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (!field.isDocOnly()) {
530920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeField(stream, field);
531920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
532920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
533920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
534920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (staticFieldNeedsInitialization) {
535920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static { ");
536ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang      for (FieldInfo field : cl.selfFields()) {
537920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (!field.isDocOnly() && field.isStatic() && field.isFinal() && !fieldIsInitialized(field)
538920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            && field.constantValue() == null) {
539920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          stream.print(field.name() + " = " + field.type().defaultValue() + "; ");
540920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
541920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
542920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println("}");
543920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
544920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
545920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println("}");
546920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
547920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
548920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
549920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeMethod(PrintStream stream, MethodInfo method, boolean isConstructor) {
550920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String comma;
551920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
55273934887ea87fca353449f0fd476d6c07b349521Tor Norbye    writeAnnotations(stream, method.annotations(), method.isDeprecated());
55373934887ea87fca353449f0fd476d6c07b349521Tor Norbye
554920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(method.scope() + " ");
555920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isStatic()) {
556920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static ");
557920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
558920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isFinal()) {
559920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("final ");
560920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
561920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isAbstract()) {
562920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("abstract ");
563920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
564920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isSynchronized()) {
565920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("synchronized ");
566920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
567920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isNative()) {
568920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("native ");
569920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
570920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (false /* method.isStictFP() */) {
571920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("strictfp ");
572920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
573920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
574920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(method.typeArgumentsName(new HashSet()) + " ");
575920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
576920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!isConstructor) {
577920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(method.returnType().fullName(method.typeVariables()) + " ");
578920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
579920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String n = method.name();
580920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int pos = n.lastIndexOf('.');
581920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pos >= 0) {
582920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      n = n.substring(pos + 1);
583920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
584920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(n + "(");
585920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    comma = "";
586920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int count = 1;
587d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int size = method.parameters().size();
588920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ParameterInfo param : method.parameters()) {
589920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(comma + fullParameterTypeName(method, param.type(), count == size) + " "
590920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + param.name());
591920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      comma = ", ";
592920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      count++;
593920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
594920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(")");
595920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
596920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    comma = "";
597d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    if (method.thrownExceptions().size() > 0) {
598920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" throws ");
599920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (ClassInfo thrown : method.thrownExceptions()) {
600920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print(comma + thrown.qualifiedName());
601920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        comma = ", ";
602920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
603920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
604920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (method.isAbstract() || method.isNative() || method.containingClass().isInterface()) {
605920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println(";");
606920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
607920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" { ");
608920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (isConstructor) {
609920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.print(superCtorCall(method.containingClass(), method.thrownExceptions()));
610920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
611920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.println("throw new RuntimeException(\"Stub!\"); }");
612920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
613920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
614920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
615920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeField(PrintStream stream, FieldInfo field) {
61673934887ea87fca353449f0fd476d6c07b349521Tor Norbye    writeAnnotations(stream, field.annotations(), field.isDeprecated());
61773934887ea87fca353449f0fd476d6c07b349521Tor Norbye
618920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(field.scope() + " ");
619920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isStatic()) {
620920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("static ");
621920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
622920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isFinal()) {
623920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("final ");
624920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
625920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isTransient()) {
626920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("transient ");
627920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
628920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (field.isVolatile()) {
629920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print("volatile ");
630920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
631920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
632920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(field.type().fullName());
633920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(" ");
634920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(field.name());
635920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
636920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (fieldIsInitialized(field)) {
637920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" = " + field.constantLiteralValue());
638920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
639920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
640920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println(";");
641920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
642920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
643920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static boolean fieldIsInitialized(FieldInfo field) {
644920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return (field.isFinal() && field.constantValue() != null)
645920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        || !field.type().dimension().equals("") || field.containingClass().isInterface();
646920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
647920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
648920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // Returns 'true' if the method is an @Override of a visible parent
649920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // method implementation, and thus does not affect the API.
650040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static boolean methodIsOverride(HashSet<ClassInfo> notStrippable, MethodInfo mi) {
651920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Abstract/static/final methods are always listed in the API description
652920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mi.isAbstract() || mi.isStatic() || mi.isFinal()) {
653920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return false;
654920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
655920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
656920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Find any relevant ancestor declaration and inspect it
657920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    MethodInfo om = mi.findSuperclassImplementation(notStrippable);
658920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (om != null) {
659920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // Visibility mismatch is an API change, so check for it
660920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (mi.mIsPrivate == om.mIsPrivate && mi.mIsPublic == om.mIsPublic
661920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          && mi.mIsProtected == om.mIsProtected) {
662920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // Look only for overrides of an ancestor class implementation,
663920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // not of e.g. an abstract or interface method declaration
664920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (!om.isAbstract()) {
6655118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          // If the parent is hidden or removed, we can't rely on it to provide
666920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // the API
6675118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          if (!om.isHiddenOrRemoved()) {
668920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // If the only "override" turns out to be in our own class
669920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // (which sometimes happens in concrete subclasses of
670920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            // abstract base classes), it's not really an override
671920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!mi.mContainingClass.equals(om.mContainingClass)) {
672920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              return true;
673920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
674920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
675920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
676920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
677920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
678920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return false;
679920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
680920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
681920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static boolean canCallMethod(ClassInfo from, MethodInfo m) {
682920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (m.isPublic() || m.isProtected()) {
683920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return true;
684920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
685920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (m.isPackagePrivate()) {
686920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String fromPkg = from.containingPackage().name();
687920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String pkg = m.containingClass().containingPackage().name();
688920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (fromPkg.equals(pkg)) {
689920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        return true;
690920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
691920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
692920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return false;
693920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
694920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
695920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  // call a constructor, any constructor on this class's superclass.
696d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  static String superCtorCall(ClassInfo cl, ArrayList<ClassInfo> thrownExceptions) {
697920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo base = cl.realSuperclass();
698920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (base == null) {
699920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return "";
700920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
701920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    HashSet<String> exceptionNames = new HashSet<String>();
702920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (thrownExceptions != null) {
703920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      for (ClassInfo thrown : thrownExceptions) {
704920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        exceptionNames.add(thrown.name());
705920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
706920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
707d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> ctors = base.constructors();
708920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    MethodInfo ctor = null;
709920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // bad exception indicates that the exceptions thrown by the super constructor
710920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // are incompatible with the constructor we're using for the sub class.
711920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Boolean badException = false;
712920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo m : ctors) {
713920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (canCallMethod(cl, m)) {
714920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (m.thrownExceptions() != null) {
715920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          for (ClassInfo thrown : m.thrownExceptions()) {
716920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            if (!exceptionNames.contains(thrown.name())) {
717920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              badException = true;
718920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            }
719920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
720920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
721920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (badException) {
722920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          badException = false;
723920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          continue;
724920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
725920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // if it has no args, we're done
726d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (m.parameters().isEmpty()) {
727920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          return "";
728920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
729920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        ctor = m;
730920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
731920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
732920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (ctor != null) {
733920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      String result = "";
734920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      result += "super(";
735d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      ArrayList<ParameterInfo> params = ctor.parameters();
736d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      for (ParameterInfo param : params) {
737d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        TypeInfo t = param.type();
738920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        if (t.isPrimitive() && t.dimension().equals("")) {
739920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          String n = t.simpleTypeName();
740920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          if (("byte".equals(n) || "short".equals(n) || "int".equals(n) || "long".equals(n)
741920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              || "float".equals(n) || "double".equals(n))
742920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              && t.dimension().equals("")) {
743920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "0";
744920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if ("char".equals(n)) {
745920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "'\\0'";
746920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else if ("boolean".equals(n)) {
747920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "false";
748920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          } else {
749920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            result += "<<unknown-" + n + ">>";
750920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          }
751920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        } else {
752920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // put null in each super class method. Cast null to the correct type
753920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // to avoid collisions with other constructors. If the type is generic
754920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          // don't cast it
755920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          result +=
756920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              (!t.isTypeVariable() ? "(" + t.qualifiedTypeName() + t.dimension() + ")" : "")
757920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson                  + "null";
758920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
759d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein        if (param != params.get(params.size()-1)) {
760920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          result += ",";
761920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        }
762920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
763920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      result += "); ";
764920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return result;
765920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
766920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return "";
767920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
768920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
769920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
77073934887ea87fca353449f0fd476d6c07b349521Tor Norbye    /**
77173934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * Write out the given list of annotations. If the {@code isDeprecated}
77273934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * flag is true also write out a {@code @Deprecated} annotation if it did not
77373934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * already appear in the list of annotations. (This covers APIs that mention
77473934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * {@code @deprecated} in their documentation but fail to add
77573934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * {@code @Deprecated} as an annotation.
77673934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * <p>
77773934887ea87fca353449f0fd476d6c07b349521Tor Norbye     * {@code @Override} annotations are deliberately skipped.
77873934887ea87fca353449f0fd476d6c07b349521Tor Norbye     */
77973934887ea87fca353449f0fd476d6c07b349521Tor Norbye  static void writeAnnotations(PrintStream stream, List<AnnotationInstanceInfo> annotations,
78073934887ea87fca353449f0fd476d6c07b349521Tor Norbye          boolean isDeprecated) {
78173934887ea87fca353449f0fd476d6c07b349521Tor Norbye    assert annotations != null;
782920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (AnnotationInstanceInfo ann : annotations) {
78373934887ea87fca353449f0fd476d6c07b349521Tor Norbye      // Skip @Override annotations: the stubs do not need it and in some cases it leads
78473934887ea87fca353449f0fd476d6c07b349521Tor Norbye      // to compilation errors with the way the stubs are generated
78573934887ea87fca353449f0fd476d6c07b349521Tor Norbye      if (ann.type() != null && ann.type().qualifiedName().equals("java.lang.Override")) {
78673934887ea87fca353449f0fd476d6c07b349521Tor Norbye        continue;
78773934887ea87fca353449f0fd476d6c07b349521Tor Norbye      }
7885118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (!ann.type().isHiddenOrRemoved()) {
789920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        stream.println(ann.toString());
79073934887ea87fca353449f0fd476d6c07b349521Tor Norbye        if (isDeprecated && ann.type() != null
79173934887ea87fca353449f0fd476d6c07b349521Tor Norbye            && ann.type().qualifiedName().equals("java.lang.Deprecated")) {
79273934887ea87fca353449f0fd476d6c07b349521Tor Norbye          isDeprecated = false; // Prevent duplicate annotations
79373934887ea87fca353449f0fd476d6c07b349521Tor Norbye        }
794920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
795920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
79673934887ea87fca353449f0fd476d6c07b349521Tor Norbye    if (isDeprecated) {
79773934887ea87fca353449f0fd476d6c07b349521Tor Norbye      stream.println("@Deprecated");
79873934887ea87fca353449f0fd476d6c07b349521Tor Norbye    }
799920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
800920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
801920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeAnnotationElement(PrintStream stream, MethodInfo ann) {
802920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(ann.returnType().fullName());
803920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(" ");
804920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print(ann.name());
805920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.print("()");
806920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    AnnotationValueInfo def = ann.defaultAnnotationElementValue();
807920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (def != null) {
808920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(" default ");
809920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      stream.print(def.valueString());
810920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
811920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    stream.println(";");
812920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
813920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
814920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeXML(PrintStream xmlWriter, HashMap<PackageInfo, List<ClassInfo>> allClasses,
815040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      HashSet<ClassInfo> notStrippable) {
816920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // extract the set of packages, sort them by name, and write them out in that order
817920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Set<PackageInfo> allClassKeys = allClasses.keySet();
818920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
819920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Arrays.sort(allPackages, PackageInfo.comparator);
820920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
821920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<api>");
822920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (PackageInfo pack : allPackages) {
823920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writePackageXML(xmlWriter, pack, allClasses.get(pack), notStrippable);
824920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
825920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</api>");
826920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
827920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
828040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static void writeXml(PrintStream xmlWriter, Collection<PackageInfo> pkgs) {
829040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final PackageInfo[] packages = pkgs.toArray(new PackageInfo[pkgs.size()]);
830040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(packages, PackageInfo.comparator);
831040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
832040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    HashSet<ClassInfo> notStrippable = new HashSet();
833040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
834040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      for (ClassInfo cl: pkg.allClasses().values()) {
835040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        notStrippable.add(cl);
836040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
837040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
838040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    xmlWriter.println("<api>");
839040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
840040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writePackageXML(xmlWriter, pkg, pkg.allClasses().values(), notStrippable);
841040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
842040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    xmlWriter.println("</api>");
843040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
844040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
845040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writePackageXML(PrintStream xmlWriter, PackageInfo pack,
846040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
847920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
848920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    Arrays.sort(classes, ClassInfo.comparator);
849920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Work around the bogus "Array" class we invent for
850920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
851920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
852920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      return;
853920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
854920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<package name=\"" + pack.name() + "\"\n"
855920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // + " source=\"" + pack.position() + "\"\n"
856920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
857920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo cl : classes) {
858920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeClassXML(xmlWriter, cl, notStrippable);
859920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
860920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</package>");
861920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
862920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
863920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
864920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
865040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassXML(PrintStream xmlWriter, ClassInfo cl, HashSet<ClassInfo> notStrippable) {
866920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = cl.scope();
867920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
868920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String declString = (cl.isInterface()) ? "interface" : "class";
869920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (cl.isDeprecated()) {
870920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
871920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
872920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
873920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
874920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<" + declString + " name=\"" + cl.name() + "\"");
875920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (!cl.isInterface() && !cl.qualifiedName().equals("java.lang.Object")) {
876920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println(" extends=\""
877920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + ((cl.realSuperclass() == null) ? "java.lang.Object" : cl.realSuperclass()
878920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson              .qualifiedName()) + "\"");
879920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
880920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println(" abstract=\"" + cl.isAbstract() + "\"\n" + " static=\"" + cl.isStatic()
881920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + "\"\n" + " final=\"" + cl.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString
882920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + "\"\n" + " visibility=\"" + scope + "\"\n"
883920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + cl.position() + "\"\n"
884920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
885920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
886d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> interfaces = cl.realInterfaces();
887d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(interfaces, ClassInfo.comparator);
888920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo iface : interfaces) {
889920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      if (notStrippable.contains(iface)) {
890920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        xmlWriter.println("<implements name=\"" + iface.qualifiedName() + "\">");
891920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        xmlWriter.println("</implements>");
892920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
893920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
894920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
895d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> constructors = cl.constructors();
896d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(constructors, MethodInfo.comparator);
897920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo mi : constructors) {
898920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeConstructorXML(xmlWriter, mi);
899920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
900920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
901d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> methods = cl.allSelfMethods();
902d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(methods, MethodInfo.comparator);
903920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (MethodInfo mi : methods) {
904040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (!methodIsOverride(notStrippable, mi)) {
905920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        writeMethodXML(xmlWriter, mi);
906920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      }
907920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
908920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
909ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang    ArrayList<FieldInfo> fields = cl.selfFields();
910d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(fields, FieldInfo.comparator);
911920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (FieldInfo fi : fields) {
912920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeFieldXML(xmlWriter, fi);
913920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
914920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</" + declString + ">");
915920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
916920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
917920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
918920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeMethodXML(PrintStream xmlWriter, MethodInfo mi) {
919920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = mi.scope();
920920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
921920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
922920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mi.isDeprecated()) {
923920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
924920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
925920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
926920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
927920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<method name=\""
928920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + mi.name()
929920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + "\"\n"
930920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ((mi.returnType() != null) ? " return=\""
931920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson            + makeXMLcompliant(fullParameterTypeName(mi, mi.returnType(), false)) + "\"\n" : "")
932920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " abstract=\"" + mi.isAbstract() + "\"\n" + " native=\"" + mi.isNative() + "\"\n"
933920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " synchronized=\"" + mi.isSynchronized() + "\"\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
939920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // write parameters in declaration order
940d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int numParameters = mi.parameters().size();
941920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int count = 0;
942920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ParameterInfo pi : mi.parameters()) {
943920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      count++;
944920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeParameterXML(xmlWriter, mi, pi, count == numParameters);
945920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
946920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
947920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // but write exceptions in canonicalized order
948d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> exceptions = mi.thrownExceptions();
949d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(exceptions, ClassInfo.comparator);
950920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo pi : exceptions) {
951920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("<exception name=\"" + pi.name() + "\" type=\"" + pi.qualifiedName()
952920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + "\">");
953920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("</exception>");
954920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
955920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</method>");
956920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
957920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
958920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeConstructorXML(PrintStream xmlWriter, MethodInfo mi) {
959920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = mi.scope();
960920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
961920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (mi.isDeprecated()) {
962920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
963920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
964920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
965920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
966920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<constructor name=\"" + mi.name() + "\"\n" + " type=\""
967920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + mi.containingClass().qualifiedName() + "\"\n" + " static=\"" + mi.isStatic() + "\"\n"
968920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " final=\"" + mi.isFinal() + "\"\n" + " deprecated=\"" + deprecatedString + "\"\n"
969920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " visibility=\"" + scope + "\"\n"
970920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + mi.position() + "\"\n"
971920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
972920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
973d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    int numParameters = mi.parameters().size();
974920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    int count = 0;
975920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ParameterInfo pi : mi.parameters()) {
976920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      count++;
977920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      writeParameterXML(xmlWriter, mi, pi, count == numParameters);
978920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
979920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
980d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> exceptions = mi.thrownExceptions();
981d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(exceptions, ClassInfo.comparator);
982920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    for (ClassInfo pi : exceptions) {
983920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("<exception name=\"" + pi.name() + "\" type=\"" + pi.qualifiedName()
984920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson          + "\">");
985920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      xmlWriter.println("</exception>");
986920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
987920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</constructor>");
988920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
989920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
990920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeParameterXML(PrintStream xmlWriter, MethodInfo method, ParameterInfo pi,
991920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      boolean isLast) {
992920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<parameter name=\"" + pi.name() + "\" type=\""
993920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + makeXMLcompliant(fullParameterTypeName(method, pi.type(), isLast)) + "\">");
994920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</parameter>");
995920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
996920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
997920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static void writeFieldXML(PrintStream xmlWriter, FieldInfo fi) {
998920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String scope = fi.scope();
999920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String deprecatedString = "";
1000920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (fi.isDeprecated()) {
1001920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "deprecated";
1002920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    } else {
1003920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      deprecatedString = "not deprecated";
1004920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
1005920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    // need to make sure value is valid XML
1006920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String value = makeXMLcompliant(fi.constantLiteralValue());
1007920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
10087751817561b5fea6ffaee8cad497ab6876deca0eYing Wang    String fullTypeName = makeXMLcompliant(fi.type().fullName());
1009920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
1010920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("<field name=\"" + fi.name() + "\"\n" + " type=\"" + fullTypeName + "\"\n"
1011920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + " transient=\"" + fi.isTransient() + "\"\n" + " volatile=\"" + fi.isVolatile() + "\"\n"
1012920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + (fieldIsInitialized(fi) ? " value=\"" + value + "\"\n" : "") + " static=\""
1013920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + fi.isStatic() + "\"\n" + " final=\"" + fi.isFinal() + "\"\n" + " deprecated=\""
1014920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + deprecatedString + "\"\n" + " visibility=\"" + scope + "\"\n"
1015920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        // + " source=\"" + fi.position() + "\"\n"
1016920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson        + ">");
1017920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    xmlWriter.println("</field>");
1018920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
1019920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
1020920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static String makeXMLcompliant(String s) {
1021920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String returnString = "";
1022920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = s.replaceAll("&", "&amp;");
1023920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll("<", "&lt;");
1024920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll(">", "&gt;");
1025920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll("\"", "&quot;");
1026920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    returnString = returnString.replaceAll("'", "&pos;");
1027920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return returnString;
1028920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
1029920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson
10305118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu  static void writeRemovedApi(PrintStream apiWriter, HashMap<PackageInfo,
10315118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      List<ClassInfo>> allPackageClassMap, Set<ClassInfo> notStrippable) {
10325118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    final PackageInfo[] packages = allPackageClassMap.keySet().toArray(new PackageInfo[0]);
10335118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    Arrays.sort(packages, PackageInfo.comparator);
10345118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (PackageInfo pkg : packages) {
10355118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      // beware that pkg.allClasses() has no class in it at the moment
10365118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      final List<ClassInfo> classes = allPackageClassMap.get(pkg);
10375118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      Collections.sort(classes, ClassInfo.comparator);
10385118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      boolean hasWrittenPackageHead = false;
10395118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      for (ClassInfo cl : classes) {
10405118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        if (cl.hasRemovedSelfMembers()) {
10415118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          if (!hasWrittenPackageHead) {
10425118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            hasWrittenPackageHead = true;
10435118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            apiWriter.print("package ");
10445118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            apiWriter.print(pkg.qualifiedName());
10455118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu            apiWriter.print(" {\n\n");
10465118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          }
10475118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          writeClassRemovedSelfMembers(apiWriter, cl, notStrippable);
10485118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        }
10495118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      }
10505118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
10515118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      // the package contains some classes with some removed members
10525118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (hasWrittenPackageHead) {
10535118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        apiWriter.print("}\n\n");
10545118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      }
10555118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
10565118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu  }
10575118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
10585118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu  /**
10595118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu   * Write the removed members of the class to removed.txt
10605118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu   */
10615118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu  private static void writeClassRemovedSelfMembers(PrintStream apiWriter, ClassInfo cl,
10625118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      Set<ClassInfo> notStrippable) {
10635118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print("  ");
10645118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print(cl.scope());
10655118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (cl.isStatic()) {
10665118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      apiWriter.print(" static");
10675118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
10685118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (cl.isFinal()) {
10695118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      apiWriter.print(" final");
10705118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
10715118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (cl.isAbstract()) {
10725118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      apiWriter.print(" abstract");
10735118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
10745118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (cl.isDeprecated()) {
10755118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      apiWriter.print(" deprecated");
10765118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
10775118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print(" ");
10785118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print(cl.isInterface() ? "interface" : "class");
10795118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print(" ");
10805118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print(cl.name());
10815118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
10825118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    if (!cl.isInterface()
10835118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        && !"java.lang.Object".equals(cl.qualifiedName())
10845118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        && cl.realSuperclass() != null
10855118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        && !"java.lang.Object".equals(cl.realSuperclass().qualifiedName())) {
10865118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      apiWriter.print(" extends ");
10875118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      apiWriter.print(cl.realSuperclass().qualifiedName());
10885118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
10895118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
10905118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    ArrayList<ClassInfo> interfaces = cl.realInterfaces();
10915118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    Collections.sort(interfaces, ClassInfo.comparator);
10925118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    boolean first = true;
10935118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (ClassInfo iface : interfaces) {
10945118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      if (notStrippable.contains(iface)) {
10955118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        if (first) {
10965118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          apiWriter.print(" implements");
10975118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu          first = false;
10985118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        }
10995118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        apiWriter.print(" ");
11005118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu        apiWriter.print(iface.qualifiedName());
11015118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      }
11025118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
11035118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
11045118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print(" {\n");
11055118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
11065118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    List<MethodInfo> constructors = cl.getRemovedConstructors();
11075118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (MethodInfo mi : constructors) {
11085118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      writeConstructorApi(apiWriter, mi);
11095118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
11105118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
11115118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    List<MethodInfo> methods = cl.getRemovedSelfMethods();
11125118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (MethodInfo mi : methods) {
11135118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      writeMethodApi(apiWriter, mi);
11145118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
11155118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
11165118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    List<FieldInfo> enums = cl.getRemovedSelfEnumConstants();
11175118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (FieldInfo fi : enums) {
11185118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      writeFieldApi(apiWriter, fi, "enum_constant");
11195118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
11205118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
11215118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    List<FieldInfo> fields = cl.getRemovedSelfFields();
11225118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    for (FieldInfo fi : fields) {
11235118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      writeFieldApi(apiWriter, fi, "field");
11245118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    }
11255118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
11265118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu    apiWriter.print("  }\n\n");
11275118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu  }
11285118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu
1129040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  public static void writeApi(PrintStream apiWriter, Collection<PackageInfo> pkgs) {
1130040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    final PackageInfo[] packages = pkgs.toArray(new PackageInfo[pkgs.size()]);
1131040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(packages, PackageInfo.comparator);
1132040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1133040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    HashSet<ClassInfo> notStrippable = new HashSet();
1134040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
1135040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      for (ClassInfo cl: pkg.allClasses().values()) {
1136040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        notStrippable.add(cl);
1137040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1138040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1139040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pkg: packages) {
1140040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writePackageApi(apiWriter, pkg, pkg.allClasses().values(), notStrippable);
1141040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1142040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1143040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1144040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeApi(PrintStream apiWriter, HashMap<PackageInfo, List<ClassInfo>> allClasses,
1145040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      HashSet<ClassInfo> notStrippable) {
1146040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // extract the set of packages, sort them by name, and write them out in that order
1147040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Set<PackageInfo> allClassKeys = allClasses.keySet();
1148040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
1149040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(allPackages, PackageInfo.comparator);
1150040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1151040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (PackageInfo pack : allPackages) {
1152040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writePackageApi(apiWriter, pack, allClasses.get(pack), notStrippable);
1153040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1154040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1155040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1156040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writePackageApi(PrintStream apiWriter, PackageInfo pack,
1157040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
1158040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // Work around the bogus "Array" class we invent for
1159040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
1160040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
1161040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      return;
1162040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1163040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1164040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("package ");
1165040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(pack.qualifiedName());
1166040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" {\n\n");
1167040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1168040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
1169040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Arrays.sort(classes, ClassInfo.comparator);
1170040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (ClassInfo cl : classes) {
1171040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeClassApi(apiWriter, cl, notStrippable);
1172040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1173040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1174040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("}\n\n");
1175040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1176040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1177040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeClassApi(PrintStream apiWriter, ClassInfo cl, HashSet<ClassInfo> notStrippable) {
1178040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean first;
1179040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1180040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("  ");
1181040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(cl.scope());
1182040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isStatic()) {
1183040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" static");
1184040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1185040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isFinal()) {
1186040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" final");
1187040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1188040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isAbstract()) {
1189040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" abstract");
1190040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1191040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (cl.isDeprecated()) {
1192040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1193040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1194040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1195040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(cl.isInterface() ? "interface" : "class");
1196040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1197040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(cl.name());
1198040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1199040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (!cl.isInterface()
1200040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        && !"java.lang.Object".equals(cl.qualifiedName())
1201040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        && cl.realSuperclass() != null
1202040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        && !"java.lang.Object".equals(cl.realSuperclass().qualifiedName())) {
1203040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" extends ");
1204040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(cl.realSuperclass().qualifiedName());
1205040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1206040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1207d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<ClassInfo> interfaces = cl.realInterfaces();
1208d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(interfaces, ClassInfo.comparator);
1209040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    first = true;
1210040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (ClassInfo iface : interfaces) {
1211040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (notStrippable.contains(iface)) {
1212040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (first) {
1213040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          apiWriter.print(" implements");
1214040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          first = false;
1215040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
1216040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(" ");
1217040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(iface.qualifiedName());
1218040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1219040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1220040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1221040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" {\n");
1222040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1223d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> constructors = cl.constructors();
1224d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(constructors, MethodInfo.comparator);
1225040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (MethodInfo mi : constructors) {
1226040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      writeConstructorApi(apiWriter, mi);
1227040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1228040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1229d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<MethodInfo> methods = cl.allSelfMethods();
1230d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(methods, MethodInfo.comparator);
1231040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (MethodInfo mi : methods) {
1232040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (!methodIsOverride(notStrippable, mi)) {
1233040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        writeMethodApi(apiWriter, mi);
1234040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1235040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1236040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1237d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    ArrayList<FieldInfo> enums = cl.enumConstants();
1238d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(enums, FieldInfo.comparator);
1239132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    for (FieldInfo fi : enums) {
1240132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      writeFieldApi(apiWriter, fi, "enum_constant");
1241132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    }
1242132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato
1243ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang    ArrayList<FieldInfo> fields = cl.selfFields();
1244d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(fields, FieldInfo.comparator);
1245040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    for (FieldInfo fi : fields) {
1246132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato      writeFieldApi(apiWriter, fi, "field");
1247040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1248040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1249040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("  }\n\n");
1250040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1251040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1252040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeConstructorApi(PrintStream apiWriter, MethodInfo mi) {
1253040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("    ctor ");
1254040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.scope());
1255040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isDeprecated()) {
1256040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1257040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1258040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1259040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.name());
1260040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1261040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeParametersApi(apiWriter, mi, mi.parameters());
1262040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeThrowsApi(apiWriter, mi.thrownExceptions());
1263040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(";\n");
1264040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1265040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1266040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  static void writeMethodApi(PrintStream apiWriter, MethodInfo mi) {
1267040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("    method ");
1268040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.scope());
1269040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isStatic()) {
1270040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" static");
1271040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1272040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isFinal()) {
1273040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" final");
1274040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1275040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isAbstract()) {
1276040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" abstract");
1277040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1278040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isDeprecated()) {
1279040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1280040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1281040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.isSynchronized()) {
1282040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" synchronized");
1283040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1284040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1285040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (mi.returnType() == null) {
1286040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print("void");
1287040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    } else {
1288040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(fullParameterTypeName(mi, mi.returnType(), false));
1289040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1290040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1291040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(mi.name());
1292040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1293040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeParametersApi(apiWriter, mi, mi.parameters());
1294040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    writeThrowsApi(apiWriter, mi.thrownExceptions());
1295040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1296040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(";\n");
1297040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1298040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
12995118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu  static void writeParametersApi(PrintStream apiWriter, MethodInfo method,
13005118ffe3bf77ec4efa070f36a7a62fd5d1bf16bfHui Shu      ArrayList<ParameterInfo> params) {
1301040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("(");
1302040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1303d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (ParameterInfo pi : params) {
1304d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      if (pi != params.get(0)) {
1305040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(", ");
1306040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1307d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein      apiWriter.print(fullParameterTypeName(method, pi.type(), pi == params.get(params.size()-1)));
1308040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      // turn on to write the names too
1309040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (false) {
1310040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(" ");
1311040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(pi.name());
1312040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1313040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1314040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1315040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(")");
1316040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1317040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1318d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein  static void writeThrowsApi(PrintStream apiWriter, ArrayList<ClassInfo> exceptions) {
1319040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    // write in a canonical order
1320d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    exceptions = (ArrayList<ClassInfo>) exceptions.clone();
1321d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    Collections.sort(exceptions, ClassInfo.comparator);
1322d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    //final int N = exceptions.length;
1323040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    boolean first = true;
1324d6eaacbb9eb56763d38a3815fc509b92ed98a585Andrew Sapperstein    for (ClassInfo ex : exceptions) {
1325040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      // Turn this off, b/c we need to regenrate the old xml files.
1326040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (true || !"java.lang.RuntimeException".equals(ex.qualifiedName())
1327040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          && !ex.isDerivedFrom("java.lang.RuntimeException")) {
1328040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        if (first) {
1329040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          apiWriter.print(" throws ");
1330040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          first = false;
1331040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        } else {
1332040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato          apiWriter.print(", ");
1333040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        }
1334040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.print(ex.qualifiedName());
1335040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1336040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1337040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1338040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1339132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato  static void writeFieldApi(PrintStream apiWriter, FieldInfo fi, String label) {
1340132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    apiWriter.print("    ");
1341132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    apiWriter.print(label);
1342132afe44b3b7963e47d4c32948b2667ddc00062cJoe Onorato    apiWriter.print(" ");
1343040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(fi.scope());
1344040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isStatic()) {
1345040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" static");
1346040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1347040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isFinal()) {
1348040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" final");
1349040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1350040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isDeprecated()) {
1351040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" deprecated");
1352040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1353040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isTransient()) {
1354040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" transient");
1355040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1356040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isVolatile()) {
1357040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" volatile");
1358040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1359040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1360040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
13617751817561b5fea6ffaee8cad497ab6876deca0eYing Wang    apiWriter.print(fi.type().fullName());
1362040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1363040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(" ");
1364040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(fi.name());
1365040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1366040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    Object val = null;
1367040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (fi.isConstant() && fieldIsInitialized(fi)) {
1368040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(" = ");
1369040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      apiWriter.print(fi.constantLiteralValue());
1370040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      val = fi.constantValue();
1371040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1372040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1373040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print(";");
1374040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1375040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    if (val != null) {
1376040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      if (val instanceof Integer && "char".equals(fi.type().qualifiedTypeName())) {
1377040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.format(" // 0x%04x '%s'", val,
1378040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato            FieldInfo.javaEscapeString("" + ((char)((Integer)val).intValue())));
1379040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (val instanceof Byte || val instanceof Short || val instanceof Integer) {
1380040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.format(" // 0x%x", val);
1381040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      } else if (val instanceof Long) {
1382040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato        apiWriter.format(" // 0x%xL", val);
1383040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato      }
1384040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    }
1385040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1386040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato    apiWriter.print("\n");
1387040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato  }
1388040992567205c3b6e4ee01bfb2893bceb915357cJoe Onorato
1389970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeKeepList(PrintStream keepListWriter,
1390970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      HashMap<PackageInfo, List<ClassInfo>> allClasses, HashSet<ClassInfo> notStrippable) {
1391970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // extract the set of packages, sort them by name, and write them out in that order
1392970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Set<PackageInfo> allClassKeys = allClasses.keySet();
1393970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    PackageInfo[] allPackages = allClassKeys.toArray(new PackageInfo[allClassKeys.size()]);
1394970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Arrays.sort(allPackages, PackageInfo.comparator);
1395970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1396970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (PackageInfo pack : allPackages) {
1397970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writePackageKeepList(keepListWriter, pack, allClasses.get(pack), notStrippable);
1398970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1399970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1400970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1401970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writePackageKeepList(PrintStream keepListWriter, PackageInfo pack,
1402970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      Collection<ClassInfo> classList, HashSet<ClassInfo> notStrippable) {
1403970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // Work around the bogus "Array" class we invent for
1404970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    // Arrays.copyOf's Class<? extends T[]> newType parameter. (http://b/2715505)
1405970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (pack.name().equals(PackageInfo.DEFAULT_PACKAGE)) {
1406970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      return;
1407970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1408970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1409970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ClassInfo[] classes = classList.toArray(new ClassInfo[classList.size()]);
1410970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Arrays.sort(classes, ClassInfo.comparator);
1411970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (ClassInfo cl : classes) {
1412970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeClassKeepList(keepListWriter, cl, notStrippable);
1413970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1414970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1415970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1416970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeClassKeepList(PrintStream keepListWriter, ClassInfo cl,
1417970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      HashSet<ClassInfo> notStrippable) {
1418970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("-keep class ");
1419970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(to$Class(cl.qualifiedName()));
1420970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1421970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" {\n");
1422970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1423970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<MethodInfo> constructors = cl.constructors();
1424970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(constructors, MethodInfo.comparator);
1425970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (MethodInfo mi : constructors) {
1426970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeConstructorKeepList(keepListWriter, mi);
1427970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1428970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1429970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("\n");
1430970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1431970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<MethodInfo> methods = cl.allSelfMethods();
1432970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(methods, MethodInfo.comparator);
1433970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (MethodInfo mi : methods) {
143437abe68eddab604d66d9d7c6eaeed5b0e2b2fc33Adam Metcalf      // allSelfMethods is the non-hidden and visible methods. See Doclava.checkLevel.
143537abe68eddab604d66d9d7c6eaeed5b0e2b2fc33Adam Metcalf      writeMethodKeepList(keepListWriter, mi);
1436970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1437970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1438970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("\n");
1439970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1440970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    ArrayList<FieldInfo> enums = cl.enumConstants();
1441970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(enums, FieldInfo.comparator);
1442970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (FieldInfo fi : enums) {
1443970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeFieldKeepList(keepListWriter, fi);
1444970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1445970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1446970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("\n");
1447970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1448ae8cb832ba8239534b7529292065936bdb85b1e3Ying Wang    ArrayList<FieldInfo> fields = cl.selfFields();
1449970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    Collections.sort(fields, FieldInfo.comparator);
1450970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (FieldInfo fi : fields) {
1451970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      writeFieldKeepList(keepListWriter, fi);
1452970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1453970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1454970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("}\n\n");
1455970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1456970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1457970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeConstructorKeepList(PrintStream keepListWriter, MethodInfo mi) {
1458970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("    ");
1459970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    String name = mi.name();
1460970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    name = name.replace(".", "$");
1461970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(name);
1462970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1463970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    writeParametersKeepList(keepListWriter, mi, mi.parameters());
1464970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(";\n");
1465970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1466970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1467970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeMethodKeepList(PrintStream keepListWriter, MethodInfo mi) {
1468970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("    ");
1469970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(mi.scope());
1470970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.isStatic()) {
1471970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" static");
1472970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1473970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.isAbstract()) {
1474970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" abstract");
1475970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1476970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.isSynchronized()) {
1477970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" synchronized");
1478970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1479970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1480970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (mi.returnType() == null) {
1481970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print("void");
1482970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    } else {
1483970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(getCleanTypeName(mi.returnType()));
1484970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1485970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1486970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(mi.name());
1487970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1488970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    writeParametersKeepList(keepListWriter, mi, mi.parameters());
1489970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1490970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(";\n");
1491970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1492970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1493970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeParametersKeepList(PrintStream keepListWriter, MethodInfo method,
1494970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      ArrayList<ParameterInfo> params) {
1495970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("(");
1496970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1497970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    for (ParameterInfo pi : params) {
1498970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      if (pi != params.get(0)) {
1499970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        keepListWriter.print(", ");
1500970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
1501550a9de05d89f19d1f824fbbb04ba7cd8a1ff86eJeff Hamilton      keepListWriter.print(getCleanTypeName(pi.type()));
1502970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1503970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1504970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(")");
1505970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1506970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1507970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static void writeFieldKeepList(PrintStream keepListWriter, FieldInfo fi) {
1508970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print("    ");
1509970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(fi.scope());
1510970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (fi.isStatic()) {
1511970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" static");
1512970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1513970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (fi.isTransient()) {
1514970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" transient");
1515970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1516970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    if (fi.isVolatile()) {
1517970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      keepListWriter.print(" volatile");
1518970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1519970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1520970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1521e64dc94c3548aba038c89438fc9fb492dc678c48Sergei Datsenko    keepListWriter.print(getCleanTypeName(fi.type()));
1522970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1523970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(" ");
1524970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(fi.name());
1525970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1526970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    keepListWriter.print(";\n");
1527970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1528970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1529920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  static String fullParameterTypeName(MethodInfo method, TypeInfo type, boolean isLast) {
1530920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    String fullTypeName = type.fullName(method.typeVariables());
1531920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    if (isLast && method.isVarArgs()) {
1532920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // TODO: note that this does not attempt to handle hypothetical
1533920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // vararg methods whose last parameter is a list of arrays, e.g.
1534920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      // "Object[]...".
1535920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson      fullTypeName = type.fullNameNoDimension(method.typeVariables()) + "...";
1536920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    }
1537920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson    return fullTypeName;
1538920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson  }
1539970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1540970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static String to$Class(String name) {
1541970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    int pos = 0;
1542970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    while ((pos = name.indexOf('.', pos)) > 0) {
1543970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      String n = name.substring(0, pos);
1544970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      if (Converter.obtainClass(n) != null) {
1545970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton        return n + (name.substring(pos).replace('.', '$'));
1546970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      }
1547970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton      pos = pos + 1;
1548970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    }
1549970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton    return name;
1550970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1551970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton
1552970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  static String getCleanTypeName(TypeInfo t) {
1553d6f2c2b6edce46c86581be1f508981742e20fb51Jeff Hamilton      return t.isPrimitive() ? t.simpleTypeName() + t.dimension() :
15541e0d370c6a4c165cb8c74f53cb035e5521e0cd87Jeff Hamilton              to$Class(t.asClassInfo().qualifiedName() + t.dimension());
1555970f13f08e404fa1e265e7ab24050f5a8c6e4603Jeff Hamilton  }
1556920dbbbaca6aa578f3b26d89e99d12754c26ed60Ben Dodson}
1557