Thu, 12 Jan 2012 15:28:34 +0000
7123100: javac fails with java.lang.StackOverflowError
Summary: Inference of under-constrained type-variables creates erroneous recursive wildcard types
Reviewed-by: jjg
1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javadoc;
28 import java.io.DataInputStream;
29 import java.io.InputStream;
30 import java.io.IOException;
31 import java.text.CollationKey;
32 import javax.tools.FileObject;
34 import com.sun.javadoc.*;
36 import com.sun.tools.javac.util.Position;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
40 /**
41 * abstract base class of all Doc classes. Doc item's are representations
42 * of java language constructs (class, package, method,...) which have
43 * comments and have been processed by this run of javadoc. All Doc items
44 * are unique, that is, they are == comparable.
45 *
46 * @since 1.2
47 * @author Robert Field
48 * @author Atul M Dambalkar
49 * @author Neal Gafter (rewrite)
50 */
51 public abstract class DocImpl implements Doc, Comparable<Object> {
53 /**
54 * Doc environment
55 */
56 protected final DocEnv env; //### Rename this everywhere to 'docenv' ?
58 /**
59 * The complex comment object, lazily initialized.
60 */
61 private Comment comment;
63 /**
64 * The cached sort key, to take care of Natural Language Text sorting.
65 */
66 private CollationKey collationkey = null;
68 /**
69 * Raw documentation string.
70 */
71 protected String documentation; // Accessed in PackageDocImpl, RootDocImpl
73 /**
74 * Cached first sentence.
75 */
76 private Tag[] firstSentence;
78 /**
79 * Cached inline tags.
80 */
81 private Tag[] inlineTags;
83 /**
84 * Constructor.
85 */
86 DocImpl(DocEnv env, String documentation) {
87 this.documentation = documentation;
88 this.env = env;
89 }
91 /**
92 * So subclasses have the option to do lazy initialization of
93 * "documentation" string.
94 */
95 protected String documentation() {
96 if (documentation == null) documentation = "";
97 return documentation;
98 }
100 /**
101 * For lazy initialization of comment.
102 */
103 Comment comment() {
104 if (comment == null) {
105 comment = new Comment(this, documentation());
106 }
107 return comment;
108 }
110 /**
111 * Return the text of the comment for this doc item.
112 * TagImpls have been removed.
113 */
114 public String commentText() {
115 return comment().commentText();
116 }
118 /**
119 * Return all tags in this Doc item.
120 *
121 * @return an array of TagImpl containing all tags on this Doc item.
122 */
123 public Tag[] tags() {
124 return comment().tags();
125 }
127 /**
128 * Return tags of the specified kind in this Doc item.
129 *
130 * @param tagname name of the tag kind to search for.
131 * @return an array of TagImpl containing all tags whose 'kind()'
132 * matches 'tagname'.
133 */
134 public Tag[] tags(String tagname) {
135 return comment().tags(tagname);
136 }
138 /**
139 * Return the see also tags in this Doc item.
140 *
141 * @return an array of SeeTag containing all @see tags.
142 */
143 public SeeTag[] seeTags() {
144 return comment().seeTags();
145 }
147 public Tag[] inlineTags() {
148 if (inlineTags == null) {
149 inlineTags = Comment.getInlineTags(this, commentText());
150 }
151 return inlineTags;
152 }
154 public Tag[] firstSentenceTags() {
155 if (firstSentence == null) {
156 //Parse all sentences first to avoid duplicate warnings.
157 inlineTags();
158 try {
159 env.setSilent(true);
160 firstSentence = Comment.firstSentenceTags(this, commentText());
161 } finally {
162 env.setSilent(false);
163 }
164 }
165 return firstSentence;
166 }
168 /**
169 * Utility for subclasses which read HTML documentation files.
170 */
171 String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException {
172 byte[] filecontents = new byte[input.available()];
173 try {
174 DataInputStream dataIn = new DataInputStream(input);
175 dataIn.readFully(filecontents);
176 } finally {
177 input.close();
178 }
179 String encoding = env.getEncoding();
180 String rawDoc = (encoding!=null)
181 ? new String(filecontents, encoding)
182 : new String(filecontents);
183 Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*");
184 Matcher m = bodyPat.matcher(rawDoc);
185 if (m.matches()) {
186 return m.group(1);
187 } else {
188 String key = rawDoc.matches("(?is).*<body\\b.*")
189 ? "javadoc.End_body_missing_from_html_file"
190 : "javadoc.Body_missing_from_html_file";
191 env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key);
192 return "";
193 }
194 }
196 /**
197 * Return the full unprocessed text of the comment. Tags
198 * are included as text. Used mainly for store and retrieve
199 * operations like internalization.
200 */
201 public String getRawCommentText() {
202 return documentation();
203 }
205 /**
206 * Set the full unprocessed text of the comment. Tags
207 * are included as text. Used mainly for store and retrieve
208 * operations like internalization.
209 */
210 public void setRawCommentText(String rawDocumentation) {
211 documentation = rawDocumentation;
212 comment = null;
213 }
215 /**
216 * return a key for sorting.
217 */
218 CollationKey key() {
219 if (collationkey == null) {
220 collationkey = generateKey();
221 }
222 return collationkey;
223 }
225 /**
226 * Generate a key for sorting.
227 * <p>
228 * Default is name().
229 */
230 CollationKey generateKey() {
231 String k = name();
232 // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\"");
233 return env.doclocale.collator.getCollationKey(k);
234 }
236 /**
237 * Returns a string representation of this Doc item.
238 */
239 @Override
240 public String toString() {
241 return qualifiedName();
242 }
244 /**
245 * Returns the name of this Doc item.
246 *
247 * @return the name
248 */
249 public abstract String name();
251 /**
252 * Returns the qualified name of this Doc item.
253 *
254 * @return the name
255 */
256 public abstract String qualifiedName();
258 /**
259 * Compares this Object with the specified Object for order. Returns a
260 * negative integer, zero, or a positive integer as this Object is less
261 * than, equal to, or greater than the given Object.
262 * <p>
263 * Included so that Doc item are java.lang.Comparable.
264 *
265 * @param o the <code>Object</code> to be compared.
266 * @return a negative integer, zero, or a positive integer as this Object
267 * is less than, equal to, or greater than the given Object.
268 * @exception ClassCastException the specified Object's type prevents it
269 * from being compared to this Object.
270 */
271 public int compareTo(Object obj) {
272 // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key()));
273 return key().compareTo(((DocImpl)obj).key());
274 }
276 /**
277 * Is this Doc item a field? False until overridden.
278 *
279 * @return true if it represents a field
280 */
281 public boolean isField() {
282 return false;
283 }
285 /**
286 * Is this Doc item an enum constant? False until overridden.
287 *
288 * @return true if it represents an enum constant
289 */
290 public boolean isEnumConstant() {
291 return false;
292 }
294 /**
295 * Is this Doc item a constructor? False until overridden.
296 *
297 * @return true if it represents a constructor
298 */
299 public boolean isConstructor() {
300 return false;
301 }
303 /**
304 * Is this Doc item a method (but not a constructor or annotation
305 * type element)?
306 * False until overridden.
307 *
308 * @return true if it represents a method
309 */
310 public boolean isMethod() {
311 return false;
312 }
314 /**
315 * Is this Doc item an annotation type element?
316 * False until overridden.
317 *
318 * @return true if it represents an annotation type element
319 */
320 public boolean isAnnotationTypeElement() {
321 return false;
322 }
324 /**
325 * Is this Doc item a interface (but not an annotation type)?
326 * False until overridden.
327 *
328 * @return true if it represents a interface
329 */
330 public boolean isInterface() {
331 return false;
332 }
334 /**
335 * Is this Doc item a exception class? False until overridden.
336 *
337 * @return true if it represents a exception
338 */
339 public boolean isException() {
340 return false;
341 }
343 /**
344 * Is this Doc item a error class? False until overridden.
345 *
346 * @return true if it represents a error
347 */
348 public boolean isError() {
349 return false;
350 }
352 /**
353 * Is this Doc item an enum type? False until overridden.
354 *
355 * @return true if it represents an enum type
356 */
357 public boolean isEnum() {
358 return false;
359 }
361 /**
362 * Is this Doc item an annotation type? False until overridden.
363 *
364 * @return true if it represents an annotation type
365 */
366 public boolean isAnnotationType() {
367 return false;
368 }
370 /**
371 * Is this Doc item an ordinary class (i.e. not an interface,
372 * annotation type, enumeration, exception, or error)?
373 * False until overridden.
374 *
375 * @return true if it represents an ordinary class
376 */
377 public boolean isOrdinaryClass() {
378 return false;
379 }
381 /**
382 * Is this Doc item a class
383 * (and not an interface or annotation type)?
384 * This includes ordinary classes, enums, errors and exceptions.
385 * False until overridden.
386 *
387 * @return true if it represents a class
388 */
389 public boolean isClass() {
390 return false;
391 }
393 /**
394 * return true if this Doc is include in the active set.
395 */
396 public abstract boolean isIncluded();
398 /**
399 * Return the source position of the entity, or null if
400 * no position is available.
401 */
402 public SourcePosition position() { return null; }
403 }