DocEnv.java revision 3896:8e4dbcb99277
1104477Ssam/* 2104477Ssam * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. 3104477Ssam * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4139749Simp * 5104477Ssam * This code is free software; you can redistribute it and/or modify it 6104477Ssam * under the terms of the GNU General Public License version 2 only, as 7104477Ssam * published by the Free Software Foundation. Oracle designates this 8104477Ssam * particular file as subject to the "Classpath" exception as provided 9104477Ssam * by Oracle in the LICENSE file that accompanied this code. 10104477Ssam * 11104477Ssam * This code is distributed in the hope that it will be useful, but WITHOUT 12104477Ssam * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13104477Ssam * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14104477Ssam * version 2 for more details (a copy is included in the LICENSE file that 15104477Ssam * accompanied this code). 16104477Ssam * 17104477Ssam * You should have received a copy of the GNU General Public License version 18104477Ssam * 2 along with this work; if not, write to the Free Software Foundation, 19104477Ssam * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20104477Ssam * 21104477Ssam * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22104477Ssam * or visit www.oracle.com if you need additional information or have any 23104477Ssam * questions. 24104477Ssam */ 25104477Ssam 26104477Ssampackage com.sun.tools.javadoc.main; 27104477Ssam 28104477Ssamimport java.lang.reflect.Modifier; 29104477Ssamimport java.util.*; 30104477Ssam 31104477Ssamimport javax.tools.JavaFileManager; 32104477Ssam 33104477Ssamimport com.sun.javadoc.*; 34104477Ssamimport com.sun.source.tree.CompilationUnitTree; 35104477Ssamimport com.sun.source.util.JavacTask; 36104477Ssamimport com.sun.source.util.TreePath; 37104477Ssamimport com.sun.tools.doclint.DocLint; 38104477Ssamimport com.sun.tools.javac.api.BasicJavacTask; 39104477Ssamimport com.sun.tools.javac.code.*; 40104477Ssamimport com.sun.tools.javac.code.Symbol.*; 41104477Ssamimport com.sun.tools.javac.code.Symbol.ClassSymbol; 42104477Ssamimport com.sun.tools.javac.code.Symbol.CompletionFailure; 43104477Ssamimport com.sun.tools.javac.code.Symbol.MethodSymbol; 44104477Ssamimport com.sun.tools.javac.code.Symbol.PackageSymbol; 45104477Ssamimport com.sun.tools.javac.code.Symbol.VarSymbol; 46104477Ssamimport com.sun.tools.javac.code.Type.ClassType; 47104477Ssamimport com.sun.tools.javac.comp.Check; 48104477Ssamimport com.sun.tools.javac.comp.Enter; 49104477Ssamimport com.sun.tools.javac.file.JavacFileManager; 50104477Ssamimport com.sun.tools.javac.tree.JCTree; 51104477Ssamimport com.sun.tools.javac.tree.JCTree.JCClassDecl; 52104477Ssamimport com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 53104477Ssamimport com.sun.tools.javac.tree.JCTree.JCPackageDecl; 54104477Ssamimport com.sun.tools.javac.util.Context; 55104477Ssamimport com.sun.tools.javac.util.Convert; 56104477Ssamimport com.sun.tools.javac.util.Name; 57104477Ssamimport com.sun.tools.javac.util.Names; 58104477Ssam 59104477Ssam/** 60104477Ssam * Holds the environment for a run of javadoc. 61104477Ssam * Holds only the information needed throughout the 62104477Ssam * run and not the compiler info that could be GC'ed 63104477Ssam * or ported. 64104477Ssam * 65104477Ssam * <p><b>This is NOT part of any supported API. 66104477Ssam * If you write code that depends on this, you do so at your own risk. 67104477Ssam * This code and its internal interfaces are subject to change or 68104477Ssam * deletion without notice.</b> 69104477Ssam * 70120915Ssam * @since 1.4 71120915Ssam * @author Robert Field 72104477Ssam * @author Neal Gafter (rewrite) 73104477Ssam * @author Scott Seligman (generics) 74104477Ssam */ 75104477Ssam@Deprecated 76104477Ssampublic class DocEnv { 77104477Ssam protected static final Context.Key<DocEnv> docEnvKey = new Context.Key<>(); 78104477Ssam 79104477Ssam public static DocEnv instance(Context context) { 80104477Ssam DocEnv instance = context.get(docEnvKey); 81104477Ssam if (instance == null) 82104477Ssam instance = new DocEnv(context); 83104477Ssam return instance; 84213091Sgonzo } 85213091Sgonzo 86104477Ssam DocLocale doclocale; 87104477Ssam 88104477Ssam private final Messager messager; 89104477Ssam 90104477Ssam /** Predefined symbols known to the compiler. */ 91104477Ssam final Symtab syms; 92104477Ssam 93104477Ssam /** Referenced directly in RootDocImpl. */ 94104477Ssam private final ClassFinder finder; 95104477Ssam 96104477Ssam /** Javadoc's own version of the compiler's enter phase. */ 97104477Ssam final Enter enter; 98104477Ssam 99104477Ssam /** The name table. */ 100104477Ssam private final Names names; 101104477Ssam 102213091Sgonzo /** The encoding name. */ 103104477Ssam private String encoding; 104104477Ssam 105104477Ssam final Symbol externalizableSym; 106136526Ssam 107158705Spjd /** Access filter (public, protected, ...). */ 108120915Ssam protected ModifierFilter showAccess; 109104477Ssam 110104477Ssam /** True if we are using a sentence BreakIterator. */ 111104477Ssam boolean breakiterator; 112104477Ssam 113104477Ssam /** 114104477Ssam * True if we do not want to print any notifications at all. 115104477Ssam */ 116104477Ssam boolean quiet = false; 117104477Ssam 118104477Ssam Check chk; 119104477Ssam Types types; 120104477Ssam JavaFileManager fileManager; 121104477Ssam Context context; 122104477Ssam DocLint doclint; 123104477Ssam JavaScriptScanner javaScriptScanner; 124104477Ssam 125104477Ssam WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<>(); 126104477Ssam 127104477Ssam /** Allow documenting from class files? */ 128104477Ssam boolean docClasses = false; 129104477Ssam 130104477Ssam /** Does the doclet only expect pre-1.5 doclet API? */ 131104477Ssam protected boolean legacyDoclet = true; 132104477Ssam 133104477Ssam /** 134104477Ssam * Set this to true if you would like to not emit any errors, warnings and 135104477Ssam * notices. 136104477Ssam */ 137104477Ssam private boolean silent = false; 138104477Ssam 139104477Ssam /** 140104477Ssam * The source language version. 141104477Ssam */ 142104477Ssam protected Source source; 143104477Ssam 144104477Ssam /** 145140480Ssam * Constructor 146104477Ssam * 147104477Ssam * @param context Context for this javadoc instance. 148104477Ssam */ 149104477Ssam protected DocEnv(Context context) { 150104477Ssam context.put(docEnvKey, this); 151104477Ssam this.context = context; 152213091Sgonzo 153213091Sgonzo messager = Messager.instance0(context); 154213091Sgonzo syms = Symtab.instance(context); 155213091Sgonzo finder = JavadocClassFinder.instance(context); 156213091Sgonzo enter = JavadocEnter.instance(context); 157213091Sgonzo names = Names.instance(context); 158213091Sgonzo externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable")); 159213091Sgonzo chk = Check.instance(context); 160213091Sgonzo types = Types.instance(context); 161104477Ssam fileManager = context.get(JavaFileManager.class); 162104477Ssam if (fileManager instanceof JavacFileManager) { 163136526Ssam ((JavacFileManager)fileManager).setSymbolFileEnabled(false); 164136526Ssam } 165104477Ssam 166104477Ssam // Default. Should normally be reset with setLocale. 167104477Ssam this.doclocale = new DocLocale(this, "", breakiterator); 168104477Ssam source = Source.instance(context); 169120915Ssam } 170120915Ssam 171120915Ssam public void setSilent(boolean silent) { 172104477Ssam this.silent = silent; 173104477Ssam } 174104477Ssam 175104477Ssam /** 176112124Ssam * Look up ClassDoc by qualified name. 177112124Ssam */ 178112124Ssam public ClassDocImpl lookupClass(String name) { 179104477Ssam ClassSymbol c = getClassSymbol(name); 180104477Ssam if (c != null) { 181104477Ssam return getClassDoc(c); 182104477Ssam } else { 183104477Ssam return null; 184104477Ssam } 185104477Ssam } 186104477Ssam 187167755Ssam /** 188167755Ssam * Load ClassDoc by qualified name. 189167755Ssam */ 190104477Ssam public ClassDocImpl loadClass(String name) { 191104477Ssam try { 192104477Ssam Name nameImpl = names.fromString(name); 193104477Ssam ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl)); 194104477Ssam ClassSymbol c = finder.loadClass(mod != null ? mod : syms.errModule, nameImpl); 195104477Ssam return getClassDoc(c); 196104477Ssam } catch (CompletionFailure ex) { 197104477Ssam chk.completionError(null, ex); 198104477Ssam return null; 199104477Ssam } 200104477Ssam } 201104477Ssam 202104477Ssam /** 203104477Ssam * Look up PackageDoc by qualified name. 204104477Ssam */ 205104477Ssam public PackageDocImpl lookupPackage(String name) { 206104477Ssam //### Jing alleges that class check is needed 207104477Ssam //### to avoid a compiler bug. Most likely 208104477Ssam //### instead a dummy created for error recovery. 209104477Ssam //### Should investigate this. 210104477Ssam Name nameImpl = names.fromString(name); 211104477Ssam ModuleSymbol mod = syms.inferModule(nameImpl); 212104477Ssam PackageSymbol p = mod != null ? syms.getPackage(mod, nameImpl) : null; 213104477Ssam ClassSymbol c = getClassSymbol(name); 214104477Ssam if (p != null && c == null) { 215104477Ssam return getPackageDoc(p); 216104477Ssam } else { 217104477Ssam return null; 218104477Ssam } 219104477Ssam } 220104477Ssam // where 221104477Ssam /** Retrieve class symbol by fully-qualified name. 222104477Ssam */ 223104477Ssam ClassSymbol getClassSymbol(String name) { 224104477Ssam // Name may contain nested class qualification. 225104477Ssam // Generate candidate flatnames with successively shorter 226104477Ssam // package qualifiers and longer nested class qualifiers. 227104477Ssam int nameLen = name.length(); 228104477Ssam char[] nameChars = name.toCharArray(); 229104477Ssam int idx = name.length(); 230104477Ssam for (;;) { 231104477Ssam Name nameImpl = names.fromChars(nameChars, 0, nameLen); 232104477Ssam ModuleSymbol mod = syms.inferModule(Convert.packagePart(nameImpl)); 233104477Ssam ClassSymbol s = mod != null ? syms.getClass(mod, nameImpl) : null; 234104477Ssam if (s != null) 235104477Ssam return s; // found it! 236104477Ssam idx = name.substring(0, idx).lastIndexOf('.'); 237104477Ssam if (idx < 0) break; 238104477Ssam nameChars[idx] = '$'; 239104477Ssam } 240104477Ssam return null; 241104477Ssam } 242104477Ssam 243104477Ssam /** 244104477Ssam * Set the locale. 245104477Ssam */ 246104477Ssam public void setLocale(String localeName) { 247104477Ssam // create locale specifics 248104477Ssam doclocale = new DocLocale(this, localeName, breakiterator); 249104477Ssam // update Messager if locale has changed. 250104477Ssam messager.setLocale(doclocale.locale); 251104477Ssam } 252104477Ssam 253104477Ssam /** Check whether this member should be documented. */ 254104477Ssam public boolean shouldDocument(VarSymbol sym) { 255104477Ssam long mod = sym.flags(); 256104477Ssam 257104477Ssam if ((mod & Flags.SYNTHETIC) != 0) { 258104477Ssam return false; 259104477Ssam } 260104477Ssam 261104477Ssam return showAccess.checkModifier(translateModifiers(mod)); 262104477Ssam } 263104477Ssam 264104477Ssam /** Check whether this member should be documented. */ 265104477Ssam public boolean shouldDocument(MethodSymbol sym) { 266104477Ssam long mod = sym.flags(); 267104477Ssam 268104477Ssam if ((mod & Flags.SYNTHETIC) != 0) { 269104477Ssam return false; 270104477Ssam } 271104477Ssam 272104477Ssam return showAccess.checkModifier(translateModifiers(mod)); 273120915Ssam } 274104477Ssam 275104477Ssam /** check whether this class should be documented. */ 276104477Ssam public boolean shouldDocument(ClassSymbol sym) { 277104477Ssam return 278104477Ssam (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics 279104477Ssam (docClasses || getClassDoc(sym).tree != null) && 280104477Ssam isVisible(sym); 281104477Ssam } 282104477Ssam 283104477Ssam //### Comment below is inaccurate wrt modifier filter testing 284104477Ssam /** 285104477Ssam * Check the visibility if this is an nested class. 286104477Ssam * if this is not a nested class, return true. 287104477Ssam * if this is an static visible nested class, 288104477Ssam * return true. 289104477Ssam * if this is an visible nested class 290104477Ssam * if the outer class is visible return true. 291104477Ssam * else return false. 292104477Ssam * IMPORTANT: This also allows, static nested classes 293104477Ssam * to be defined inside an nested class, which is not 294104477Ssam * allowed by the compiler. So such an test case will 295104477Ssam * not reach upto this method itself, but if compiler 296104477Ssam * allows it, then that will go through. 297104477Ssam */ 298104477Ssam protected boolean isVisible(ClassSymbol sym) { 299104477Ssam long mod = sym.flags_field; 300104477Ssam if (!showAccess.checkModifier(translateModifiers(mod))) { 301104477Ssam return false; 302104477Ssam } 303104477Ssam ClassSymbol encl = sym.owner.enclClass(); 304104477Ssam return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl)); 305104477Ssam } 306104477Ssam 307104477Ssam //---------------- print forwarders ----------------// 308104477Ssam 309104477Ssam /** 310104477Ssam * Print error message, increment error count. 311104477Ssam * 312104477Ssam * @param msg message to print. 313104477Ssam */ 314104477Ssam public void printError(String msg) { 315104477Ssam if (silent) 316104477Ssam return; 317104477Ssam messager.printError(msg); 318104477Ssam } 319104477Ssam 320104477Ssam /** 321104477Ssam * Print error message, increment error count. 322104477Ssam * 323104477Ssam * @param key selects message from resource 324104477Ssam */ 325104477Ssam public void error(DocImpl doc, String key) { 326104477Ssam if (silent) 327104477Ssam return; 328104477Ssam messager.error(doc==null ? null : doc.position(), key); 329104477Ssam } 330104477Ssam 331104477Ssam /** 332104477Ssam * Print error message, increment error count. 333104477Ssam * 334104477Ssam * @param key selects message from resource 335104477Ssam */ 336104477Ssam public void error(SourcePosition pos, String key) { 337104477Ssam if (silent) 338104477Ssam return; 339104477Ssam messager.error(pos, key); 340104477Ssam } 341104477Ssam 342104477Ssam /** 343104477Ssam * Print error message, increment error count. 344104477Ssam * 345104477Ssam * @param msg message to print. 346104477Ssam */ 347104477Ssam public void printError(SourcePosition pos, String msg) { 348104477Ssam if (silent) 349104477Ssam return; 350104477Ssam messager.printError(pos, msg); 351104477Ssam } 352104477Ssam 353104477Ssam /** 354104477Ssam * Print error message, increment error count. 355104477Ssam * 356104477Ssam * @param key selects message from resource 357104477Ssam * @param a1 first argument 358104477Ssam */ 359104477Ssam public void error(DocImpl doc, String key, String a1) { 360104477Ssam if (silent) 361104477Ssam return; 362104477Ssam messager.error(doc==null ? null : doc.position(), key, a1); 363104477Ssam } 364 365 /** 366 * Print error message, increment error count. 367 * 368 * @param key selects message from resource 369 * @param a1 first argument 370 * @param a2 second argument 371 */ 372 public void error(DocImpl doc, String key, String a1, String a2) { 373 if (silent) 374 return; 375 messager.error(doc==null ? null : doc.position(), key, a1, a2); 376 } 377 378 /** 379 * Print error message, increment error count. 380 * 381 * @param key selects message from resource 382 * @param a1 first argument 383 * @param a2 second argument 384 * @param a3 third argument 385 */ 386 public void error(DocImpl doc, String key, String a1, String a2, String a3) { 387 if (silent) 388 return; 389 messager.error(doc==null ? null : doc.position(), key, a1, a2, a3); 390 } 391 392 /** 393 * Print warning message, increment warning count. 394 * 395 * @param msg message to print. 396 */ 397 public void printWarning(String msg) { 398 if (silent) 399 return; 400 messager.printWarning(msg); 401 } 402 403 /** 404 * Print warning message, increment warning count. 405 * 406 * @param key selects message from resource 407 */ 408 public void warning(DocImpl doc, String key) { 409 if (silent) 410 return; 411 messager.warning(doc==null ? null : doc.position(), key); 412 } 413 414 /** 415 * Print warning message, increment warning count. 416 * 417 * @param msg message to print. 418 */ 419 public void printWarning(SourcePosition pos, String msg) { 420 if (silent) 421 return; 422 messager.printWarning(pos, msg); 423 } 424 425 /** 426 * Print warning message, increment warning count. 427 * 428 * @param key selects message from resource 429 * @param a1 first argument 430 */ 431 public void warning(DocImpl doc, String key, String a1) { 432 if (silent) 433 return; 434 // suppress messages that have (probably) been covered by doclint 435 if (doclint != null && doc != null && key.startsWith("tag")) 436 return; 437 messager.warning(doc==null ? null : doc.position(), key, a1); 438 } 439 440 /** 441 * Print warning message, increment warning count. 442 * 443 * @param key selects message from resource 444 * @param a1 first argument 445 * @param a2 second argument 446 */ 447 public void warning(DocImpl doc, String key, String a1, String a2) { 448 if (silent) 449 return; 450 messager.warning(doc==null ? null : doc.position(), key, a1, a2); 451 } 452 453 /** 454 * Print warning message, increment warning count. 455 * 456 * @param key selects message from resource 457 * @param a1 first argument 458 * @param a2 second argument 459 * @param a3 third argument 460 */ 461 public void warning(DocImpl doc, String key, String a1, String a2, String a3) { 462 if (silent) 463 return; 464 messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3); 465 } 466 467 /** 468 * Print warning message, increment warning count. 469 * 470 * @param key selects message from resource 471 * @param a1 first argument 472 * @param a2 second argument 473 * @param a3 third argument 474 */ 475 public void warning(DocImpl doc, String key, String a1, String a2, String a3, 476 String a4) { 477 if (silent) 478 return; 479 messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4); 480 } 481 482 /** 483 * Print a message. 484 * 485 * @param msg message to print. 486 */ 487 public void printNotice(String msg) { 488 if (silent || quiet) 489 return; 490 messager.printNotice(msg); 491 } 492 493 494 /** 495 * Print a message. 496 * 497 * @param key selects message from resource 498 */ 499 public void notice(String key) { 500 if (silent || quiet) 501 return; 502 messager.notice(key); 503 } 504 505 /** 506 * Print a message. 507 * 508 * @param msg message to print. 509 */ 510 public void printNotice(SourcePosition pos, String msg) { 511 if (silent || quiet) 512 return; 513 messager.printNotice(pos, msg); 514 } 515 516 /** 517 * Print a message. 518 * 519 * @param key selects message from resource 520 * @param a1 first argument 521 */ 522 public void notice(String key, String a1) { 523 if (silent || quiet) 524 return; 525 messager.notice(key, a1); 526 } 527 528 /** 529 * Print a message. 530 * 531 * @param key selects message from resource 532 * @param a1 first argument 533 * @param a2 second argument 534 */ 535 public void notice(String key, String a1, String a2) { 536 if (silent || quiet) 537 return; 538 messager.notice(key, a1, a2); 539 } 540 541 /** 542 * Print a message. 543 * 544 * @param key selects message from resource 545 * @param a1 first argument 546 * @param a2 second argument 547 * @param a3 third argument 548 */ 549 public void notice(String key, String a1, String a2, String a3) { 550 if (silent || quiet) 551 return; 552 messager.notice(key, a1, a2, a3); 553 } 554 555 /** 556 * Exit, reporting errors and warnings. 557 */ 558 public void exit() { 559 // Messager should be replaced by a more general 560 // compilation environment. This can probably 561 // subsume DocEnv as well. 562 messager.exit(); 563 } 564 565 protected Map<PackageSymbol, PackageDocImpl> packageMap = new HashMap<>(); 566 /** 567 * Return the PackageDoc of this package symbol. 568 */ 569 public PackageDocImpl getPackageDoc(PackageSymbol pack) { 570 PackageDocImpl result = packageMap.get(pack); 571 if (result != null) return result; 572 result = new PackageDocImpl(this, pack); 573 packageMap.put(pack, result); 574 return result; 575 } 576 577 /** 578 * Create the PackageDoc (or a subtype) for a package symbol. 579 */ 580 void makePackageDoc(PackageSymbol pack, TreePath treePath) { 581 PackageDocImpl result = packageMap.get(pack); 582 if (result != null) { 583 if (treePath != null) result.setTreePath(treePath); 584 } else { 585 result = new PackageDocImpl(this, pack, treePath); 586 packageMap.put(pack, result); 587 } 588 } 589 590 591 protected Map<ClassSymbol, ClassDocImpl> classMap = new HashMap<>(); 592 /** 593 * Return the ClassDoc (or a subtype) of this class symbol. 594 */ 595 public ClassDocImpl getClassDoc(ClassSymbol clazz) { 596 ClassDocImpl result = classMap.get(clazz); 597 if (result != null) return result; 598 if (isAnnotationType(clazz)) { 599 result = new AnnotationTypeDocImpl(this, clazz); 600 } else { 601 result = new ClassDocImpl(this, clazz); 602 } 603 classMap.put(clazz, result); 604 return result; 605 } 606 607 /** 608 * Create the ClassDoc (or a subtype) for a class symbol. 609 */ 610 protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) { 611 ClassDocImpl result = classMap.get(clazz); 612 if (result != null) { 613 if (treePath != null) result.setTreePath(treePath); 614 return; 615 } 616 if (isAnnotationType((JCClassDecl) treePath.getLeaf())) { // flags of clazz may not yet be set 617 result = new AnnotationTypeDocImpl(this, clazz, treePath); 618 } else { 619 result = new ClassDocImpl(this, clazz, treePath); 620 } 621 classMap.put(clazz, result); 622 } 623 624 protected static boolean isAnnotationType(ClassSymbol clazz) { 625 return ClassDocImpl.isAnnotationType(clazz); 626 } 627 628 protected static boolean isAnnotationType(JCClassDecl tree) { 629 return (tree.mods.flags & Flags.ANNOTATION) != 0; 630 } 631 632 protected Map<VarSymbol, FieldDocImpl> fieldMap = new HashMap<>(); 633 /** 634 * Return the FieldDoc of this var symbol. 635 */ 636 public FieldDocImpl getFieldDoc(VarSymbol var) { 637 FieldDocImpl result = fieldMap.get(var); 638 if (result != null) return result; 639 result = new FieldDocImpl(this, var); 640 fieldMap.put(var, result); 641 return result; 642 } 643 /** 644 * Create a FieldDoc for a var symbol. 645 */ 646 protected void makeFieldDoc(VarSymbol var, TreePath treePath) { 647 FieldDocImpl result = fieldMap.get(var); 648 if (result != null) { 649 if (treePath != null) result.setTreePath(treePath); 650 } else { 651 result = new FieldDocImpl(this, var, treePath); 652 fieldMap.put(var, result); 653 } 654 } 655 656 protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap = new HashMap<>(); 657 /** 658 * Create a MethodDoc for this MethodSymbol. 659 * Should be called only on symbols representing methods. 660 */ 661 protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) { 662 MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); 663 if (result != null) { 664 if (treePath != null) result.setTreePath(treePath); 665 } else { 666 result = new MethodDocImpl(this, meth, treePath); 667 methodMap.put(meth, result); 668 } 669 } 670 671 /** 672 * Return the MethodDoc for a MethodSymbol. 673 * Should be called only on symbols representing methods. 674 */ 675 public MethodDocImpl getMethodDoc(MethodSymbol meth) { 676 assert !meth.isConstructor() : "not expecting a constructor symbol"; 677 MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); 678 if (result != null) return result; 679 result = new MethodDocImpl(this, meth); 680 methodMap.put(meth, result); 681 return result; 682 } 683 684 /** 685 * Create the ConstructorDoc for a MethodSymbol. 686 * Should be called only on symbols representing constructors. 687 */ 688 protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) { 689 ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); 690 if (result != null) { 691 if (treePath != null) result.setTreePath(treePath); 692 } else { 693 result = new ConstructorDocImpl(this, meth, treePath); 694 methodMap.put(meth, result); 695 } 696 } 697 698 /** 699 * Return the ConstructorDoc for a MethodSymbol. 700 * Should be called only on symbols representing constructors. 701 */ 702 public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) { 703 assert meth.isConstructor() : "expecting a constructor symbol"; 704 ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); 705 if (result != null) return result; 706 result = new ConstructorDocImpl(this, meth); 707 methodMap.put(meth, result); 708 return result; 709 } 710 711 /** 712 * Create the AnnotationTypeElementDoc for a MethodSymbol. 713 * Should be called only on symbols representing annotation type elements. 714 */ 715 protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) { 716 AnnotationTypeElementDocImpl result = 717 (AnnotationTypeElementDocImpl)methodMap.get(meth); 718 if (result != null) { 719 if (treePath != null) result.setTreePath(treePath); 720 } else { 721 result = 722 new AnnotationTypeElementDocImpl(this, meth, treePath); 723 methodMap.put(meth, result); 724 } 725 } 726 727 /** 728 * Return the AnnotationTypeElementDoc for a MethodSymbol. 729 * Should be called only on symbols representing annotation type elements. 730 */ 731 public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc( 732 MethodSymbol meth) { 733 734 AnnotationTypeElementDocImpl result = 735 (AnnotationTypeElementDocImpl)methodMap.get(meth); 736 if (result != null) return result; 737 result = new AnnotationTypeElementDocImpl(this, meth); 738 methodMap.put(meth, result); 739 return result; 740 } 741 742// private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap = 743// new HashMap<ClassType, ParameterizedTypeImpl>(); 744 /** 745 * Return the ParameterizedType of this instantiation. 746// * ### Could use Type.sameTypeAs() instead of equality matching in hashmap 747// * ### to avoid some duplication. 748 */ 749 ParameterizedTypeImpl getParameterizedType(ClassType t) { 750 return new ParameterizedTypeImpl(this, t); 751// ParameterizedTypeImpl result = parameterizedTypeMap.get(t); 752// if (result != null) return result; 753// result = new ParameterizedTypeImpl(this, t); 754// parameterizedTypeMap.put(t, result); 755// return result; 756 } 757 758 TreePath getTreePath(JCCompilationUnit tree) { 759 TreePath p = treePaths.get(tree); 760 if (p == null) 761 treePaths.put(tree, p = new TreePath(tree)); 762 return p; 763 } 764 765 TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) { 766 TreePath p = treePaths.get(tree); 767 if (p == null) 768 treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); 769 return p; 770 } 771 772 TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) { 773 TreePath p = treePaths.get(tree); 774 if (p == null) 775 treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); 776 return p; 777 } 778 779 TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) { 780 return new TreePath(getTreePath(toplevel, cdecl), tree); 781 } 782 783 /** 784 * Set the encoding. 785 */ 786 public void setEncoding(String encoding) { 787 this.encoding = encoding; 788 } 789 790 /** 791 * Get the encoding. 792 */ 793 public String getEncoding() { 794 return encoding; 795 } 796 797 /** 798 * Convert modifier bits from private coding used by 799 * the compiler to that of java.lang.reflect.Modifier. 800 */ 801 static int translateModifiers(long flags) { 802 int result = 0; 803 if ((flags & Flags.ABSTRACT) != 0) 804 result |= Modifier.ABSTRACT; 805 if ((flags & Flags.FINAL) != 0) 806 result |= Modifier.FINAL; 807 if ((flags & Flags.INTERFACE) != 0) 808 result |= Modifier.INTERFACE; 809 if ((flags & Flags.NATIVE) != 0) 810 result |= Modifier.NATIVE; 811 if ((flags & Flags.PRIVATE) != 0) 812 result |= Modifier.PRIVATE; 813 if ((flags & Flags.PROTECTED) != 0) 814 result |= Modifier.PROTECTED; 815 if ((flags & Flags.PUBLIC) != 0) 816 result |= Modifier.PUBLIC; 817 if ((flags & Flags.STATIC) != 0) 818 result |= Modifier.STATIC; 819 if ((flags & Flags.SYNCHRONIZED) != 0) 820 result |= Modifier.SYNCHRONIZED; 821 if ((flags & Flags.TRANSIENT) != 0) 822 result |= Modifier.TRANSIENT; 823 if ((flags & Flags.VOLATILE) != 0) 824 result |= Modifier.VOLATILE; 825 return result; 826 } 827 828 void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) { 829 ArrayList<String> doclintOpts = new ArrayList<>(); 830 boolean msgOptionSeen = false; 831 832 for (String opt : opts) { 833 if (opt.startsWith(DocLint.XMSGS_OPTION)) { 834 if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) 835 return; 836 msgOptionSeen = true; 837 } 838 doclintOpts.add(opt); 839 } 840 841 if (!msgOptionSeen) { 842 doclintOpts.add(DocLint.XMSGS_OPTION); 843 } 844 845 String sep = ""; 846 StringBuilder customTags = new StringBuilder(); 847 for (String customTag : customTagNames) { 848 customTags.append(sep); 849 customTags.append(customTag); 850 sep = DocLint.SEPARATOR; 851 } 852 doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString()); 853 doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + htmlVersion); 854 855 JavacTask t = BasicJavacTask.instance(context); 856 doclint = new DocLint(); 857 // standard doclet normally generates H1, H2 858 doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2"); 859 doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false); 860 } 861 862 JavaScriptScanner initJavaScriptScanner(boolean allowScriptInComments) { 863 if (allowScriptInComments) { 864 javaScriptScanner = null; 865 } else { 866 javaScriptScanner = new JavaScriptScanner(); 867 } 868 return javaScriptScanner; 869 } 870 871 boolean showTagMessages() { 872 return (doclint == null); 873 } 874 875 Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>(); 876 877 boolean shouldCheck(CompilationUnitTree unit) { 878 return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck); 879 } 880} 881