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 jdk.javadoc.internal.tool; 27 28 29 import java.lang.reflect.Modifier; 30 import java.util.*; 31 32 import javax.lang.model.element.Element; 33 import javax.lang.model.element.ExecutableElement; 34 import javax.lang.model.element.PackageElement; 35 import javax.lang.model.element.TypeElement; 36 import javax.lang.model.element.VariableElement; 37 import javax.lang.model.util.Elements; 38 import javax.lang.model.util.SimpleElementVisitor9; 39 import javax.tools.JavaFileManager; 40 import javax.tools.JavaFileObject; 41 42 import com.sun.source.util.DocTrees; 43 import com.sun.source.util.TreePath; 44 import com.sun.tools.javac.api.JavacTrees; 45 import com.sun.tools.javac.code.ClassFinder; 46 import com.sun.tools.javac.code.Flags; 47 import com.sun.tools.javac.code.Kinds.Kind; 48 import com.sun.tools.javac.code.Source; 49 import com.sun.tools.javac.code.Symbol; 50 import com.sun.tools.javac.code.Symbol.ClassSymbol; 51 import com.sun.tools.javac.code.Symbol.CompletionFailure; 52 import com.sun.tools.javac.code.Symbol.MethodSymbol; 53 import com.sun.tools.javac.code.Symbol.PackageSymbol; 54 import com.sun.tools.javac.code.Symbol.VarSymbol; 55 import com.sun.tools.javac.code.Symtab; 56 import com.sun.tools.javac.comp.AttrContext; 57 import com.sun.tools.javac.comp.Check; 58 import com.sun.tools.javac.comp.Enter; 59 import com.sun.tools.javac.comp.Env; 60 import com.sun.tools.javac.file.JavacFileManager; 61 import com.sun.tools.javac.model.JavacElements; 62 import com.sun.tools.javac.model.JavacTypes; 63 import com.sun.tools.javac.tree.JCTree; 64 import com.sun.tools.javac.tree.JCTree.JCClassDecl; 65 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 66 import com.sun.tools.javac.tree.JCTree.JCPackageDecl; 67 import com.sun.tools.javac.util.Context; 68 import com.sun.tools.javac.util.DefinedBy; 69 import com.sun.tools.javac.util.DefinedBy.Api; 70 import com.sun.tools.javac.util.Names; 71 72 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; 73 74 /** 75 * Holds the environment for a run of javadoc. 76 * Holds only the information needed throughout the 77 * run and not the compiler info that could be GC'ed 78 * or ported. 79 * 80 * <p><b>This is NOT part of any supported API. 81 * If you write code that depends on this, you do so at your own risk. 82 * This code and its internal interfaces are subject to change or 83 * deletion without notice.</b> 84 * 85 * @since 1.4 86 * @author Robert Field 87 * @author Neal Gafter (rewrite) 88 * @author Scott Seligman (generics) 89 */ 90 public class DocEnv { 91 protected static final Context.Key<DocEnv> docEnvKey = new Context.Key<>(); 92 93 public static DocEnv instance(Context context) { 94 DocEnv instance = context.get(docEnvKey); 95 if (instance == null) 96 instance = new DocEnv(context); 97 return instance; 98 } 99 100 private final Messager messager; 101 102 /** Predefined symbols known to the compiler. */ 103 public final Symtab syms; 104 105 /** Referenced directly in RootDocImpl. */ 106 private final ClassFinder finder; 107 108 /** Javadoc's own version of the compiler's enter phase. */ 109 final Enter enter; 110 111 /** The name table. */ 112 private Names names; 113 114 /** The encoding name. */ 115 private String encoding; 116 117 final Symbol externalizableSym; 118 119 /** Access filter (public, protected, ...). */ 120 protected ModifierFilter filter; 121 122 /** 123 * True if we do not want to print any notifications at all. 124 */ 125 boolean quiet = false; 126 127 Check chk; 128 com.sun.tools.javac.code.Types types; 129 JavaFileManager fileManager; 130 public final Context context; 131 132 WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<>(); 133 134 public final HashMap<PackageElement, JavaFileObject> pkgToJavaFOMap = new HashMap<>(); 135 136 /** Allow documenting from class files? */ 137 boolean docClasses = false; 138 139 /** 140 * The source language version. 141 */ 142 public final Source source; 143 144 public final Elements elements; 145 146 public final JavacTypes typeutils; 147 148 protected RootDocImpl root; 149 150 public final DocTrees docTrees; 151 152 public final Map<Element, TreePath> elementToTreePath; 153 154 /** 155 * Constructor 156 * 157 * @param context Context for this javadoc instance. 158 */ 159 protected DocEnv(Context context) { 160 context.put(docEnvKey, this); 161 this.context = context; 162 163 messager = Messager.instance0(context); 164 syms = Symtab.instance(context); 165 finder = JavadocClassFinder.instance(context); 166 enter = JavadocEnter.instance(context); 167 names = Names.instance(context); 168 externalizableSym = syms.enterClass(names.fromString("java.io.Externalizable")); 169 chk = Check.instance(context); 170 types = com.sun.tools.javac.code.Types.instance(context); 171 fileManager = context.get(JavaFileManager.class); 172 if (fileManager instanceof JavacFileManager) { 173 ((JavacFileManager)fileManager).setSymbolFileEnabled(false); 174 } 175 docTrees = JavacTrees.instance(context); 176 source = Source.instance(context); 177 elements = JavacElements.instance(context); 178 typeutils = JavacTypes.instance(context); 179 elementToTreePath = new HashMap<>(); 180 } 181 182 public void intialize(String encoding, 183 String showAccess, 184 String overviewpath, 185 List<String> javaNames, 186 Iterable<? extends JavaFileObject> fileObjects, 187 List<String> subPackages, 188 List<String> excludedPackages, 189 boolean docClasses, 190 boolean quiet) { 191 this.filter = ModifierFilter.getModifierFilter(showAccess); 192 this.quiet = quiet; 193 194 this.setEncoding(encoding); 195 this.docClasses = docClasses; 196 } 197 198 /** 199 * Load a class by qualified name. 200 */ 201 public TypeElement loadClass(String name) { 202 try { 203 ClassSymbol c = finder.loadClass(names.fromString(name)); 204 return c; 205 } catch (CompletionFailure ex) { 206 chk.completionError(null, ex); 207 return null; 208 } 209 } 210 211 private boolean isSynthetic(long flags) { 212 return (flags & Flags.SYNTHETIC) != 0; 213 } 214 215 private boolean isSynthetic(Symbol sym) { 216 return isSynthetic(sym.flags_field); 217 } 218 219 SimpleElementVisitor9<Boolean, Void> shouldDocumentVisitor = null; 220 public boolean shouldDocument(Element e) { 221 if (shouldDocumentVisitor == null) { 222 shouldDocumentVisitor = new SimpleElementVisitor9<Boolean, Void>() { 223 224 @Override @DefinedBy(Api.LANGUAGE_MODEL) 225 public Boolean visitType(TypeElement e, Void p) { 226 return shouldDocument((ClassSymbol)e); 227 } 228 229 @Override @DefinedBy(Api.LANGUAGE_MODEL) 230 public Boolean visitVariable(VariableElement e, Void p) { 231 return shouldDocument((VarSymbol)e); 232 } 233 234 @Override @DefinedBy(Api.LANGUAGE_MODEL) 235 public Boolean visitExecutable(ExecutableElement e, Void p) { 236 return shouldDocument((MethodSymbol)e); 237 } 238 }; 239 } 240 return shouldDocumentVisitor.visit(e); 241 } 242 243 /** Check whether this member should be documented. */ 244 public boolean shouldDocument(VarSymbol sym) { 245 long mod = sym.flags(); 246 if (isSynthetic(mod)) { 247 return false; 248 } 249 return filter.checkModifier(translateModifiers(mod)); 250 } 251 252 /** Check whether this member should be documented. */ 253 public boolean shouldDocument(MethodSymbol sym) { 254 long mod = sym.flags(); 255 if (isSynthetic(mod)) { 256 return false; 257 } 258 return filter.checkModifier(translateModifiers(mod)); 259 } 260 261 void setElementToTreePath(Element e, TreePath tree) { 262 if (e == null || tree == null) 263 return; 264 elementToTreePath.put(e, tree); 265 } 266 267 private boolean hasLeaf(ClassSymbol sym) { 268 TreePath path = elementToTreePath.get(sym); 269 if (path == null) 270 return false; 271 return path.getLeaf() != null; 272 } 273 274 /** check whether this class should be documented. */ 275 public boolean shouldDocument(ClassSymbol sym) { 276 return 277 !isSynthetic(sym.flags_field) && // no synthetics 278 (docClasses || hasLeaf(sym)) && 279 isVisible(sym); 280 } 281 282 //### Comment below is inaccurate wrt modifier filter testing 283 /** 284 * Check the visibility if this is an nested class. 285 * if this is not a nested class, return true. 286 * if this is an static visible nested class, 287 * return true. 288 * if this is an visible nested class 289 * if the outer class is visible return true. 290 * else return false. 291 * IMPORTANT: This also allows, static nested classes 292 * to be defined inside an nested class, which is not 293 * allowed by the compiler. So such an test case will 294 * not reach upto this method itself, but if compiler 295 * allows it, then that will go through. 296 */ 297 public boolean isVisible(ClassSymbol sym) { 298 long mod = sym.flags_field; 299 if (!filter.checkModifier(translateModifiers(mod))) { 300 return false; 301 } 302 ClassSymbol encl = sym.owner.enclClass(); 303 return (encl == null || (mod & Flags.STATIC) != 0 || isVisible(encl)); 304 } 305 306 //---------------- print forwarders ----------------// 307 308 // ERRORS 309 /** 310 * Print error message, increment error count. 311 * 312 * @param msg message to print. 313 */ 314 public void printError(String msg) { 315 messager.printError(msg); 316 } 317 318 // /** 319 // * Print error message, increment error count. 320 // * 321 // * @param key selects message from resource 322 // */ 323 // public void error(Element element, String key) { 324 // if (element == null) 325 // messager.error(key); 326 // else 327 // messager.error(element, key); 328 // } 329 // 330 // public void error(String prefix, String key) { 331 // printError(prefix + ":" + messager.getText(key)); 332 // } 333 // 334 // /** 335 // * Print error message, increment error count. 336 // * 337 // * @param path the path to the source 338 // * @param key selects message from resource 339 // */ 340 // public void error(DocTreePath path, String key) { 341 // messager.error(path, key); 342 // } 343 // 344 // /** 345 // * Print error message, increment error count. 346 // * 347 // * @param path the path to the source 348 // * @param msg message to print. 349 // */ 350 // public void printError(DocTreePath path, String msg) { 351 // messager.printError(path, msg); 352 // } 353 // 354 // /** 355 // * Print error message, increment error count. 356 // * @param e the target element 357 // * @param msg message to print. 358 // */ 359 // public void printError(Element e, String msg) { 360 // messager.printError(e, msg); 361 // } 362 363 /** 364 * Print error message, increment error count. 365 * 366 * @param element the source element 367 * @param key selects message from resource 368 * @param args replacement arguments 369 */ 370 public void error(Element element, String key, String... args) { 371 if (element == null) 372 messager.error(key, (Object[]) args); 373 else 374 messager.error(element, key, (Object[]) args); 375 } 376 377 // WARNINGS 378 379 // /** 380 // * Print warning message, increment warning count. 381 // * 382 // * @param msg message to print. 383 // */ 384 // public void printWarning(String msg) { 385 // messager.printWarning(msg); 386 // } 387 // 388 // public void warning(String key) { 389 // warning((Element)null, key); 390 // } 391 392 public void warning(String key, String... args) { 393 warning((Element)null, key, args); 394 } 395 396 // /** 397 // * Print warning message, increment warning count. 398 // * 399 // * @param element the source element 400 // * @param key selects message from resource 401 // */ 402 // public void warning(Element element, String key) { 403 // if (element == null) 404 // messager.warning(key); 405 // else 406 // messager.warning(element, key); 407 // } 408 // 409 // /** 410 // * Print warning message, increment warning count. 411 // * 412 // * @param path the path to the source 413 // * @param msg message to print. 414 // */ 415 // public void printWarning(DocTreePath path, String msg) { 416 // messager.printWarning(path, msg); 417 // } 418 // 419 // /** 420 // * Print warning message, increment warning count. 421 // * 422 // * @param e the source element 423 // * @param msg message to print. 424 // */ 425 // public void printWarning(Element e, String msg) { 426 // messager.printWarning(e, msg); 427 // } 428 429 /** 430 * Print warning message, increment warning count. 431 * 432 * @param e the source element 433 * @param key selects message from resource 434 * @param args the replace arguments 435 */ 436 public void warning(Element e, String key, String... args) { 437 if (e == null) 438 messager.warning(key, (Object[]) args); 439 else 440 messager.warning(e, key, (Object[]) args); 441 } 442 443 // Note: no longer required 444 // /** 445 // * Print a message. 446 // * 447 // * @param msg message to print. 448 // */ 449 // public void printNotice(String msg) { 450 // if (quiet) { 451 // return; 452 // } 453 // messager.printNotice(msg); 454 // } 455 456 // Note: no longer required 457 // /** 458 // * Print a message. 459 // * 460 // * @param e the source element 461 // * @param msg message to print. 462 // */ 463 // public void printNotice(Element e, String msg) { 464 // if (quiet) { 465 // return; 466 // } 467 // messager.printNotice(e, msg); 468 // } 469 470 // NOTICES 471 /** 472 * Print a message. 473 * 474 * @param key selects message from resource 475 */ 476 public void notice(String key) { 477 if (quiet) { 478 return; 479 } 480 messager.notice(key); 481 } 482 483 // Note: not used anymore 484 // /** 485 // * Print a message. 486 // * 487 // * @param path the path to the source 488 // * @param msg message to print. 489 // */ 490 // public void printNotice(DocTreePath path, String msg) { 491 // if (quiet) { 492 // return; 493 // } 494 // messager.printNotice(path, msg); 495 // } 496 497 /** 498 * Print a message. 499 * 500 * @param key selects message from resource 501 * @param a1 first argument 502 */ 503 public void notice(String key, String a1) { 504 if (quiet) { 505 return; 506 } 507 messager.notice(key, a1); 508 } 509 510 // Note: not used anymore 511 // /** 512 // * Print a message. 513 // * 514 // * @param key selects message from resource 515 // * @param a1 first argument 516 // * @param a2 second argument 517 // */ 518 // public void notice(String key, String a1, String a2) { 519 // if (quiet) { 520 // return; 521 // } 522 // messager.notice(key, a1, a2); 523 // } 524 // 525 526 // Note: not used anymore 527 // /** 528 // * Print a message. 529 // * 530 // * @param key selects message from resource 531 // * @param a1 first argument 532 // * @param a2 second argument 533 // * @param a3 third argument 534 // */ 535 // public void notice(String key, String a1, String a2, String a3) { 536 // if (quiet) { 537 // return; 538 // } 539 // messager.notice(key, a1, a2, a3); 540 // } 541 542 /** 543 * Exit, reporting errors and warnings. 544 */ 545 public void exit() { 546 // Messager should be replaced by a more general 547 // compilation environment. This can probably 548 // subsume DocEnv as well. 549 messager.exit(); 550 } 551 552 /** 553 * Adds all inner classes of this class, and their inner classes recursively, to the list 554 */ 555 void addAllClasses(Collection<TypeElement> list, TypeElement typeElement, boolean filtered) { 556 ClassSymbol klass = (ClassSymbol)typeElement; 557 try { 558 if (isSynthetic(klass.flags())) return; 559 // sometimes synthetic classes are not marked synthetic 560 if (!JavadocTool.isValidClassName(klass.name.toString())) return; 561 if (filtered && !shouldDocument(klass)) return; 562 if (list.contains(klass)) return; 563 list.add(klass); 564 for (Symbol sym : klass.members().getSymbols(NON_RECURSIVE)) { 565 if (sym != null && sym.kind == Kind.TYP) { 566 ClassSymbol s = (ClassSymbol)sym; 567 if (!isSynthetic(s.flags())) { 568 addAllClasses(list, s, filtered); 569 } 570 } 571 } 572 } catch (CompletionFailure e) { 573 // quietly ignore completion failures 574 } 575 } 576 577 /** 578 * Return a list of all classes contained in this package, including 579 * member classes of those classes, and their member classes, etc. 580 */ 581 void addAllClasses(Collection<TypeElement> list, PackageElement pkg) { 582 boolean filtered = true; 583 PackageSymbol sym = (PackageSymbol)pkg; 584 for (Symbol isym : sym.members().getSymbols(NON_RECURSIVE)) { 585 if (isym != null) { 586 ClassSymbol s = (ClassSymbol)isym; 587 if (!isSynthetic(s)) { 588 addAllClasses(list, s, filtered); 589 } 590 } 591 } 592 } 593 594 TreePath getTreePath(JCCompilationUnit tree) { 595 TreePath p = treePaths.get(tree); 596 if (p == null) 597 treePaths.put(tree, p = new TreePath(tree)); 598 return p; 599 } 600 601 TreePath getTreePath(JCCompilationUnit toplevel, JCPackageDecl tree) { 602 TreePath p = treePaths.get(tree); 603 if (p == null) 604 treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); 605 return p; 606 } 607 608 TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) { 609 TreePath p = treePaths.get(tree); 610 if (p == null) 611 treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree)); 612 return p; 613 } 614 615 TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) { 616 return new TreePath(getTreePath(toplevel, cdecl), tree); 617 } 618 619 public com.sun.tools.javac.code.Types getTypes() { 620 return types; 621 } 622 623 /** 624 * Set the encoding. 625 */ 626 public void setEncoding(String encoding) { 627 this.encoding = encoding; 628 } 629 630 public Env<AttrContext> getEnv(ClassSymbol tsym) { 631 return enter.getEnv(tsym); 632 } 633 634 /** 635 * Get the encoding. 636 */ 637 public String getEncoding() { 638 return encoding; 639 } 640 641 /** 642 * Convert modifier bits from private coding used by 643 * the compiler to that of java.lang.reflect.Modifier. 644 */ 645 static int translateModifiers(long flags) { 646 int result = 0; 647 if ((flags & Flags.ABSTRACT) != 0) 648 result |= Modifier.ABSTRACT; 649 if ((flags & Flags.FINAL) != 0) 650 result |= Modifier.FINAL; 651 if ((flags & Flags.INTERFACE) != 0) 652 result |= Modifier.INTERFACE; 653 if ((flags & Flags.NATIVE) != 0) 654 result |= Modifier.NATIVE; 655 if ((flags & Flags.PRIVATE) != 0) 656 result |= Modifier.PRIVATE; 657 if ((flags & Flags.PROTECTED) != 0) 658 result |= Modifier.PROTECTED; 659 if ((flags & Flags.PUBLIC) != 0) 660 result |= Modifier.PUBLIC; 661 if ((flags & Flags.STATIC) != 0) 662 result |= Modifier.STATIC; 663 if ((flags & Flags.SYNCHRONIZED) != 0) 664 result |= Modifier.SYNCHRONIZED; 665 if ((flags & Flags.TRANSIENT) != 0) 666 result |= Modifier.TRANSIENT; 667 if ((flags & Flags.VOLATILE) != 0) 668 result |= Modifier.VOLATILE; 669 return result; 670 } 671 672 private final Set<Element> includedSet = new HashSet<>(); 673 674 public void setIncluded(Element element) { 675 includedSet.add(element); 676 } 677 678 private SimpleElementVisitor9<Boolean, Void> includedVisitor = null; 679 680 public boolean isIncluded(Element e) { 681 if (e == null) { 682 return false; 683 } 684 if (includedVisitor == null) { 685 includedVisitor = new SimpleElementVisitor9<Boolean, Void>() { 686 @Override @DefinedBy(Api.LANGUAGE_MODEL) 687 public Boolean visitType(TypeElement e, Void p) { 688 if (includedSet.contains(e)) { 689 return true; 690 } 691 if (shouldDocument(e)) { 692 // Class is nameable from top-level and 693 // the class and all enclosing classes 694 // pass the modifier filter. 695 PackageElement pkg = elements.getPackageOf(e); 696 if (includedSet.contains(pkg)) { 697 setIncluded(e); 698 return true; 699 } 700 Element enclosing = e.getEnclosingElement(); 701 if (enclosing != null && includedSet.contains(enclosing)) { 702 setIncluded(e); 703 return true; 704 } 705 } 706 return false; 707 } 708 709 @Override @DefinedBy(Api.LANGUAGE_MODEL) 710 public Boolean defaultAction(Element e, Void p) { 711 if (includedSet.contains(e) || shouldDocument(e)) { 712 return true; 713 } 714 return false; 715 } 716 717 @Override @DefinedBy(Api.LANGUAGE_MODEL) 718 public Boolean visitPackage(PackageElement e, Void p) { 719 return includedSet.contains(e); 720 } 721 722 @Override @DefinedBy(Api.LANGUAGE_MODEL) 723 public Boolean visitUnknown(Element e, Void p) { 724 throw new AssertionError("got element: " + e); 725 } 726 }; 727 } 728 return includedVisitor.visit(e); 729 } 730 731 public boolean isQuiet() { 732 return quiet; 733 } 734 735 /** 736 * A class which filters the access flags on classes, fields, methods, etc. 737 * 738 * <p> 739 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so 740 * at your own risk. This code and its internal interfaces are subject to change or deletion 741 * without notice.</b> 742 * 743 * @see javax.lang.model.element.Modifier 744 * @author Robert Field 745 */ 746 747 private static class ModifierFilter { 748 749 static enum FilterFlag { 750 PACKAGE, 751 PRIVATE, 752 PROTECTED, 753 PUBLIC 754 } 755 756 private Set<FilterFlag> oneOf; 757 758 /** 759 * Constructor - Specify a filter. 760 * 761 * @param oneOf a set containing desired flags to be matched. 762 */ 763 ModifierFilter(Set<FilterFlag> oneOf) { 764 this.oneOf = oneOf; 765 } 766 767 /** 768 * Constructor - Specify a filter. 769 * 770 * @param oneOf an array containing desired flags to be matched. 771 */ 772 ModifierFilter(FilterFlag... oneOf) { 773 this.oneOf = new HashSet<>(); 774 this.oneOf.addAll(Arrays.asList(oneOf)); 775 } 776 777 static ModifierFilter getModifierFilter(String showAccess) { 778 switch (showAccess) { 779 case "public": 780 return new ModifierFilter(FilterFlag.PUBLIC); 781 case "package": 782 return new ModifierFilter(FilterFlag.PUBLIC, FilterFlag.PROTECTED, 783 FilterFlag.PACKAGE); 784 case "private": 785 return new ModifierFilter(FilterFlag.PRIVATE); 786 default: 787 return new ModifierFilter(FilterFlag.PUBLIC, FilterFlag.PROTECTED); 788 } 789 } 790 791 private boolean hasFlag(long flag, long modifierBits) { 792 return (flag & modifierBits) != 0; 793 } 794 795 private List<FilterFlag> flagsToModifiers(long modifierBits) { 796 List<FilterFlag> list = new ArrayList<>(); 797 boolean isPackage = true; 798 if (hasFlag(com.sun.tools.javac.code.Flags.PRIVATE, modifierBits)) { 799 list.add(FilterFlag.PRIVATE); 800 isPackage = false; 801 } 802 if (hasFlag(com.sun.tools.javac.code.Flags.PROTECTED, modifierBits)) { 803 list.add(FilterFlag.PROTECTED); 804 isPackage = false; 805 } 806 if (hasFlag(com.sun.tools.javac.code.Flags.PUBLIC, modifierBits)) { 807 list.add(FilterFlag.PUBLIC); 808 isPackage = false; 809 } 810 if (isPackage) { 811 list.add(FilterFlag.PACKAGE); 812 } 813 return list; 814 } 815 816 /** 817 * Filter on modifier bits. 818 * 819 * @param modifierBits Bits as specified in the Modifier class 820 * 821 * @return Whether the modifierBits pass this filter. 822 */ 823 public boolean checkModifier(int modifierBits) { 824 return checkModifier(flagsToModifiers(modifierBits)); 825 } 826 827 /** 828 * Filter on Filter flags 829 * 830 * @param modifiers Flags as specified in the FilterFlags enumeration. 831 * 832 * @return if the modifier is contained. 833 */ 834 public boolean checkModifier(List<FilterFlag> modifiers) { 835 if (oneOf.contains(FilterFlag.PRIVATE)) { 836 return true; 837 } 838 for (FilterFlag mod : modifiers) { 839 if (oneOf.contains(mod)) { 840 return true; 841 } 842 } 843 return false; 844 } 845 846 } // end ModifierFilter 847 }