Tue, 24 Dec 2013 09:17:37 -0800
8029230: Update copyright year to match last edit in jdk8 langtools repository for 2013
Reviewed-by: ksrini
Contributed-by: steve.sides@oracle.com
1 /*
2 * Copyright (c) 1997, 2013, 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.IOException;
29 import java.io.InputStream;
31 import javax.tools.FileObject;
33 import com.sun.javadoc.*;
34 import com.sun.source.util.TreePath;
35 import com.sun.tools.javac.code.Attribute;
36 import com.sun.tools.javac.code.Scope;
37 import com.sun.tools.javac.code.Symbol.ClassSymbol;
38 import com.sun.tools.javac.code.Symbol.PackageSymbol;
39 import com.sun.tools.javac.tree.JCTree;
40 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
41 import com.sun.tools.javac.util.List;
42 import com.sun.tools.javac.util.ListBuffer;
43 import com.sun.tools.javac.util.Name;
44 import com.sun.tools.javac.util.Position;
46 /**
47 * Represents a java package. Provides access to information
48 * about the package, the package's comment and tags, and the
49 * classes in the package.
50 *
51 * <p><b>This is NOT part of any supported API.
52 * If you write code that depends on this, you do so at your own risk.
53 * This code and its internal interfaces are subject to change or
54 * deletion without notice.</b>
55 *
56 * @since 1.2
57 * @author Kaiyang Liu (original)
58 * @author Robert Field (rewrite)
59 * @author Neal Gafter (rewrite)
60 * @author Scott Seligman (package-info.java)
61 */
63 public class PackageDocImpl extends DocImpl implements PackageDoc {
65 protected PackageSymbol sym;
66 private JCCompilationUnit tree = null; // for source position
68 public FileObject docPath = null;
69 private boolean foundDoc; // found a doc comment in either
70 // package.html or package-info.java
72 boolean isIncluded = false; // Set in RootDocImpl.
73 public boolean setDocPath = false; //Flag to avoid setting doc path multiple times.
75 /**
76 * Constructor
77 */
78 public PackageDocImpl(DocEnv env, PackageSymbol sym) {
79 this(env, sym, null);
80 }
82 /**
83 * Constructor
84 */
85 public PackageDocImpl(DocEnv env, PackageSymbol sym, TreePath treePath) {
86 super(env, treePath);
87 this.sym = sym;
88 this.tree = (treePath == null) ? null : (JCCompilationUnit) treePath.getCompilationUnit();
89 foundDoc = (documentation != null);
90 }
92 void setTree(JCTree tree) {
93 this.tree = (JCCompilationUnit) tree;
94 }
96 public void setTreePath(TreePath treePath) {
97 super.setTreePath(treePath);
98 checkDoc();
99 }
101 /**
102 * Do lazy initialization of "documentation" string.
103 */
104 protected String documentation() {
105 if (documentation != null)
106 return documentation;
107 if (docPath != null) {
108 // read from file
109 try {
110 InputStream s = docPath.openInputStream();
111 documentation = readHTMLDocumentation(s, docPath);
112 } catch (IOException exc) {
113 documentation = "";
114 env.error(null, "javadoc.File_Read_Error", docPath.getName());
115 }
116 } else {
117 // no doc file to be had
118 documentation = "";
119 }
120 return documentation;
121 }
123 /**
124 * Cache of all classes contained in this package, including
125 * member classes of those classes, and their member classes, etc.
126 * Includes only those classes at the specified protection level
127 * and weaker.
128 */
129 private List<ClassDocImpl> allClassesFiltered = null;
131 /**
132 * Cache of all classes contained in this package, including
133 * member classes of those classes, and their member classes, etc.
134 */
135 private List<ClassDocImpl> allClasses = null;
137 /**
138 * Return a list of all classes contained in this package, including
139 * member classes of those classes, and their member classes, etc.
140 */
141 private List<ClassDocImpl> getClasses(boolean filtered) {
142 if (allClasses != null && !filtered) {
143 return allClasses;
144 }
145 if (allClassesFiltered != null && filtered) {
146 return allClassesFiltered;
147 }
148 ListBuffer<ClassDocImpl> classes = new ListBuffer<ClassDocImpl>();
149 for (Scope.Entry e = sym.members().elems; e != null; e = e.sibling) {
150 if (e.sym != null) {
151 ClassSymbol s = (ClassSymbol)e.sym;
152 ClassDocImpl c = env.getClassDoc(s);
153 if (c != null && !c.isSynthetic())
154 c.addAllClasses(classes, filtered);
155 }
156 }
157 if (filtered)
158 return allClassesFiltered = classes.toList();
159 else
160 return allClasses = classes.toList();
161 }
163 /**
164 * Add all included classes (including Exceptions and Errors)
165 * and interfaces.
166 */
167 public void addAllClassesTo(ListBuffer<ClassDocImpl> list) {
168 list.appendList(getClasses(true));
169 }
171 /**
172 * Get all classes (including Exceptions and Errors)
173 * and interfaces.
174 * @since J2SE1.4.
175 *
176 * @return all classes and interfaces in this package, filtered to include
177 * only the included classes if filter==true.
178 */
179 public ClassDoc[] allClasses(boolean filter) {
180 List<ClassDocImpl> classes = getClasses(filter);
181 return classes.toArray(new ClassDocImpl[classes.length()]);
182 }
184 /**
185 * Get all included classes (including Exceptions and Errors)
186 * and interfaces. Same as allClasses(true).
187 *
188 * @return all included classes and interfaces in this package.
189 */
190 public ClassDoc[] allClasses() {
191 return allClasses(true);
192 }
194 /**
195 * Get ordinary classes (that is, exclude exceptions, errors,
196 * enums, interfaces, and annotation types) in this package.
197 *
198 * @return included ordinary classes in this package.
199 */
200 public ClassDoc[] ordinaryClasses() {
201 ListBuffer<ClassDocImpl> ret = new ListBuffer<ClassDocImpl>();
202 for (ClassDocImpl c : getClasses(true)) {
203 if (c.isOrdinaryClass()) {
204 ret.append(c);
205 }
206 }
207 return ret.toArray(new ClassDocImpl[ret.length()]);
208 }
210 /**
211 * Get Exception classes in this package.
212 *
213 * @return included Exceptions in this package.
214 */
215 public ClassDoc[] exceptions() {
216 ListBuffer<ClassDocImpl> ret = new ListBuffer<ClassDocImpl>();
217 for (ClassDocImpl c : getClasses(true)) {
218 if (c.isException()) {
219 ret.append(c);
220 }
221 }
222 return ret.toArray(new ClassDocImpl[ret.length()]);
223 }
225 /**
226 * Get Error classes in this package.
227 *
228 * @return included Errors in this package.
229 */
230 public ClassDoc[] errors() {
231 ListBuffer<ClassDocImpl> ret = new ListBuffer<ClassDocImpl>();
232 for (ClassDocImpl c : getClasses(true)) {
233 if (c.isError()) {
234 ret.append(c);
235 }
236 }
237 return ret.toArray(new ClassDocImpl[ret.length()]);
238 }
240 /**
241 * Get included enum types in this package.
242 *
243 * @return included enum types in this package.
244 */
245 public ClassDoc[] enums() {
246 ListBuffer<ClassDocImpl> ret = new ListBuffer<ClassDocImpl>();
247 for (ClassDocImpl c : getClasses(true)) {
248 if (c.isEnum()) {
249 ret.append(c);
250 }
251 }
252 return ret.toArray(new ClassDocImpl[ret.length()]);
253 }
255 /**
256 * Get included interfaces in this package, omitting annotation types.
257 *
258 * @return included interfaces in this package.
259 */
260 public ClassDoc[] interfaces() {
261 ListBuffer<ClassDocImpl> ret = new ListBuffer<ClassDocImpl>();
262 for (ClassDocImpl c : getClasses(true)) {
263 if (c.isInterface()) {
264 ret.append(c);
265 }
266 }
267 return ret.toArray(new ClassDocImpl[ret.length()]);
268 }
270 /**
271 * Get included annotation types in this package.
272 *
273 * @return included annotation types in this package.
274 */
275 public AnnotationTypeDoc[] annotationTypes() {
276 ListBuffer<AnnotationTypeDocImpl> ret =
277 new ListBuffer<AnnotationTypeDocImpl>();
278 for (ClassDocImpl c : getClasses(true)) {
279 if (c.isAnnotationType()) {
280 ret.append((AnnotationTypeDocImpl)c);
281 }
282 }
283 return ret.toArray(new AnnotationTypeDocImpl[ret.length()]);
284 }
286 /**
287 * Get the annotations of this package.
288 * Return an empty array if there are none.
289 */
290 public AnnotationDesc[] annotations() {
291 AnnotationDesc res[] = new AnnotationDesc[sym.getRawAttributes().length()];
292 int i = 0;
293 for (Attribute.Compound a : sym.getRawAttributes()) {
294 res[i++] = new AnnotationDescImpl(env, a);
295 }
296 return res;
297 }
300 /**
301 * Lookup for a class within this package.
302 *
303 * @return ClassDocImpl of found class, or null if not found.
304 */
305 public ClassDoc findClass(String className) {
306 final boolean filtered = true;
307 for (ClassDocImpl c : getClasses(filtered)) {
308 if (c.name().equals(className)) {
309 return c;
310 }
311 }
312 return null;
313 }
315 /**
316 * Return true if this package is included in the active set.
317 */
318 public boolean isIncluded() {
319 return isIncluded;
320 }
322 /**
323 * Get package name.
324 *
325 * Note that we do not provide a means of obtaining the simple
326 * name of a package -- package names are always returned in their
327 * uniquely qualified form.
328 */
329 public String name() {
330 return qualifiedName();
331 }
333 /**
334 * Get package name.
335 */
336 public String qualifiedName() {
337 if (qualifiedName == null) {
338 Name fullname = sym.getQualifiedName();
339 // Some bogus tests depend on the interned "" being returned.
340 // See 6457276.
341 qualifiedName = fullname.isEmpty() ? "" : fullname.toString();
342 }
343 return qualifiedName;
344 }
346 private String qualifiedName;
348 /**
349 * set doc path for an unzipped directory
350 */
351 public void setDocPath(FileObject path) {
352 setDocPath = true;
353 if (path == null)
354 return;
355 if (!path.equals(docPath)) {
356 docPath = path;
357 checkDoc();
358 }
359 }
361 // Has checkDoc() sounded off yet?
362 private boolean checkDocWarningEmitted = false;
364 /**
365 * Invoked when a source of package doc comments is located.
366 * Emits a diagnostic if this is the second one.
367 */
368 private void checkDoc() {
369 if (foundDoc) {
370 if (!checkDocWarningEmitted) {
371 env.warning(null, "javadoc.Multiple_package_comments", name());
372 checkDocWarningEmitted = true;
373 }
374 } else {
375 foundDoc = true;
376 }
377 }
379 /**
380 * Return the source position of the entity, or null if
381 * no position is available.
382 */
383 public SourcePosition position() {
384 return (tree != null)
385 ? SourcePositionImpl.make(tree.sourcefile, tree.pos, tree.lineMap)
386 : SourcePositionImpl.make(docPath, Position.NOPOS, null);
387 }
388 }