1 /* 2 * Copyright (c) 1999, 2016, 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.javac.code; 27 28 import java.io.IOException; 29 import java.nio.file.Path; 30 import java.util.EnumSet; 31 import java.util.HashMap; 32 import java.util.Iterator; 33 import java.util.Map; 34 import java.util.NoSuchElementException; 35 import java.util.Set; 36 37 import javax.lang.model.SourceVersion; 38 import javax.tools.JavaFileManager; 39 import javax.tools.JavaFileManager.Location; 40 import javax.tools.JavaFileObject; 41 import javax.tools.JavaFileObject.Kind; 42 import javax.tools.StandardJavaFileManager; 43 import javax.tools.StandardLocation; 44 45 import com.sun.tools.javac.code.Scope.WriteableScope; 46 import com.sun.tools.javac.code.Symbol.ClassSymbol; 47 import com.sun.tools.javac.code.Symbol.Completer; 48 import com.sun.tools.javac.code.Symbol.CompletionFailure; 49 import com.sun.tools.javac.code.Symbol.ModuleSymbol; 50 import com.sun.tools.javac.code.Symbol.PackageSymbol; 51 import com.sun.tools.javac.code.Symbol.TypeSymbol; 52 import com.sun.tools.javac.comp.Annotate; 53 import com.sun.tools.javac.file.JRTIndex; 54 import com.sun.tools.javac.file.JavacFileManager; 55 import com.sun.tools.javac.jvm.ClassReader; 56 import com.sun.tools.javac.jvm.Profile; 57 import com.sun.tools.javac.main.Option; 58 import com.sun.tools.javac.platform.PlatformDescription; 59 import com.sun.tools.javac.util.*; 60 61 import static javax.tools.StandardLocation.*; 62 63 import static com.sun.tools.javac.code.Flags.*; 64 import static com.sun.tools.javac.code.Kinds.Kind.*; 65 66 import com.sun.tools.javac.util.Dependencies.CompletionCause; 67 68 /** 69 * This class provides operations to locate class definitions 70 * from the source and class files on the paths provided to javac. 71 * 72 * <p><b>This is NOT part of any supported API. 73 * If you write code that depends on this, you do so at your own risk. 74 * This code and its internal interfaces are subject to change or 75 * deletion without notice.</b> 76 */ 77 public class ClassFinder { 78 /** The context key for the class finder. */ 79 protected static final Context.Key<ClassFinder> classFinderKey = new Context.Key<>(); 80 81 ClassReader reader; 82 83 private final Annotate annotate; 84 85 /** Switch: verbose output. 86 */ 87 boolean verbose; 88 89 /** 90 * Switch: cache completion failures unless -XDdev is used 91 */ 92 private boolean cacheCompletionFailure; 93 94 /** 95 * Switch: prefer source files instead of newer when both source 96 * and class are available 97 **/ 98 protected boolean preferSource; 99 100 /** 101 * Switch: Search classpath and sourcepath for classes before the 102 * bootclasspath 103 */ 104 protected boolean userPathsFirst; 105 106 /** 107 * Switch: should read OTHER classfiles (.sig files) from PLATFORM_CLASS_PATH. 108 */ 109 private boolean allowSigFiles; 110 111 /** The log to use for verbose output 112 */ 113 final Log log; 114 115 /** The symbol table. */ 116 Symtab syms; 117 118 /** The name table. */ 119 final Names names; 120 121 /** Force a completion failure on this name 122 */ 123 final Name completionFailureName; 124 125 /** Access to files 126 */ 127 private final JavaFileManager fileManager; 128 129 /** Dependency tracker 130 */ 131 private final Dependencies dependencies; 132 133 /** Factory for diagnostics 134 */ 135 JCDiagnostic.Factory diagFactory; 136 137 /** Can be reassigned from outside: 138 * the completer to be used for ".java" files. If this remains unassigned 139 * ".java" files will not be loaded. 140 */ 141 public Completer sourceCompleter = Completer.NULL_COMPLETER; 142 143 /** The path name of the class file currently being read. 144 */ 145 protected JavaFileObject currentClassFile = null; 146 147 /** The class or method currently being read. 148 */ 149 protected Symbol currentOwner = null; 150 151 /** 152 * The currently selected profile. 153 */ 154 private final Profile profile; 155 156 /** 157 * Use direct access to the JRTIndex to access the temporary 158 * replacement for the info that used to be in ct.sym. 159 * In time, this will go away and be replaced by the module system. 160 */ 161 private final JRTIndex jrtIndex; 162 163 /** 164 * Completer that delegates to the complete-method of this class. 165 */ 166 private final Completer thisCompleter = this::complete; 167 168 public Completer getCompleter() { 169 return thisCompleter; 170 } 171 172 /** Get the ClassFinder instance for this invocation. */ 173 public static ClassFinder instance(Context context) { 174 ClassFinder instance = context.get(classFinderKey); 175 if (instance == null) 176 instance = new ClassFinder(context); 177 return instance; 178 } 179 180 /** Construct a new class finder. */ 181 protected ClassFinder(Context context) { 182 context.put(classFinderKey, this); 183 reader = ClassReader.instance(context); 184 names = Names.instance(context); 185 syms = Symtab.instance(context); 186 fileManager = context.get(JavaFileManager.class); 187 dependencies = Dependencies.instance(context); 188 if (fileManager == null) 189 throw new AssertionError("FileManager initialization error"); 190 diagFactory = JCDiagnostic.Factory.instance(context); 191 192 log = Log.instance(context); 193 annotate = Annotate.instance(context); 194 195 Options options = Options.instance(context); 196 verbose = options.isSet(Option.VERBOSE); 197 cacheCompletionFailure = options.isUnset("dev"); 198 preferSource = "source".equals(options.get("-Xprefer")); 199 userPathsFirst = options.isSet(Option.XXUSERPATHSFIRST); 200 allowSigFiles = context.get(PlatformDescription.class) != null; 201 202 completionFailureName = 203 options.isSet("failcomplete") 204 ? names.fromString(options.get("failcomplete")) 205 : null; 206 207 // Temporary, until more info is available from the module system. 208 boolean useCtProps; 209 JavaFileManager fm = context.get(JavaFileManager.class); 210 if (fm instanceof JavacFileManager) { 211 JavacFileManager jfm = (JavacFileManager) fm; 212 useCtProps = jfm.isDefaultBootClassPath() && jfm.isSymbolFileEnabled(); 213 } else if (fm.getClass().getName().equals("com.sun.tools.sjavac.comp.SmartFileManager")) { 214 useCtProps = !options.isSet("ignore.symbol.file"); 215 } else { 216 useCtProps = false; 217 } 218 jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null; 219 220 profile = Profile.instance(context); 221 } 222 223 224 /************************************************************************ 225 * Temporary ct.sym replacement 226 * 227 * The following code is a temporary substitute for the ct.sym mechanism 228 * used in JDK 6 thru JDK 8. 229 * This mechanism will eventually be superseded by the Jigsaw module system. 230 ***********************************************************************/ 231 232 /** 233 * Returns any extra flags for a class symbol. 234 * This information used to be provided using private annotations 235 * in the class file in ct.sym; in time, this information will be 236 * available from the module system. 237 */ 238 long getSupplementaryFlags(ClassSymbol c) { 239 if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) { 240 return 0; 241 } 242 243 if (supplementaryFlags == null) { 244 supplementaryFlags = new HashMap<>(); 245 } 246 247 Long flags = supplementaryFlags.get(c.packge()); 248 if (flags == null) { 249 long newFlags = 0; 250 try { 251 JRTIndex.CtSym ctSym = jrtIndex.getCtSym(c.packge().flatName()); 252 Profile minProfile = Profile.DEFAULT; 253 if (ctSym.proprietary) 254 newFlags |= PROPRIETARY; 255 if (ctSym.minProfile != null) 256 minProfile = Profile.lookup(ctSym.minProfile); 257 if (profile != Profile.DEFAULT && minProfile.value > profile.value) { 258 newFlags |= NOT_IN_PROFILE; 259 } 260 } catch (IOException ignore) { 261 } 262 supplementaryFlags.put(c.packge(), flags = newFlags); 263 } 264 return flags; 265 } 266 267 private Map<PackageSymbol, Long> supplementaryFlags; 268 269 /************************************************************************ 270 * Loading Classes 271 ***********************************************************************/ 272 273 /** Completion for classes to be loaded. Before a class is loaded 274 * we make sure its enclosing class (if any) is loaded. 275 */ 276 private void complete(Symbol sym) throws CompletionFailure { 277 if (sym.kind == TYP) { 278 try { 279 ClassSymbol c = (ClassSymbol) sym; 280 dependencies.push(c, CompletionCause.CLASS_READER); 281 annotate.blockAnnotations(); 282 c.members_field = new Scope.ErrorScope(c); // make sure it's always defined 283 completeOwners(c.owner); 284 completeEnclosing(c); 285 fillIn(c); 286 } finally { 287 annotate.unblockAnnotationsNoFlush(); 288 dependencies.pop(); 289 } 290 } else if (sym.kind == PCK) { 291 PackageSymbol p = (PackageSymbol)sym; 292 try { 293 fillIn(p); 294 } catch (IOException ex) { 295 throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex); 296 } 297 } 298 if (!reader.filling) 299 annotate.flush(); // finish attaching annotations 300 } 301 302 /** complete up through the enclosing package. */ 303 private void completeOwners(Symbol o) { 304 if (o.kind != PCK) completeOwners(o.owner); 305 o.complete(); 306 } 307 308 /** 309 * Tries to complete lexically enclosing classes if c looks like a 310 * nested class. This is similar to completeOwners but handles 311 * the situation when a nested class is accessed directly as it is 312 * possible with the Tree API or javax.lang.model.*. 313 */ 314 private void completeEnclosing(ClassSymbol c) { 315 if (c.owner.kind == PCK) { 316 Symbol owner = c.owner; 317 for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) { 318 Symbol encl = owner.members().findFirst(name); 319 if (encl == null) 320 encl = syms.getClass(c.packge().modle, TypeSymbol.formFlatName(name, owner)); 321 if (encl != null) 322 encl.complete(); 323 } 324 } 325 } 326 327 /** Fill in definition of class `c' from corresponding class or 328 * source file. 329 */ 330 void fillIn(ClassSymbol c) { 331 if (completionFailureName == c.fullname) { 332 throw new CompletionFailure(c, "user-selected completion failure by class name"); 333 } 334 currentOwner = c; 335 JavaFileObject classfile = c.classfile; 336 if (classfile != null) { 337 JavaFileObject previousClassFile = currentClassFile; 338 try { 339 if (reader.filling) { 340 Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile); 341 } 342 currentClassFile = classfile; 343 if (verbose) { 344 log.printVerbose("loading", currentClassFile.getName()); 345 } 346 if (classfile.getKind() == JavaFileObject.Kind.CLASS || 347 classfile.getKind() == JavaFileObject.Kind.OTHER) { 348 reader.readClassFile(c); 349 c.flags_field |= getSupplementaryFlags(c); 350 } else { 351 if (!sourceCompleter.isTerminal()) { 352 sourceCompleter.complete(c); 353 } else { 354 throw new IllegalStateException("Source completer required to read " 355 + classfile.toUri()); 356 } 357 } 358 } finally { 359 currentClassFile = previousClassFile; 360 } 361 } else { 362 throw classFileNotFound(c); 363 } 364 } 365 // where 366 private CompletionFailure classFileNotFound(ClassSymbol c) { 367 JCDiagnostic diag = 368 diagFactory.fragment("class.file.not.found", c.flatname); 369 return newCompletionFailure(c, diag); 370 } 371 /** Static factory for CompletionFailure objects. 372 * In practice, only one can be used at a time, so we share one 373 * to reduce the expense of allocating new exception objects. 374 */ 375 private CompletionFailure newCompletionFailure(TypeSymbol c, 376 JCDiagnostic diag) { 377 if (!cacheCompletionFailure) { 378 // log.warning("proc.messager", 379 // Log.getLocalizedString("class.file.not.found", c.flatname)); 380 // c.debug.printStackTrace(); 381 return new CompletionFailure(c, diag); 382 } else { 383 CompletionFailure result = cachedCompletionFailure; 384 result.sym = c; 385 result.diag = diag; 386 return result; 387 } 388 } 389 private final CompletionFailure cachedCompletionFailure = 390 new CompletionFailure(null, (JCDiagnostic) null); 391 { 392 cachedCompletionFailure.setStackTrace(new StackTraceElement[0]); 393 } 394 395 396 /** Load a toplevel class with given fully qualified name 397 * The class is entered into `classes' only if load was successful. 398 */ 399 public ClassSymbol loadClass(ModuleSymbol msym, Name flatname) throws CompletionFailure { 400 Assert.checkNonNull(msym); 401 Name packageName = Convert.packagePart(flatname); 402 PackageSymbol ps = syms.lookupPackage(msym, packageName); 403 404 Assert.checkNonNull(ps.modle, () -> "msym=" + msym + "; flatName=" + flatname); 405 406 boolean absent = syms.getClass(ps.modle, flatname) == null; 407 ClassSymbol c = syms.enterClass(ps.modle, flatname); 408 409 if (c.members_field == null) { 410 try { 411 c.complete(); 412 } catch (CompletionFailure ex) { 413 if (absent) syms.removeClass(ps.modle, flatname); 414 throw ex; 415 } 416 } 417 return c; 418 } 419 420 /************************************************************************ 421 * Loading Packages 422 ***********************************************************************/ 423 424 /** Include class corresponding to given class file in package, 425 * unless (1) we already have one the same kind (.class or .java), or 426 * (2) we have one of the other kind, and the given class file 427 * is older. 428 */ 429 protected void includeClassFile(PackageSymbol p, JavaFileObject file) { 430 if ((p.flags_field & EXISTS) == 0) 431 for (Symbol q = p; q != null && q.kind == PCK; q = q.owner) 432 q.flags_field |= EXISTS; 433 JavaFileObject.Kind kind = file.getKind(); 434 int seen; 435 if (kind == JavaFileObject.Kind.CLASS || kind == JavaFileObject.Kind.OTHER) 436 seen = CLASS_SEEN; 437 else 438 seen = SOURCE_SEEN; 439 String binaryName = fileManager.inferBinaryName(currentLoc, file); 440 int lastDot = binaryName.lastIndexOf("."); 441 Name classname = names.fromString(binaryName.substring(lastDot + 1)); 442 boolean isPkgInfo = classname == names.package_info; 443 ClassSymbol c = isPkgInfo 444 ? p.package_info 445 : (ClassSymbol) p.members_field.findFirst(classname); 446 if (c == null) { 447 c = syms.enterClass(p.modle, classname, p); 448 if (c.classfile == null) // only update the file if's it's newly created 449 c.classfile = file; 450 if (isPkgInfo) { 451 p.package_info = c; 452 } else { 453 if (c.owner == p) // it might be an inner class 454 p.members_field.enter(c); 455 } 456 } else if (!preferCurrent && c.classfile != null && (c.flags_field & seen) == 0) { 457 // if c.classfile == null, we are currently compiling this class 458 // and no further action is necessary. 459 // if (c.flags_field & seen) != 0, we have already encountered 460 // a file of the same kind; again no further action is necessary. 461 if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0) 462 c.classfile = preferredFileObject(file, c.classfile); 463 } 464 c.flags_field |= seen; 465 } 466 467 /** Implement policy to choose to derive information from a source 468 * file or a class file when both are present. May be overridden 469 * by subclasses. 470 */ 471 protected JavaFileObject preferredFileObject(JavaFileObject a, 472 JavaFileObject b) { 473 474 if (preferSource) 475 return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b; 476 else { 477 long adate = a.getLastModified(); 478 long bdate = b.getLastModified(); 479 // 6449326: policy for bad lastModifiedTime in ClassReader 480 //assert adate >= 0 && bdate >= 0; 481 return (adate > bdate) ? a : b; 482 } 483 } 484 485 /** 486 * specifies types of files to be read when filling in a package symbol 487 */ 488 // Note: overridden by JavadocClassFinder 489 protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() { 490 return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE); 491 } 492 493 /** 494 * this is used to support javadoc 495 */ 496 protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) { 497 } 498 499 protected Location currentLoc; // FIXME 500 501 private boolean verbosePath = true; 502 503 // Set to true when the currently selected file should be kept 504 private boolean preferCurrent; 505 506 /** Load directory of package into members scope. 507 */ 508 private void fillIn(PackageSymbol p) throws IOException { 509 if (p.members_field == null) 510 p.members_field = WriteableScope.create(p); 511 512 ModuleSymbol msym = p.modle; 513 514 Assert.checkNonNull(msym, p::toString); 515 516 msym.complete(); 517 518 if (msym == syms.noModule) { 519 preferCurrent = false; 520 if (userPathsFirst) { 521 scanUserPaths(p, true); 522 preferCurrent = true; 523 scanPlatformPath(p); 524 } else { 525 scanPlatformPath(p); 526 scanUserPaths(p, true); 527 } 528 } else if (msym.classLocation == StandardLocation.CLASS_PATH) { 529 scanUserPaths(p, msym.sourceLocation == StandardLocation.SOURCE_PATH); 530 } else { 531 scanModulePaths(p, msym); 532 } 533 } 534 535 // TODO: for now, this is a much simplified form of scanUserPaths 536 // and (deliberately) does not default sourcepath to classpath. 537 // But, we need to think about retaining existing behavior for 538 // -classpath and -sourcepath for single module mode. 539 // One plausible solution is to detect if the module's sourceLocation 540 // is the same as the module's classLocation. 541 private void scanModulePaths(PackageSymbol p, ModuleSymbol msym) throws IOException { 542 Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); 543 544 Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds); 545 classKinds.remove(JavaFileObject.Kind.SOURCE); 546 boolean wantClassFiles = !classKinds.isEmpty(); 547 548 Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds); 549 sourceKinds.remove(JavaFileObject.Kind.CLASS); 550 boolean wantSourceFiles = !sourceKinds.isEmpty(); 551 552 String packageName = p.fullname.toString(); 553 554 Location classLocn = msym.classLocation; 555 Location sourceLocn = msym.sourceLocation; 556 557 if (wantClassFiles && (classLocn != null)) { 558 fillIn(p, classLocn, 559 list(classLocn, 560 p, 561 packageName, 562 classKinds)); 563 } 564 if (wantSourceFiles && (sourceLocn != null)) { 565 fillIn(p, sourceLocn, 566 list(sourceLocn, 567 p, 568 packageName, 569 sourceKinds)); 570 } 571 } 572 573 /** 574 * Scans class path and source path for files in given package. 575 */ 576 private void scanUserPaths(PackageSymbol p, boolean includeSourcePath) throws IOException { 577 Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); 578 579 Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds); 580 classKinds.remove(JavaFileObject.Kind.SOURCE); 581 boolean wantClassFiles = !classKinds.isEmpty(); 582 583 Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds); 584 sourceKinds.remove(JavaFileObject.Kind.CLASS); 585 boolean wantSourceFiles = !sourceKinds.isEmpty(); 586 587 boolean haveSourcePath = includeSourcePath && fileManager.hasLocation(SOURCE_PATH); 588 589 if (verbose && verbosePath) { 590 if (fileManager instanceof StandardJavaFileManager) { 591 StandardJavaFileManager fm = (StandardJavaFileManager)fileManager; 592 if (haveSourcePath && wantSourceFiles) { 593 List<Path> path = List.nil(); 594 for (Path sourcePath : fm.getLocationAsPaths(SOURCE_PATH)) { 595 path = path.prepend(sourcePath); 596 } 597 log.printVerbose("sourcepath", path.reverse().toString()); 598 } else if (wantSourceFiles) { 599 List<Path> path = List.nil(); 600 for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { 601 path = path.prepend(classPath); 602 } 603 log.printVerbose("sourcepath", path.reverse().toString()); 604 } 605 if (wantClassFiles) { 606 List<Path> path = List.nil(); 607 for (Path platformPath : fm.getLocationAsPaths(PLATFORM_CLASS_PATH)) { 608 path = path.prepend(platformPath); 609 } 610 for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { 611 path = path.prepend(classPath); 612 } 613 log.printVerbose("classpath", path.reverse().toString()); 614 } 615 } 616 } 617 618 String packageName = p.fullname.toString(); 619 if (wantSourceFiles && !haveSourcePath) { 620 fillIn(p, CLASS_PATH, 621 list(CLASS_PATH, 622 p, 623 packageName, 624 kinds)); 625 } else { 626 if (wantClassFiles) 627 fillIn(p, CLASS_PATH, 628 list(CLASS_PATH, 629 p, 630 packageName, 631 classKinds)); 632 if (wantSourceFiles) 633 fillIn(p, SOURCE_PATH, 634 list(SOURCE_PATH, 635 p, 636 packageName, 637 sourceKinds)); 638 } 639 } 640 641 /** 642 * Scans platform class path for files in given package. 643 */ 644 private void scanPlatformPath(PackageSymbol p) throws IOException { 645 fillIn(p, PLATFORM_CLASS_PATH, 646 list(PLATFORM_CLASS_PATH, 647 p, 648 p.fullname.toString(), 649 allowSigFiles ? EnumSet.of(JavaFileObject.Kind.CLASS, 650 JavaFileObject.Kind.OTHER) 651 : EnumSet.of(JavaFileObject.Kind.CLASS))); 652 } 653 // where 654 @SuppressWarnings("fallthrough") 655 private void fillIn(PackageSymbol p, 656 Location location, 657 Iterable<JavaFileObject> files) 658 { 659 currentLoc = location; 660 for (JavaFileObject fo : files) { 661 switch (fo.getKind()) { 662 case OTHER: 663 if (!isSigFile(location, fo)) { 664 extraFileActions(p, fo); 665 break; 666 } 667 //intentional fall-through: 668 case CLASS: 669 case SOURCE: { 670 // TODO pass binaryName to includeClassFile 671 String binaryName = fileManager.inferBinaryName(currentLoc, fo); 672 String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1); 673 if (SourceVersion.isIdentifier(simpleName) || 674 simpleName.equals("package-info")) 675 includeClassFile(p, fo); 676 break; 677 } 678 default: 679 extraFileActions(p, fo); 680 break; 681 } 682 } 683 } 684 685 boolean isSigFile(Location location, JavaFileObject fo) { 686 return location == PLATFORM_CLASS_PATH && 687 allowSigFiles && 688 fo.getName().endsWith(".sig"); 689 } 690 691 Iterable<JavaFileObject> list(Location location, 692 PackageSymbol p, 693 String packageName, 694 Set<Kind> kinds) throws IOException { 695 Iterable<JavaFileObject> listed = fileManager.list(location, 696 packageName, 697 EnumSet.allOf(Kind.class), 698 false); 699 return () -> new Iterator<JavaFileObject>() { 700 private final Iterator<JavaFileObject> original = listed.iterator(); 701 private JavaFileObject next; 702 @Override 703 public boolean hasNext() { 704 if (next == null) { 705 while (original.hasNext()) { 706 JavaFileObject fo = original.next(); 707 708 if (fo.getKind() != Kind.CLASS && 709 fo.getKind() != Kind.SOURCE && 710 !isSigFile(currentLoc, fo)) { 711 p.flags_field |= Flags.HAS_RESOURCE; 712 } 713 714 if (kinds.contains(fo.getKind())) { 715 next = fo; 716 break; 717 } 718 } 719 } 720 return next != null; 721 } 722 723 @Override 724 public JavaFileObject next() { 725 if (!hasNext()) 726 throw new NoSuchElementException(); 727 JavaFileObject result = next; 728 next = null; 729 return result; 730 } 731 732 }; 733 } 734 735 /** 736 * Used for bad class definition files, such as bad .class files or 737 * for .java files with unexpected package or class names. 738 */ 739 public static class BadClassFile extends CompletionFailure { 740 private static final long serialVersionUID = 0; 741 742 public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag, 743 JCDiagnostic.Factory diagFactory) { 744 super(sym, createBadClassFileDiagnostic(file, diag, diagFactory)); 745 } 746 // where 747 private static JCDiagnostic createBadClassFileDiagnostic( 748 JavaFileObject file, JCDiagnostic diag, JCDiagnostic.Factory diagFactory) { 749 String key = (file.getKind() == JavaFileObject.Kind.SOURCE 750 ? "bad.source.file.header" : "bad.class.file.header"); 751 return diagFactory.fragment(key, file, diag); 752 } 753 } 754 755 public static class BadEnclosingMethodAttr extends BadClassFile { 756 private static final long serialVersionUID = 0; 757 758 public BadEnclosingMethodAttr(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag, 759 JCDiagnostic.Factory diagFactory) { 760 super(sym, file, diag, diagFactory); 761 } 762 } 763 }