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