1 /* 2 * Copyright (c) 2000, 2015, 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; 27 28 import java.lang.reflect.Modifier; 29 import java.util.*; 30 31 import javax.tools.JavaFileManager; 32 33 import com.sun.javadoc.*; 34 import com.sun.source.tree.CompilationUnitTree; 35 import com.sun.source.util.JavacTask; 36 import com.sun.source.util.TreePath; 37 import com.sun.tools.doclint.DocLint; 38 import com.sun.tools.javac.api.BasicJavacTask; 39 import com.sun.tools.javac.code.*; 40 import com.sun.tools.javac.code.Symbol.*; 41 import com.sun.tools.javac.code.Symbol.ClassSymbol; 42 import com.sun.tools.javac.code.Symbol.CompletionFailure; 43 import com.sun.tools.javac.code.Symbol.MethodSymbol; 44 import com.sun.tools.javac.code.Symbol.PackageSymbol; 45 import com.sun.tools.javac.code.Symbol.VarSymbol; 46 import com.sun.tools.javac.code.Type.ClassType; 47 import com.sun.tools.javac.comp.Check; 48 import com.sun.tools.javac.comp.Enter; 49 import com.sun.tools.javac.file.JavacFileManager; 50 import com.sun.tools.javac.tree.JCTree; 51 import com.sun.tools.javac.tree.JCTree.JCClassDecl; 52 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 53 import com.sun.tools.javac.tree.JCTree.JCPackageDecl; 54 import com.sun.tools.javac.util.Context; 55 import com.sun.tools.javac.util.Names; 56 57 /** 58 * Holds the environment for a run of javadoc. 59 * Holds only the information needed throughout the 60 * run and not the compiler info that could be GC'ed 61 * or ported. 62 * 63 * <p><b>This is NOT part of any supported API. 64 * If you write code that depends on this, you do so at your own risk. 65 * This code and its internal interfaces are subject to change or 66 * deletion without notice.</b> 67 * 68 * @since 1.4 69 * @author Robert Field 70 * @author Neal Gafter (rewrite) 71 * @author Scott Seligman (generics) 72 */ 73 public class DocEnv { 74 protected static final Context.Key<DocEnv> docEnvKey = new Context.Key<>(); 75 76 public static DocEnv instance(Context context) { 77 DocEnv instance = context.get(docEnvKey); 78 if (instance == null) 79 instance = new DocEnv(context); 80 return instance; 81 } 82 83 DocLocale doclocale; 84 85 private final Messager messager; 86 87 /** Predefined symbols known to the compiler. */ 88 final Symtab syms; 89 90 /** Referenced directly in RootDocImpl. */ 91 private final ClassFinder finder; 92 93 /** Javadoc's own version of the compiler's enter phase. */ 94 final Enter enter; 95 96 /** The name table. */ 97 private Names names; 98 99 /** The encoding name. */ 100 private String encoding; 101 102 final Symbol externalizableSym; 103 104 /** Access filter (public, protected, ...). */ 105 protected ModifierFilter showAccess; 106 107 /** True if we are using a sentence BreakIterator. */ 108 boolean breakiterator; 109 110 /** 111 * True if we do not want to print any notifications at all. 112 */ 113 boolean quiet = false; 114 115 Check chk; 116 Types types; 117 JavaFileManager fileManager; 118 Context context; 119 DocLint doclint; 120 121 WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<>(); 122 123 /** Allow documenting from class files? */ 124 boolean docClasses = false; 125 126 /** Does the doclet only expect pre-1.5 doclet API? */ 127 protected boolean legacyDoclet = true; 128 129 /** 130 * Set this to true if you would like to not emit any errors, warnings and 131 * notices. 132 */ 133 private boolean silent = false; 134 135 /** 136 * The source language version. 137 */ 138 protected Source source; 139 140 /** 141 * Constructor 142 * 143 * @param context Context for this javadoc instance. 144 */ 145 protected DocEnv(Context context) { 146 context.put(docEnvKey, this); 147 this.context = context; 148 149 messager = Messager.instance0(context); 150 syms = Symtab.instance(context); 151 finder = JavadocClassFinder.instance(context); 152 enter = JavadocEnter.instance(context); 153 names = Names.instance(context); 154 externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable")); 155 chk = Check.instance(context); 156 types = Types.instance(context); 157 fileManager = context.get(JavaFileManager.class); 158 if (fileManager instanceof JavacFileManager) { 159 ((JavacFileManager)fileManager).setSymbolFileEnabled(false); 160 } 161 162 // Default. Should normally be reset with setLocale. 163 this.doclocale = new DocLocale(this, "", breakiterator); 164 source = Source.instance(context); 165 } 166 167 public void setSilent(boolean silent) { 168 this.silent = silent; 169 } 170 171 /** 172 * Look up ClassDoc by qualified name. 173 */ 174 public ClassDocImpl lookupClass(String name) { 175 ClassSymbol c = getClassSymbol(name); 176 if (c != null) { 177 return getClassDoc(c); 178 } else { 179 return null; 180 } 181 } 182 183 /** 184 * Load ClassDoc by qualified name. 185 */ 186 public ClassDocImpl loadClass(String name) { 187 try { 188 ClassSymbol c = finder.loadClass(names.fromString(name)); 189 return getClassDoc(c); 190 } catch (CompletionFailure ex) { 191 chk.completionError(null, ex); 192 return null; 193 } 194 } 195 196 /** 197 * Look up PackageDoc by qualified name. 198 */ 199 public PackageDocImpl lookupPackage(String name) { 200 //### Jing alleges that class check is needed 201 //### to avoid a compiler bug. Most likely 202 //### instead a dummy created for error recovery. 203 //### Should investigate this. 204 PackageSymbol p = syms.packages.get(names.fromString(name)); 205 ClassSymbol c = getClassSymbol(name); 206 if (p != null && c == null) { 207 return getPackageDoc(p); 208 } else { 209 return null; 210 } 211 } 212 // where 213 /** Retrieve class symbol by fully-qualified name. 214 */ 215 ClassSymbol getClassSymbol(String name) { 216 // Name may contain nested class qualification. 217 // Generate candidate flatnames with successively shorter 218 // package qualifiers and longer nested class qualifiers. 219 int nameLen = name.length(); 220 char[] nameChars = name.toCharArray(); 221 int idx = name.length(); 222 for (;;) { 223 ClassSymbol s = syms.classes.get(names.fromChars(nameChars, 0, nameLen)); 224 if (s != null) 225 return s; // found it! 226 idx = name.substring(0, idx).lastIndexOf('.'); 227 if (idx < 0) break; 228 nameChars[idx] = '$'; 229 } 230 return null; 231 } 232 233 /** 234 * Set the locale. 235 */ 236 public void setLocale(String localeName) { 237 // create locale specifics 238 doclocale = new DocLocale(this, localeName, breakiterator); 239 // update Messager if locale has changed. 240 messager.setLocale(doclocale.locale); 241 } 242 243 /** Check whether this member should be documented. */ 244 public boolean shouldDocument(VarSymbol sym) { 245 long mod = sym.flags(); 246 247 if ((mod & Flags.SYNTHETIC) != 0) { 248 return false; 249 } 250 251 return showAccess.checkModifier(translateModifiers(mod)); 252 } 253 254 /** Check whether this member should be documented. */ 255 public boolean shouldDocument(MethodSymbol sym) { 256 long mod = sym.flags(); 257 258 if ((mod & Flags.SYNTHETIC) != 0) { 259 return false; 260 } 261 262 return showAccess.checkModifier(translateModifiers(mod)); 263 } 264 265 /** check whether this class should be documented. */ 266 public boolean shouldDocument(ClassSymbol sym) { 267 return 268 (sym.flags_field&Flags.SYNTHETIC) == 0 && // no synthetics 269 (docClasses || getClassDoc(sym).tree != null) && 270 isVisible(sym); 271 } 272 273 //### Comment below is inaccurate wrt modifier filter testing 274 /** 275 * Check the visibility if this is an nested class. 276 * if this is not a nested class, return true. 277 * if this is an static visible nested class, 278 * return true. 279 * if this is an visible nested class 280 * if the outer class is visible return true. 281 * else return false. 282 * IMPORTANT: This also allows, static nested classes 283 * to be defined inside an nested class, which is not 284 * allowed by the compiler. So such an test case will 285 * not reach upto this method itself, but if compiler 286 * allows it, then that will go through. 287 */ 288 protected boolean isVisible(ClassSymbol sym) { 289 long mod = sym.flags_field; 290 if (!showAccess.checkModifier(translateModifiers(mod))) { 291 return false; 292 } 293 ClassSymbol encl = sym.owner.enclClass(); 294 return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl)); 295 } 296 297 //---------------- print forwarders ----------------// 298 299 /** 300 * Print error message, increment error count. 301 * 302 * @param msg message to print. 303 */ 304 public void printError(String msg) { 305 if (silent) 306 return; 307 messager.printError(msg); 308 } 309 310 /** 311 * Print error message, increment error count. 312 * 313 * @param key selects message from resource 314 */ 315 public void error(DocImpl doc, String key) { 316 if (silent) 317 return; 318 messager.error(doc==null ? null : doc.position(), key); 319 } 320 321 /** 322 * Print error message, increment error count. 323 * 324 * @param key selects message from resource 325 */ 326 public void error(SourcePosition pos, String key) { 327 if (silent) 328 return; 329 messager.error(pos, key); 330 } 331 332 /** 333 * Print error message, increment error count. 334 * 335 * @param msg message to print. 336 */ 337 public void printError(SourcePosition pos, String msg) { 338 if (silent) 339 return; 340 messager.printError(pos, msg); 341 } 342 343 /** 344 * Print error message, increment error count. 345 * 346 * @param key selects message from resource 347 * @param a1 first argument 348 */ 349 public void error(DocImpl doc, String key, String a1) { 350 if (silent) 351 return; 352 messager.error(doc==null ? null : doc.position(), key, a1); 353 } 354 355 /** 356 * Print error message, increment error count. 357 * 358 * @param key selects message from resource 359 * @param a1 first argument 360 * @param a2 second argument 361 */ 362 public void error(DocImpl doc, String key, String a1, String a2) { 363 if (silent) 364 return; 365 messager.error(doc==null ? null : doc.position(), key, a1, a2); 366 } 367 368 /** 369 * Print error message, increment error count. 370 * 371 * @param key selects message from resource 372 * @param a1 first argument 373 * @param a2 second argument 374 * @param a3 third argument 375 */ 376 public void error(DocImpl doc, String key, String a1, String a2, String a3) { 377 if (silent) 378 return; 379 messager.error(doc==null ? null : doc.position(), key, a1, a2, a3); 380 } 381 382 /** 383 * Print warning message, increment warning count. 384 * 385 * @param msg message to print. 386 */ 387 public void printWarning(String msg) { 388 if (silent) 389 return; 390 messager.printWarning(msg); 391 } 392 393 /** 394 * Print warning message, increment warning count. 395 * 396 * @param key selects message from resource 397 */ 398 public void warning(DocImpl doc, String key) { 399 if (silent) 400 return; 401 messager.warning(doc==null ? null : doc.position(), key); 402 } 403 404 /** 405 * Print warning message, increment warning count. 406 * 407 * @param msg message to print. 408 */ 409 public void printWarning(SourcePosition pos, String msg) { 410 if (silent) 411 return; 412 messager.printWarning(pos, msg); 413 } 414 415 /** 416 * Print warning message, increment warning count. 417 * 418 * @param key selects message from resource 419 * @param a1 first argument 420 */ 421 public void warning(DocImpl doc, String key, String a1) { 422 if (silent) 423 return; 424 // suppress messages that have (probably) been covered by doclint 425 if (doclint != null && doc != null && key.startsWith("tag")) 426 return; 427 messager.warning(doc==null ? null : doc.position(), key, a1); 428 } 429 430 /** 431 * Print warning message, increment warning count. 432 * 433 * @param key selects message from resource 434 * @param a1 first argument 435 * @param a2 second argument 436 */ 437 public void warning(DocImpl doc, String key, String a1, String a2) { 438 if (silent) 439 return; 440 messager.warning(doc==null ? null : doc.position(), key, a1, a2); 441 } 442 443 /** 444 * Print warning message, increment warning count. 445 * 446 * @param key selects message from resource 447 * @param a1 first argument 448 * @param a2 second argument 449 * @param a3 third argument 450 */ 451 public void warning(DocImpl doc, String key, String a1, String a2, String a3) { 452 if (silent) 453 return; 454 messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3); 455 } 456 457 /** 458 * Print warning message, increment warning count. 459 * 460 * @param key selects message from resource 461 * @param a1 first argument 462 * @param a2 second argument 463 * @param a3 third argument 464 */ 465 public void warning(DocImpl doc, String key, String a1, String a2, String a3, 466 String a4) { 467 if (silent) 468 return; 469 messager.warning(doc==null ? null : doc.position(), key, a1, a2, a3, a4); 470 } 471 472 /** 473 * Print a message. 474 * 475 * @param msg message to print. 476 */ 477 public void printNotice(String msg) { 478 if (silent || quiet) 479 return; 480 messager.printNotice(msg); 481 } 482 483 484 /** 485 * Print a message. 486 * 487 * @param key selects message from resource 488 */ 489 public void notice(String key) { 490 if (silent || quiet) 491 return; 492 messager.notice(key); 493 } 494 495 /** 496 * Print a message. 497 * 498 * @param msg message to print. 499 */ 500 public void printNotice(SourcePosition pos, String msg) { 501 if (silent || quiet) 502 return; 503 messager.printNotice(pos, msg); 504 } 505 506 /** 507 * Print a message. 508 * 509 * @param key selects message from resource 510 * @param a1 first argument 511 */ 512 public void notice(String key, String a1) { 513 if (silent || quiet) 514 return; 515 messager.notice(key, a1); 516 } 517 518 /** 519 * Print a message. 520 * 521 * @param key selects message from resource 522 * @param a1 first argument 523 * @param a2 second argument 524 */ 525 public void notice(String key, String a1, String a2) { 526 if (silent || quiet) 527 return; 528 messager.notice(key, a1, a2); 529 } 530 531 /** 532 * Print a message. 533 * 534 * @param key selects message from resource 535 * @param a1 first argument 536 * @param a2 second argument 537 * @param a3 third argument 538 */ 539 public void notice(String key, String a1, String a2, String a3) { 540 if (silent || quiet) 541 return; 542 messager.notice(key, a1, a2, a3); 543 } 544 545 /** 546 * Exit, reporting errors and warnings. 547 */ 548 public void exit() { 549 // Messager should be replaced by a more general 550 // compilation environment. This can probably 551 // subsume DocEnv as well. 552 messager.exit(); 553 } 554 555 protected Map<PackageSymbol, PackageDocImpl> packageMap = new HashMap<>(); 556 /** 557 * Return the PackageDoc of this package symbol. 558 */ 559 public PackageDocImpl getPackageDoc(PackageSymbol pack) { 560 PackageDocImpl result = packageMap.get(pack); 561 if (result != null) return result; 562 result = new PackageDocImpl(this, pack); 563 packageMap.put(pack, result); 564 return result; 565 } 566 567 /** 568 * Create the PackageDoc (or a subtype) for a package symbol. 569 */ 570 void makePackageDoc(PackageSymbol pack, TreePath treePath) { 571 PackageDocImpl result = packageMap.get(pack); 572 if (result != null) { 573 if (treePath != null) result.setTreePath(treePath); 574 } else { 575 result = new PackageDocImpl(this, pack, treePath); 576 packageMap.put(pack, result); 577 } 578 } 579 580 581 protected Map<ClassSymbol, ClassDocImpl> classMap = new HashMap<>(); 582 /** 583 * Return the ClassDoc (or a subtype) of this class symbol. 584 */ 585 public ClassDocImpl getClassDoc(ClassSymbol clazz) { 586 ClassDocImpl result = classMap.get(clazz); 587 if (result != null) return result; 588 if (isAnnotationType(clazz)) { 589 result = new AnnotationTypeDocImpl(this, clazz); 590 } else { 591 result = new ClassDocImpl(this, clazz); 592 } 593 classMap.put(clazz, result); 594 return result; 595 } 596 597 /** 598 * Create the ClassDoc (or a subtype) for a class symbol. 599 */ 600 protected void makeClassDoc(ClassSymbol clazz, TreePath treePath) { 601 ClassDocImpl result = classMap.get(clazz); 602 if (result != null) { 603 if (treePath != null) result.setTreePath(treePath); 604 return; 605 } 606 if (isAnnotationType((JCClassDecl) treePath.getLeaf())) { // flags of clazz may not yet be set 607 result = new AnnotationTypeDocImpl(this, clazz, treePath); 608 } else { 609 result = new ClassDocImpl(this, clazz, treePath); 610 } 611 classMap.put(clazz, result); 612 } 613 614 protected static boolean isAnnotationType(ClassSymbol clazz) { 615 return ClassDocImpl.isAnnotationType(clazz); 616 } 617 618 protected static boolean isAnnotationType(JCClassDecl tree) { 619 return (tree.mods.flags & Flags.ANNOTATION) != 0; 620 } 621 622 protected Map<VarSymbol, FieldDocImpl> fieldMap = new HashMap<>(); 623 /** 624 * Return the FieldDoc of this var symbol. 625 */ 626 public FieldDocImpl getFieldDoc(VarSymbol var) { 627 FieldDocImpl result = fieldMap.get(var); 628 if (result != null) return result; 629 result = new FieldDocImpl(this, var); 630 fieldMap.put(var, result); 631 return result; 632 } 633 /** 634 * Create a FieldDoc for a var symbol. 635 */ 636 protected void makeFieldDoc(VarSymbol var, TreePath treePath) { 637 FieldDocImpl result = fieldMap.get(var); 638 if (result != null) { 639 if (treePath != null) result.setTreePath(treePath); 640 } else { 641 result = new FieldDocImpl(this, var, treePath); 642 fieldMap.put(var, result); 643 } 644 } 645 646 protected Map<MethodSymbol, ExecutableMemberDocImpl> methodMap = new HashMap<>(); 647 /** 648 * Create a MethodDoc for this MethodSymbol. 649 * Should be called only on symbols representing methods. 650 */ 651 protected void makeMethodDoc(MethodSymbol meth, TreePath treePath) { 652 MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); 653 if (result != null) { 654 if (treePath != null) result.setTreePath(treePath); 655 } else { 656 result = new MethodDocImpl(this, meth, treePath); 657 methodMap.put(meth, result); 658 } 659 } 660 661 /** 662 * Return the MethodDoc for a MethodSymbol. 663 * Should be called only on symbols representing methods. 664 */ 665 public MethodDocImpl getMethodDoc(MethodSymbol meth) { 666 assert !meth.isConstructor() : "not expecting a constructor symbol"; 667 MethodDocImpl result = (MethodDocImpl)methodMap.get(meth); 668 if (result != null) return result; 669 result = new MethodDocImpl(this, meth); 670 methodMap.put(meth, result); 671 return result; 672 } 673 674 /** 675 * Create the ConstructorDoc for a MethodSymbol. 676 * Should be called only on symbols representing constructors. 677 */ 678 protected void makeConstructorDoc(MethodSymbol meth, TreePath treePath) { 679 ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); 680 if (result != null) { 681 if (treePath != null) result.setTreePath(treePath); 682 } else { 683 result = new ConstructorDocImpl(this, meth, treePath); 684 methodMap.put(meth, result); 685 } 686 } 687 688 /** 689 * Return the ConstructorDoc for a MethodSymbol. 690 * Should be called only on symbols representing constructors. 691 */ 692 public ConstructorDocImpl getConstructorDoc(MethodSymbol meth) { 693 assert meth.isConstructor() : "expecting a constructor symbol"; 694 ConstructorDocImpl result = (ConstructorDocImpl)methodMap.get(meth); 695 if (result != null) return result; 696 result = new ConstructorDocImpl(this, meth); 697 methodMap.put(meth, result); 698 return result; 699 } 700 701 /** 702 * Create the AnnotationTypeElementDoc for a MethodSymbol. 703 * Should be called only on symbols representing annotation type elements. 704 */ 705 protected void makeAnnotationTypeElementDoc(MethodSymbol meth, TreePath treePath) { 706 AnnotationTypeElementDocImpl result = 707 (AnnotationTypeElementDocImpl)methodMap.get(meth); 708 if (result != null) { 709 if (treePath != null) result.setTreePath(treePath); 710 } else { 711 result = 712 new AnnotationTypeElementDocImpl(this, meth, treePath); 713 methodMap.put(meth, result); 714 } 715 } 716 717 /** 718 * Return the AnnotationTypeElementDoc for a MethodSymbol. 719 * Should be called only on symbols representing annotation type elements. 720 */ 721 public AnnotationTypeElementDocImpl getAnnotationTypeElementDoc( 722 MethodSymbol meth) { 723 724 AnnotationTypeElementDocImpl result = 725 (AnnotationTypeElementDocImpl)methodMap.get(meth); 726 if (result != null) return result; 727 result = new AnnotationTypeElementDocImpl(this, meth); 728 methodMap.put(meth, result); 729 return result; 730 } 731 732 // private Map<ClassType, ParameterizedTypeImpl> parameterizedTypeMap = 733 // new HashMap<ClassType, ParameterizedTypeImpl>(); 734 /** 735 * Return the ParameterizedType of this instantiation. 736 // * ### Could use Type.sameTypeAs() instead of equality matching in hashmap 737 // * ### to avoid some duplication. 738 */ 739 ParameterizedTypeImpl getParameterizedType(ClassType t) { 740 return new ParameterizedTypeImpl(this, t); 741 // ParameterizedTypeImpl result = parameterizedTypeMap.get(t); 742 // if (result != null) return result; 743 // result = new ParameterizedTypeImpl(this, t); 744 // parameterizedTypeMap.put(t, result); 745 // return result; 746 } 747 748 TreePath getTreePath(JCCompilationUnit tree) { 749 TreePath p = treePaths.get(tree); 750 if (p == null) 751 treePaths.put(tree, p = new TreePath(tree)); 752 return p; 753 } 754 755 TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) { 756 TreePath p = treePaths.get(tree); 757 if (p == null) 758 treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); 759 return p; 760 } 761 762 TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) { 763 TreePath p = treePaths.get(tree); 764 if (p == null) 765 treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); 766 return p; 767 } 768 769 TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) { 770 return new TreePath(getTreePath(toplevel, cdecl), tree); 771 } 772 773 /** 774 * Set the encoding. 775 */ 776 public void setEncoding(String encoding) { 777 this.encoding = encoding; 778 } 779 780 /** 781 * Get the encoding. 782 */ 783 public String getEncoding() { 784 return encoding; 785 } 786 787 /** 788 * Convert modifier bits from private coding used by 789 * the compiler to that of java.lang.reflect.Modifier. 790 */ 791 static int translateModifiers(long flags) { 792 int result = 0; 793 if ((flags & Flags.ABSTRACT) != 0) 794 result |= Modifier.ABSTRACT; 795 if ((flags & Flags.FINAL) != 0) 796 result |= Modifier.FINAL; 797 if ((flags & Flags.INTERFACE) != 0) 798 result |= Modifier.INTERFACE; 799 if ((flags & Flags.NATIVE) != 0) 800 result |= Modifier.NATIVE; 801 if ((flags & Flags.PRIVATE) != 0) 802 result |= Modifier.PRIVATE; 803 if ((flags & Flags.PROTECTED) != 0) 804 result |= Modifier.PROTECTED; 805 if ((flags & Flags.PUBLIC) != 0) 806 result |= Modifier.PUBLIC; 807 if ((flags & Flags.STATIC) != 0) 808 result |= Modifier.STATIC; 809 if ((flags & Flags.SYNCHRONIZED) != 0) 810 result |= Modifier.SYNCHRONIZED; 811 if ((flags & Flags.TRANSIENT) != 0) 812 result |= Modifier.TRANSIENT; 813 if ((flags & Flags.VOLATILE) != 0) 814 result |= Modifier.VOLATILE; 815 return result; 816 } 817 818 void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) { 819 ArrayList<String> doclintOpts = new ArrayList<>(); 820 boolean msgOptionSeen = false; 821 822 for (String opt : opts) { 823 if (opt.startsWith(DocLint.XMSGS_OPTION)) { 824 if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) 825 return; 826 msgOptionSeen = true; 827 } 828 doclintOpts.add(opt); 829 } 830 831 if (!msgOptionSeen) { 832 doclintOpts.add(DocLint.XMSGS_OPTION); 833 } 834 835 String sep = ""; 836 StringBuilder customTags = new StringBuilder(); 837 for (String customTag : customTagNames) { 838 customTags.append(sep); 839 customTags.append(customTag); 840 sep = DocLint.SEPARATOR; 841 } 842 doclintOpts.add(DocLint.XCUSTOM_TAGS_PREFIX + customTags.toString()); 843 doclintOpts.add(DocLint.XHTML_VERSION_PREFIX + htmlVersion); 844 845 JavacTask t = BasicJavacTask.instance(context); 846 doclint = new DocLint(); 847 // standard doclet normally generates H1, H2 848 doclintOpts.add(DocLint.XIMPLICIT_HEADERS + "2"); 849 doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false); 850 } 851 852 boolean showTagMessages() { 853 return (doclint == null); 854 } 855 856 Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>(); 857 858 boolean shouldCheck(CompilationUnitTree unit) { 859 return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck); 860 } 861 }