Wed, 12 Mar 2008 13:06:00 -0700
6668794: javac puts localized text in raw diagnostics
6668796: bad diagnostic "bad class file" given for source files
Summary: Replace internal use of localized text with JCDiagnostic fragments; fix diagnostic for bad source file
Reviewed-by: mcimadamore
1 /*
2 * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
24 /*
25 * A utility used to invoke and test the javadoc tool.
26 *
27 * @author Scott Seligman
28 */
31 import java.io.*;
32 import java.util.*;
33 import com.sun.javadoc.*;
36 public class Tester {
38 protected final String TEST_SRC = System.getProperty("test.src", ".");
39 protected final String TEST_CLASSES = System.getProperty("test.classes",
40 ".");
41 private final String DEFAULT_ARGS[] = {
42 "-source", "1.5",
43 "-sourcepath", TEST_SRC,
44 };
46 private final File outputFile = new File(TEST_CLASSES, "testrun.out");
47 private final File expectedOutputFile = new File(TEST_SRC, "expected.out");
48 // private final File bootstrapMarkerFile = new File("bootstrap");
50 // True if we should "set expectations" by writing the expected output file
51 // rather than reading it and comparing.
52 // private final boolean bootstrap = bootstrapMarkerFile.isFile();
54 private String docletName;
55 private String[] args;
56 private Writer out = null;
59 /*
60 * Individual tests can extend this to create generics-aware doclets.
61 */
62 public static abstract class Doclet extends com.sun.javadoc.Doclet {
63 public static LanguageVersion languageVersion() {
64 return LanguageVersion.JAVA_1_5;
65 }
66 }
69 public Tester(String docletName) {
70 this(docletName, new String[0]);
71 }
73 public Tester(String docletName, String... additionalArgs) {
74 this.docletName = docletName;
76 int len = DEFAULT_ARGS.length + additionalArgs.length;
77 args = new String[len];
78 System.arraycopy(DEFAULT_ARGS, 0, args, 0, DEFAULT_ARGS.length);
79 System.arraycopy(additionalArgs, 0, args, DEFAULT_ARGS.length,
80 additionalArgs.length);
82 try {
83 out = new BufferedWriter(new FileWriter(outputFile));
84 } catch (IOException e) {
85 throw new Error("Could not open output file " + outputFile);
86 }
87 }
89 public void run() throws IOException {
90 try {
91 if (com.sun.tools.javadoc.Main.execute("javadoc",
92 docletName, args) != 0) {
93 throw new Error("Javadoc errors encountered.");
94 }
95 System.out.println("--> Output written to " + outputFile);
96 } finally {
97 out.close();
98 }
99 }
101 /*
102 * Compare output of test run to expected output.
103 * Throw an Error if they don't match.
104 */
105 public void verify() throws IOException {
106 BufferedReader thisRun =
107 new BufferedReader(new FileReader(outputFile));
108 BufferedReader expected =
109 new BufferedReader(new FileReader(expectedOutputFile));
111 for (int lineNum = 1; true; lineNum++) {
112 String line1 = thisRun.readLine();
113 String line2 = expected.readLine();
114 if (line1 == null && line2 == null) {
115 return; // EOF with all lines matching
116 }
117 if (line1 == null || !line1.equals(line2)) {
118 throw new Error(outputFile + ":" + lineNum +
119 ": output doesn't match");
120 }
121 }
122 }
125 public void println(Object o) throws IOException {
126 prln(0, o);
127 }
129 public void println() throws IOException {
130 prln();
131 }
133 public void printPackage(PackageDoc p) throws IOException {
134 prPackage(0, p);
135 }
137 public void printClass(ClassDoc cd) throws IOException {
138 if (cd.isAnnotationType())
139 printAnnotationType((AnnotationTypeDoc)cd);
140 else
141 prClass(0, cd);
142 }
144 public void printAnnotationType(AnnotationTypeDoc at) throws IOException {
145 prAnnotationType(0, at);
146 }
148 public void printField(FieldDoc f) throws IOException {
149 prField(0, f);
150 }
152 public void printParameter(Parameter p) throws IOException {
153 prParameter(0, p);
154 }
156 public void printMethod(MethodDoc m) throws IOException {
157 prln(0, "method " + m);
158 prMethod(0, m);
159 }
161 public void printAnnotationTypeElement(AnnotationTypeElementDoc e)
162 throws IOException {
163 prln(0, "element " + e);
164 prMethod(0, e);
165 }
167 public void printConstructor(ConstructorDoc c) throws IOException {
168 prln(0, "constructor " + c);
169 prExecutable(0, c);
170 }
173 private void prPackage(int off, PackageDoc p) throws IOException {
174 prln(off, "package " + p);
175 prAnnotations(off + 2, p.annotations());
176 }
178 private void prClass(int off, ClassDoc cd) throws IOException {
179 prln(off,
180 (cd.isInterface() ? "interface" : cd.isEnum() ? "enum" : "class")
181 + " " + cd);
182 prln(off + 2, "name: " + cd.simpleTypeName() + " / " +
183 cd.typeName() + " / " + cd.qualifiedTypeName());
184 prAnnotations(off + 2, cd.annotations());
185 prLabel(off + 2, "type parameters");
186 for (Type t : cd.typeParameters())
187 prln(off + 4, t);
188 prParamTags(off + 2, cd.typeParamTags());
189 prLabel(off + 2, "nested in");
190 prln(off + 4, cd.containingClass());
191 prLabel(off + 2, "superclass");
192 prln(off + 4, cd.superclassType());
193 prLabel(off + 2, "interfaces");
194 Type[] ts = cd.interfaceTypes();
195 Arrays.sort(ts);
196 for (Type t : ts)
197 prln(off + 4, t);
198 prLabel(off + 2, "enum constants");
199 for (FieldDoc f : cd.enumConstants())
200 prln(off + 4, f.name());
201 prLabel(off + 2, "fields");
202 for (FieldDoc f : cd.fields())
203 prln(off + 4, f.type() + " " + f.name());
204 prLabel(off + 2, "constructors");
205 for (ConstructorDoc c : cd.constructors())
206 prln(off + 4, c.name() + c.flatSignature());
207 prLabel(off + 2, "methods");
208 for (MethodDoc m : cd.methods())
209 prln(off + 4, typeUseString(m.returnType()) + " " +
210 m.name() + m.flatSignature());
211 }
213 private void prAnnotationType(int off, AnnotationTypeDoc at)
214 throws IOException {
215 prln(off, "@interface " + at);
216 prAnnotations(off + 2, at.annotations());
217 prLabel(off + 2, "elements");
218 for (AnnotationTypeElementDoc e : at.elements()) {
219 String def = (e.defaultValue() == null)
220 ? ""
221 : " default " + e.defaultValue();
222 prln(off + 4, typeUseString(e.returnType()) + " " + e.name() +
223 e.flatSignature() + def);
224 }
225 }
227 private void prField(int off, FieldDoc f) throws IOException {
228 prln(off, "field " + typeUseString(f.type()) + " " + f.name());
229 prAnnotations(off + 2, f.annotations());
230 }
232 private void prParameter(int off, Parameter p) throws IOException {
233 prln(off, "parameter " + p);
234 prAnnotations(off + 2, p.annotations());
235 }
237 private void prMethod(int off, MethodDoc m) throws IOException {
238 prExecutable(off, m);
239 prLabel(off + 2, "returns");
240 prln(off + 4, typeUseString(m.returnType()));
241 prLabel(off + 2, "overridden type");
242 prln(off + 4, m.overriddenType());
243 }
245 private void prExecutable(int off, ExecutableMemberDoc m)
246 throws IOException {
247 if (!m.isAnnotationTypeElement()) {
248 prln(off + 2, "signature: " + m.flatSignature());
249 prln(off + 2, " " + m.signature());
250 }
251 prAnnotations(off + 2, m.annotations());
252 prParamTags(off + 2, m.typeParamTags());
253 prParamTags(off + 2, m.paramTags());
254 prLabel(off + 2, "type parameters");
255 for (Type t : m.typeParameters())
256 prln(off + 4, t);
257 prLabel(off + 2, "throws");
258 Type[] ts = m.thrownExceptionTypes();
259 Arrays.sort(ts);
260 for (Type t : ts)
261 prln(off + 4, t);
262 }
264 private void prAnnotations(int off, AnnotationDesc[] as)
265 throws IOException {
266 prLabel(off, "annotations");
267 for (AnnotationDesc a : as)
268 prln(off + 2, a.toString());
269 }
271 private void prParamTags(int off, ParamTag tags[]) throws IOException {
272 for (ParamTag tag : tags)
273 prParamTag(off, tag);
274 }
276 private void prParamTag(int off, ParamTag tag) throws IOException {
277 String name = tag.parameterName();
278 if (tag.isTypeParameter()) name = "<" + name + ">";
279 prln(off, "@param " + name + " " + tag.parameterComment());
280 }
283 private String typeUseString(Type t) {
284 return (t instanceof ClassDoc || t instanceof TypeVariable)
285 ? t.typeName()
286 : t.toString();
287 }
290 // Labels queued for possible printing. Innermost is first in list.
291 List<Line> labels = new ArrayList<Line>();
293 // Print label if its section is nonempty.
294 void prLabel(int off, String s) {
295 while (!labels.isEmpty() && labels.get(0).off >= off)
296 labels.remove(0);
297 labels.add(0, new Line(off, s));
298 }
300 // Print queued labels with offsets less than "off".
301 void popLabels(int off) throws IOException {
302 while (!labels.isEmpty()) {
303 Line label = labels.remove(0);
304 if (label.off < off)
305 prln(label.off, label.o + ":");
306 }
307 }
309 // Print "o" at given offset.
310 void pr(int off, Object o) throws IOException {
311 popLabels(off);
312 for (int i = 0; i < off; i++)
313 out.write(' ');
314 if (o != null)
315 out.write(o.toString());
316 }
318 // Print "o" (if non-null) at given offset, then newline.
319 void prln(int off, Object o) throws IOException {
320 if (o != null) {
321 pr(off, o);
322 prln();
323 }
324 }
326 // Print newline.
327 void prln() throws IOException {
328 out.write('\n'); // don't want platform-dependent separator
329 }
332 static class Line {
333 int off;
334 Object o;
335 Line(int off, Object o) { this.off = off; this.o = o; }
336 }
337 }