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.DataInputStream; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.text.CollationKey; 32 import java.util.regex.Matcher; 33 import java.util.regex.Pattern; 34 35 import javax.tools.FileObject; 36 37 import com.sun.javadoc.*; 38 import com.sun.source.util.TreePath; 39 import com.sun.tools.javac.tree.JCTree; 40 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 41 import com.sun.tools.javac.util.Position; 42 43 /** 44 * abstract base class of all Doc classes. Doc item's are representations 45 * of java language constructs (class, package, method,...) which have 46 * comments and have been processed by this run of javadoc. All Doc items 47 * are unique, that is, they are == comparable. 48 * 49 * <p><b>This is NOT part of any supported API. 50 * If you write code that depends on this, you do so at your own risk. 51 * This code and its internal interfaces are subject to change or 52 * deletion without notice.</b> 53 * 54 * @since 1.2 55 * @author Robert Field 56 * @author Atul M Dambalkar 57 * @author Neal Gafter (rewrite) 58 */ 59 @Deprecated(since="9", forRemoval=true) 60 @SuppressWarnings("removal") 61 public abstract class DocImpl implements Doc, Comparable<Object> { 62 63 /** 64 * Doc environment 65 */ 66 protected final DocEnv env; //### Rename this everywhere to 'docenv' ? 67 68 /** 69 * Back pointer to the tree node for this doc item. 70 * May be null if there is no associated tree. 71 */ 72 protected TreePath treePath; 73 74 /** 75 * The complex comment object, lazily initialized. 76 */ 77 private Comment comment; 78 79 /** 80 * The cached sort key, to take care of Natural Language Text sorting. 81 */ 82 private CollationKey collationkey = null; 83 84 /** 85 * Raw documentation string. 86 */ 87 protected String documentation; // Accessed in PackageDocImpl, RootDocImpl 88 89 /** 90 * Cached first sentence. 91 */ 92 private Tag[] firstSentence; 93 94 /** 95 * Cached inline tags. 96 */ 97 private Tag[] inlineTags; 98 99 /** 100 * Constructor. 101 */ DocImpl(DocEnv env, TreePath treePath)102 DocImpl(DocEnv env, TreePath treePath) { 103 this.treePath = treePath; 104 this.documentation = getCommentText(treePath); 105 this.env = env; 106 } 107 getCommentText(TreePath p)108 private static String getCommentText(TreePath p) { 109 if (p == null) 110 return null; 111 112 JCCompilationUnit topLevel = (JCCompilationUnit) p.getCompilationUnit(); 113 JCTree tree = (JCTree) p.getLeaf(); 114 return topLevel.docComments.getCommentText(tree); 115 } 116 117 /** 118 * So subclasses have the option to do lazy initialization of 119 * "documentation" string. 120 */ documentation()121 protected String documentation() { 122 if (documentation == null) documentation = ""; 123 return documentation; 124 } 125 126 /** 127 * For lazy initialization of comment. 128 */ comment()129 Comment comment() { 130 if (comment == null) { 131 String d = documentation(); 132 if (env.javaScriptScanner != null) { 133 env.javaScriptScanner.parse(d, new JavaScriptScanner.Reporter() { 134 @Override 135 public void report() { 136 env.error(DocImpl.this, "javadoc.JavaScript_in_comment"); 137 throw new Error(); 138 } 139 }); 140 } 141 if (env.doclint != null 142 && treePath != null 143 && env.shouldCheck(treePath.getCompilationUnit()) 144 && d.equals(getCommentText(treePath))) { 145 env.doclint.scan(treePath); 146 } 147 comment = new Comment(this, d); 148 } 149 return comment; 150 } 151 152 /** 153 * Return the text of the comment for this doc item. 154 * TagImpls have been removed. 155 */ commentText()156 public String commentText() { 157 return comment().commentText(); 158 } 159 160 /** 161 * Return all tags in this Doc item. 162 * 163 * @return an array of TagImpl containing all tags on this Doc item. 164 */ tags()165 public Tag[] tags() { 166 return comment().tags(); 167 } 168 169 /** 170 * Return tags of the specified kind in this Doc item. 171 * 172 * @param tagname name of the tag kind to search for. 173 * @return an array of TagImpl containing all tags whose 'kind()' 174 * matches 'tagname'. 175 */ tags(String tagname)176 public Tag[] tags(String tagname) { 177 return comment().tags(tagname); 178 } 179 180 /** 181 * Return the see also tags in this Doc item. 182 * 183 * @return an array of SeeTag containing all @see tags. 184 */ seeTags()185 public SeeTag[] seeTags() { 186 return comment().seeTags(); 187 } 188 inlineTags()189 public Tag[] inlineTags() { 190 if (inlineTags == null) { 191 inlineTags = Comment.getInlineTags(this, commentText()); 192 } 193 return inlineTags; 194 } 195 firstSentenceTags()196 public Tag[] firstSentenceTags() { 197 if (firstSentence == null) { 198 //Parse all sentences first to avoid duplicate warnings. 199 inlineTags(); 200 try { 201 env.setSilent(true); 202 firstSentence = Comment.firstSentenceTags(this, commentText()); 203 } finally { 204 env.setSilent(false); 205 } 206 } 207 return firstSentence; 208 } 209 210 /** 211 * Utility for subclasses which read HTML documentation files. 212 */ readHTMLDocumentation(InputStream input, FileObject filename)213 String readHTMLDocumentation(InputStream input, FileObject filename) throws IOException { 214 byte[] filecontents = new byte[input.available()]; 215 try { 216 DataInputStream dataIn = new DataInputStream(input); 217 dataIn.readFully(filecontents); 218 } finally { 219 input.close(); 220 } 221 String encoding = env.getEncoding(); 222 String rawDoc = (encoding!=null) 223 ? new String(filecontents, encoding) 224 : new String(filecontents); 225 Pattern bodyPat = Pattern.compile("(?is).*<body\\b[^>]*>(.*)</body\\b.*"); 226 Matcher m = bodyPat.matcher(rawDoc); 227 if (m.matches()) { 228 return m.group(1); 229 } else { 230 String key = rawDoc.matches("(?is).*<body\\b.*") 231 ? "javadoc.End_body_missing_from_html_file" 232 : "javadoc.Body_missing_from_html_file"; 233 env.error(SourcePositionImpl.make(filename, Position.NOPOS, null), key); 234 return ""; 235 } 236 } 237 238 /** 239 * Return the full unprocessed text of the comment. Tags 240 * are included as text. Used mainly for store and retrieve 241 * operations like internalization. 242 */ getRawCommentText()243 public String getRawCommentText() { 244 return documentation(); 245 } 246 247 /** 248 * Set the full unprocessed text of the comment. Tags 249 * are included as text. Used mainly for store and retrieve 250 * operations like internalization. 251 */ setRawCommentText(String rawDocumentation)252 public void setRawCommentText(String rawDocumentation) { 253 treePath = null; 254 documentation = rawDocumentation; 255 comment = null; 256 } 257 258 /** 259 * Set the full unprocessed text of the comment and tree path. 260 */ setTreePath(TreePath treePath)261 void setTreePath(TreePath treePath) { 262 this.treePath = treePath; 263 documentation = getCommentText(treePath); 264 comment = null; 265 } 266 267 /** 268 * return a key for sorting. 269 */ key()270 CollationKey key() { 271 if (collationkey == null) { 272 collationkey = generateKey(); 273 } 274 return collationkey; 275 } 276 277 /** 278 * Generate a key for sorting. 279 * <p> 280 * Default is name(). 281 */ generateKey()282 CollationKey generateKey() { 283 String k = name(); 284 // System.out.println("COLLATION KEY FOR " + this + " is \"" + k + "\""); 285 return env.doclocale.collator.getCollationKey(k); 286 } 287 288 /** 289 * Returns a string representation of this Doc item. 290 */ 291 @Override toString()292 public String toString() { 293 return qualifiedName(); 294 } 295 296 /** 297 * Returns the name of this Doc item. 298 * 299 * @return the name 300 */ name()301 public abstract String name(); 302 303 /** 304 * Returns the qualified name of this Doc item. 305 * 306 * @return the name 307 */ qualifiedName()308 public abstract String qualifiedName(); 309 310 /** 311 * Compares this Object with the specified Object for order. Returns a 312 * negative integer, zero, or a positive integer as this Object is less 313 * than, equal to, or greater than the given Object. 314 * <p> 315 * Included so that Doc item are java.lang.Comparable. 316 * 317 * @param obj the {@code Object} to be compared. 318 * @return a negative integer, zero, or a positive integer as this Object 319 * is less than, equal to, or greater than the given Object. 320 * @exception ClassCastException the specified Object's type prevents it 321 * from being compared to this Object. 322 */ compareTo(Object obj)323 public int compareTo(Object obj) { 324 // System.out.println("COMPARE \"" + this + "\" to \"" + obj + "\" = " + key().compareTo(((DocImpl)obj).key())); 325 return key().compareTo(((DocImpl)obj).key()); 326 } 327 328 /** 329 * Is this Doc item a field? False until overridden. 330 * 331 * @return true if it represents a field 332 */ isField()333 public boolean isField() { 334 return false; 335 } 336 337 /** 338 * Is this Doc item an enum constant? False until overridden. 339 * 340 * @return true if it represents an enum constant 341 */ isEnumConstant()342 public boolean isEnumConstant() { 343 return false; 344 } 345 346 /** 347 * Is this Doc item a constructor? False until overridden. 348 * 349 * @return true if it represents a constructor 350 */ isConstructor()351 public boolean isConstructor() { 352 return false; 353 } 354 355 /** 356 * Is this Doc item a method (but not a constructor or annotation 357 * type element)? 358 * False until overridden. 359 * 360 * @return true if it represents a method 361 */ isMethod()362 public boolean isMethod() { 363 return false; 364 } 365 366 /** 367 * Is this Doc item an annotation type element? 368 * False until overridden. 369 * 370 * @return true if it represents an annotation type element 371 */ isAnnotationTypeElement()372 public boolean isAnnotationTypeElement() { 373 return false; 374 } 375 376 /** 377 * Is this Doc item a interface (but not an annotation type)? 378 * False until overridden. 379 * 380 * @return true if it represents a interface 381 */ isInterface()382 public boolean isInterface() { 383 return false; 384 } 385 386 /** 387 * Is this Doc item a exception class? False until overridden. 388 * 389 * @return true if it represents a exception 390 */ isException()391 public boolean isException() { 392 return false; 393 } 394 395 /** 396 * Is this Doc item a error class? False until overridden. 397 * 398 * @return true if it represents a error 399 */ isError()400 public boolean isError() { 401 return false; 402 } 403 404 /** 405 * Is this Doc item an enum type? False until overridden. 406 * 407 * @return true if it represents an enum type 408 */ isEnum()409 public boolean isEnum() { 410 return false; 411 } 412 413 /** 414 * Is this Doc item an annotation type? False until overridden. 415 * 416 * @return true if it represents an annotation type 417 */ isAnnotationType()418 public boolean isAnnotationType() { 419 return false; 420 } 421 422 /** 423 * Is this Doc item an ordinary class (i.e. not an interface, 424 * annotation type, enumeration, exception, or error)? 425 * False until overridden. 426 * 427 * @return true if it represents an ordinary class 428 */ isOrdinaryClass()429 public boolean isOrdinaryClass() { 430 return false; 431 } 432 433 /** 434 * Is this Doc item a class 435 * (and not an interface or annotation type)? 436 * This includes ordinary classes, enums, errors and exceptions. 437 * False until overridden. 438 * 439 * @return true if it represents a class 440 */ isClass()441 public boolean isClass() { 442 return false; 443 } 444 445 /** 446 * return true if this Doc is include in the active set. 447 */ isIncluded()448 public abstract boolean isIncluded(); 449 450 /** 451 * Return the source position of the entity, or null if 452 * no position is available. 453 */ position()454 public SourcePosition position() { return null; } 455 } 456