ClassFinder.java revision 3634:5a2d38a840cc
1271743Sbz/* 2271743Sbz * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. 3271743Sbz * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4271743Sbz * 5271743Sbz * This code is free software; you can redistribute it and/or modify it 6271743Sbz * under the terms of the GNU General Public License version 2 only, as 7271743Sbz * published by the Free Software Foundation. Oracle designates this 8271743Sbz * particular file as subject to the "Classpath" exception as provided 9271743Sbz * by Oracle in the LICENSE file that accompanied this code. 10271743Sbz * 11271743Sbz * This code is distributed in the hope that it will be useful, but WITHOUT 12271743Sbz * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13271743Sbz * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14271743Sbz * version 2 for more details (a copy is included in the LICENSE file that 15271743Sbz * accompanied this code). 16271743Sbz * 17271743Sbz * You should have received a copy of the GNU General Public License version 18271743Sbz * 2 along with this work; if not, write to the Free Software Foundation, 19271743Sbz * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20271743Sbz * 21271743Sbz * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22271743Sbz * or visit www.oracle.com if you need additional information or have any 23271743Sbz * questions. 24271743Sbz */ 25271743Sbz 26271743Sbzpackage com.sun.tools.javac.code; 27271743Sbz 28271743Sbzimport java.io.IOException; 29271743Sbzimport java.nio.file.Path; 30271743Sbzimport java.util.EnumSet; 31271743Sbzimport java.util.HashMap; 32271743Sbzimport java.util.Map; 33271743Sbzimport java.util.Set; 34271743Sbz 35271743Sbzimport javax.lang.model.SourceVersion; 36271743Sbzimport javax.tools.JavaFileManager; 37271743Sbzimport javax.tools.JavaFileManager.Location; 38271743Sbzimport javax.tools.JavaFileObject; 39271743Sbzimport javax.tools.StandardJavaFileManager; 40271743Sbzimport javax.tools.StandardLocation; 41271743Sbz 42271743Sbzimport com.sun.tools.javac.code.Scope.WriteableScope; 43271743Sbzimport com.sun.tools.javac.code.Symbol.ClassSymbol; 44271743Sbzimport com.sun.tools.javac.code.Symbol.Completer; 45271743Sbzimport com.sun.tools.javac.code.Symbol.CompletionFailure; 46271743Sbzimport com.sun.tools.javac.code.Symbol.ModuleSymbol; 47271743Sbzimport com.sun.tools.javac.code.Symbol.PackageSymbol; 48271743Sbzimport com.sun.tools.javac.code.Symbol.TypeSymbol; 49271743Sbzimport com.sun.tools.javac.comp.Annotate; 50271743Sbzimport com.sun.tools.javac.file.JRTIndex; 51271743Sbzimport com.sun.tools.javac.file.JavacFileManager; 52271743Sbzimport com.sun.tools.javac.jvm.ClassReader; 53271743Sbzimport com.sun.tools.javac.jvm.Profile; 54271743Sbzimport com.sun.tools.javac.main.Option; 55271743Sbzimport com.sun.tools.javac.platform.PlatformDescription; 56271743Sbzimport com.sun.tools.javac.util.*; 57271743Sbz 58271743Sbzimport static javax.tools.StandardLocation.*; 59271743Sbz 60292744Sdchaginimport static com.sun.tools.javac.code.Flags.*; 61292744Sdchaginimport static com.sun.tools.javac.code.Kinds.Kind.*; 62271743Sbz 63283476Sdchaginimport com.sun.tools.javac.util.Dependencies.CompletionCause; 64271743Sbz 65271743Sbz/** 66271743Sbz * This class provides operations to locate class definitions 67271743Sbz * from the source and class files on the paths provided to javac. 68271743Sbz * 69271743Sbz * <p><b>This is NOT part of any supported API. 70271743Sbz * If you write code that depends on this, you do so at your own risk. 71271743Sbz * This code and its internal interfaces are subject to change or 72271743Sbz * deletion without notice.</b> 73271743Sbz */ 74271743Sbzpublic class ClassFinder { 75271743Sbz /** The context key for the class finder. */ 76271743Sbz protected static final Context.Key<ClassFinder> classFinderKey = new Context.Key<>(); 77271743Sbz 78292744Sdchagin ClassReader reader; 79292744Sdchagin 80271743Sbz private final Annotate annotate; 81271743Sbz 82283476Sdchagin /** Switch: verbose output. 83271743Sbz */ 84271743Sbz boolean verbose; 85271743Sbz 86271743Sbz /** 87271743Sbz * Switch: cache completion failures unless -XDdev is used 88271743Sbz */ 89271743Sbz private boolean cacheCompletionFailure; 90271743Sbz 91271743Sbz /** 92271743Sbz * Switch: prefer source files instead of newer when both source 93271743Sbz * and class are available 94271743Sbz **/ 95271743Sbz protected boolean preferSource; 96283464Sdchagin 97271743Sbz /** 98271743Sbz * Switch: Search classpath and sourcepath for classes before the 99271743Sbz * bootclasspath 100271743Sbz */ 101271743Sbz protected boolean userPathsFirst; 102271743Sbz 103271743Sbz /** 104271743Sbz * Switch: should read OTHER classfiles (.sig files) from PLATFORM_CLASS_PATH. 105271743Sbz */ 106271743Sbz private boolean allowSigFiles; 107271743Sbz 108271743Sbz /** The log to use for verbose output 109271743Sbz */ 110283464Sdchagin final Log log; 111271743Sbz 112271743Sbz /** The symbol table. */ 113283464Sdchagin Symtab syms; 114271743Sbz 115271743Sbz /** The name table. */ 116271743Sbz final Names names; 117271743Sbz 118271743Sbz /** Force a completion failure on this name 119271743Sbz */ 120271743Sbz final Name completionFailureName; 121271743Sbz 122271743Sbz /** Access to files 123271743Sbz */ 124271743Sbz private final JavaFileManager fileManager; 125271743Sbz 126271743Sbz /** Dependency tracker 127271743Sbz */ 128271743Sbz private final Dependencies dependencies; 129271743Sbz 130271743Sbz /** Factory for diagnostics 131271743Sbz */ 132271743Sbz JCDiagnostic.Factory diagFactory; 133271743Sbz 134271743Sbz /** Can be reassigned from outside: 135271743Sbz * the completer to be used for ".java" files. If this remains unassigned 136271743Sbz * ".java" files will not be loaded. 137271743Sbz */ 138271743Sbz public Completer sourceCompleter = Completer.NULL_COMPLETER; 139271743Sbz 140271743Sbz /** The path name of the class file currently being read. 141271743Sbz */ 142271743Sbz protected JavaFileObject currentClassFile = null; 143271743Sbz 144271743Sbz /** The class or method currently being read. 145271743Sbz */ 146271743Sbz protected Symbol currentOwner = null; 147271743Sbz 148271743Sbz /** 149271743Sbz * The currently selected profile. 150271743Sbz */ 151271743Sbz private final Profile profile; 152271743Sbz 153271743Sbz /** 154271743Sbz * Use direct access to the JRTIndex to access the temporary 155271743Sbz * replacement for the info that used to be in ct.sym. 156271743Sbz * In time, this will go away and be replaced by the module system. 157271743Sbz */ 158271743Sbz private final JRTIndex jrtIndex; 159271743Sbz 160271743Sbz /** 161271743Sbz * Completer that delegates to the complete-method of this class. 162271743Sbz */ 163271743Sbz private final Completer thisCompleter = new Completer() { 164271743Sbz @Override 165271743Sbz public void complete(Symbol sym) throws CompletionFailure { 166271743Sbz ClassFinder.this.complete(sym); 167271743Sbz } 168271743Sbz }; 169271743Sbz 170 public Completer getCompleter() { 171 return thisCompleter; 172 } 173 174 /** Get the ClassFinder instance for this invocation. */ 175 public static ClassFinder instance(Context context) { 176 ClassFinder instance = context.get(classFinderKey); 177 if (instance == null) 178 instance = new ClassFinder(context); 179 return instance; 180 } 181 182 /** Construct a new class finder. */ 183 protected ClassFinder(Context context) { 184 context.put(classFinderKey, this); 185 reader = ClassReader.instance(context); 186 names = Names.instance(context); 187 syms = Symtab.instance(context); 188 fileManager = context.get(JavaFileManager.class); 189 dependencies = Dependencies.instance(context); 190 if (fileManager == null) 191 throw new AssertionError("FileManager initialization error"); 192 diagFactory = JCDiagnostic.Factory.instance(context); 193 194 log = Log.instance(context); 195 annotate = Annotate.instance(context); 196 197 Options options = Options.instance(context); 198 verbose = options.isSet(Option.VERBOSE); 199 cacheCompletionFailure = options.isUnset("dev"); 200 preferSource = "source".equals(options.get("-Xprefer")); 201 userPathsFirst = options.isSet(Option.XXUSERPATHSFIRST); 202 allowSigFiles = context.get(PlatformDescription.class) != null; 203 204 completionFailureName = 205 options.isSet("failcomplete") 206 ? names.fromString(options.get("failcomplete")) 207 : null; 208 209 // Temporary, until more info is available from the module system. 210 boolean useCtProps; 211 JavaFileManager fm = context.get(JavaFileManager.class); 212 if (fm instanceof JavacFileManager) { 213 JavacFileManager jfm = (JavacFileManager) fm; 214 useCtProps = jfm.isDefaultBootClassPath() && jfm.isSymbolFileEnabled(); 215 } else if (fm.getClass().getName().equals("com.sun.tools.sjavac.comp.SmartFileManager")) { 216 useCtProps = !options.isSet("ignore.symbol.file"); 217 } else { 218 useCtProps = false; 219 } 220 jrtIndex = useCtProps && JRTIndex.isAvailable() ? JRTIndex.getSharedInstance() : null; 221 222 profile = Profile.instance(context); 223 } 224 225 226/************************************************************************ 227 * Temporary ct.sym replacement 228 * 229 * The following code is a temporary substitute for the ct.sym mechanism 230 * used in JDK 6 thru JDK 8. 231 * This mechanism will eventually be superseded by the Jigsaw module system. 232 ***********************************************************************/ 233 234 /** 235 * Returns any extra flags for a class symbol. 236 * This information used to be provided using private annotations 237 * in the class file in ct.sym; in time, this information will be 238 * available from the module system. 239 */ 240 long getSupplementaryFlags(ClassSymbol c) { 241 if (jrtIndex == null || !jrtIndex.isInJRT(c.classfile) || c.name == names.module_info) { 242 return 0; 243 } 244 245 if (supplementaryFlags == null) { 246 supplementaryFlags = new HashMap<>(); 247 } 248 249 Long flags = supplementaryFlags.get(c.packge()); 250 if (flags == null) { 251 long newFlags = 0; 252 try { 253 JRTIndex.CtSym ctSym = jrtIndex.getCtSym(c.packge().flatName()); 254 Profile minProfile = Profile.DEFAULT; 255 if (ctSym.proprietary) 256 newFlags |= PROPRIETARY; 257 if (ctSym.minProfile != null) 258 minProfile = Profile.lookup(ctSym.minProfile); 259 if (profile != Profile.DEFAULT && minProfile.value > profile.value) { 260 newFlags |= NOT_IN_PROFILE; 261 } 262 } catch (IOException ignore) { 263 } 264 supplementaryFlags.put(c.packge(), flags = newFlags); 265 } 266 return flags; 267 } 268 269 private Map<PackageSymbol, Long> supplementaryFlags; 270 271/************************************************************************ 272 * Loading Classes 273 ***********************************************************************/ 274 275 /** Completion for classes to be loaded. Before a class is loaded 276 * we make sure its enclosing class (if any) is loaded. 277 */ 278 private void complete(Symbol sym) throws CompletionFailure { 279 if (sym.kind == TYP) { 280 try { 281 ClassSymbol c = (ClassSymbol) sym; 282 dependencies.push(c, CompletionCause.CLASS_READER); 283 annotate.blockAnnotations(); 284 c.members_field = new Scope.ErrorScope(c); // make sure it's always defined 285 completeOwners(c.owner); 286 completeEnclosing(c); 287 fillIn(c); 288 } finally { 289 annotate.unblockAnnotationsNoFlush(); 290 dependencies.pop(); 291 } 292 } else if (sym.kind == PCK) { 293 PackageSymbol p = (PackageSymbol)sym; 294 try { 295 fillIn(p); 296 } catch (IOException ex) { 297 throw new CompletionFailure(sym, ex.getLocalizedMessage()).initCause(ex); 298 } 299 } 300 if (!reader.filling) 301 annotate.flush(); // finish attaching annotations 302 } 303 304 /** complete up through the enclosing package. */ 305 private void completeOwners(Symbol o) { 306 if (o.kind != PCK) completeOwners(o.owner); 307 o.complete(); 308 } 309 310 /** 311 * Tries to complete lexically enclosing classes if c looks like a 312 * nested class. This is similar to completeOwners but handles 313 * the situation when a nested class is accessed directly as it is 314 * possible with the Tree API or javax.lang.model.*. 315 */ 316 private void completeEnclosing(ClassSymbol c) { 317 if (c.owner.kind == PCK) { 318 Symbol owner = c.owner; 319 for (Name name : Convert.enclosingCandidates(Convert.shortName(c.name))) { 320 Symbol encl = owner.members().findFirst(name); 321 if (encl == null) 322 encl = syms.getClass(c.packge().modle, TypeSymbol.formFlatName(name, owner)); 323 if (encl != null) 324 encl.complete(); 325 } 326 } 327 } 328 329 /** Fill in definition of class `c' from corresponding class or 330 * source file. 331 */ 332 void fillIn(ClassSymbol c) { 333 if (completionFailureName == c.fullname) { 334 throw new CompletionFailure(c, "user-selected completion failure by class name"); 335 } 336 currentOwner = c; 337 JavaFileObject classfile = c.classfile; 338 if (classfile != null) { 339 JavaFileObject previousClassFile = currentClassFile; 340 try { 341 if (reader.filling) { 342 Assert.error("Filling " + classfile.toUri() + " during " + previousClassFile); 343 } 344 currentClassFile = classfile; 345 if (verbose) { 346 log.printVerbose("loading", currentClassFile.getName()); 347 } 348 if (classfile.getKind() == JavaFileObject.Kind.CLASS || 349 classfile.getKind() == JavaFileObject.Kind.OTHER) { 350 reader.readClassFile(c); 351 c.flags_field |= getSupplementaryFlags(c); 352 } else { 353 if (!sourceCompleter.isTerminal()) { 354 sourceCompleter.complete(c); 355 } else { 356 throw new IllegalStateException("Source completer required to read " 357 + classfile.toUri()); 358 } 359 } 360 } finally { 361 currentClassFile = previousClassFile; 362 } 363 } else { 364 throw classFileNotFound(c); 365 } 366 } 367 // where 368 private CompletionFailure classFileNotFound(ClassSymbol c) { 369 JCDiagnostic diag = 370 diagFactory.fragment("class.file.not.found", c.flatname); 371 return newCompletionFailure(c, diag); 372 } 373 /** Static factory for CompletionFailure objects. 374 * In practice, only one can be used at a time, so we share one 375 * to reduce the expense of allocating new exception objects. 376 */ 377 private CompletionFailure newCompletionFailure(TypeSymbol c, 378 JCDiagnostic diag) { 379 if (!cacheCompletionFailure) { 380 // log.warning("proc.messager", 381 // Log.getLocalizedString("class.file.not.found", c.flatname)); 382 // c.debug.printStackTrace(); 383 return new CompletionFailure(c, diag); 384 } else { 385 CompletionFailure result = cachedCompletionFailure; 386 result.sym = c; 387 result.diag = diag; 388 return result; 389 } 390 } 391 private final CompletionFailure cachedCompletionFailure = 392 new CompletionFailure(null, (JCDiagnostic) null); 393 { 394 cachedCompletionFailure.setStackTrace(new StackTraceElement[0]); 395 } 396 397 398 /** Load a toplevel class with given fully qualified name 399 * The class is entered into `classes' only if load was successful. 400 */ 401 public ClassSymbol loadClass(ModuleSymbol msym, Name flatname) throws CompletionFailure { 402 Assert.checkNonNull(msym); 403 Name packageName = Convert.packagePart(flatname); 404 PackageSymbol ps = syms.lookupPackage(msym, packageName); 405 406 Assert.checkNonNull(ps.modle, () -> "msym=" + msym + "; flatName=" + flatname); 407 408 boolean absent = syms.getClass(ps.modle, flatname) == null; 409 ClassSymbol c = syms.enterClass(ps.modle, flatname); 410 411 if (c.members_field == null) { 412 try { 413 c.complete(); 414 } catch (CompletionFailure ex) { 415 if (absent) syms.removeClass(ps.modle, flatname); 416 throw ex; 417 } 418 } 419 return c; 420 } 421 422/************************************************************************ 423 * Loading Packages 424 ***********************************************************************/ 425 426 /** Include class corresponding to given class file in package, 427 * unless (1) we already have one the same kind (.class or .java), or 428 * (2) we have one of the other kind, and the given class file 429 * is older. 430 */ 431 protected void includeClassFile(PackageSymbol p, JavaFileObject file) { 432 if ((p.flags_field & EXISTS) == 0) 433 for (Symbol q = p; q != null && q.kind == PCK; q = q.owner) 434 q.flags_field |= EXISTS; 435 JavaFileObject.Kind kind = file.getKind(); 436 int seen; 437 if (kind == JavaFileObject.Kind.CLASS || kind == JavaFileObject.Kind.OTHER) 438 seen = CLASS_SEEN; 439 else 440 seen = SOURCE_SEEN; 441 String binaryName = fileManager.inferBinaryName(currentLoc, file); 442 int lastDot = binaryName.lastIndexOf("."); 443 Name classname = names.fromString(binaryName.substring(lastDot + 1)); 444 boolean isPkgInfo = classname == names.package_info; 445 ClassSymbol c = isPkgInfo 446 ? p.package_info 447 : (ClassSymbol) p.members_field.findFirst(classname); 448 if (c == null) { 449 c = syms.enterClass(p.modle, classname, p); 450 if (c.classfile == null) // only update the file if's it's newly created 451 c.classfile = file; 452 if (isPkgInfo) { 453 p.package_info = c; 454 } else { 455 if (c.owner == p) // it might be an inner class 456 p.members_field.enter(c); 457 } 458 } else if (!preferCurrent && c.classfile != null && (c.flags_field & seen) == 0) { 459 // if c.classfile == null, we are currently compiling this class 460 // and no further action is necessary. 461 // if (c.flags_field & seen) != 0, we have already encountered 462 // a file of the same kind; again no further action is necessary. 463 if ((c.flags_field & (CLASS_SEEN | SOURCE_SEEN)) != 0) 464 c.classfile = preferredFileObject(file, c.classfile); 465 } 466 c.flags_field |= seen; 467 } 468 469 /** Implement policy to choose to derive information from a source 470 * file or a class file when both are present. May be overridden 471 * by subclasses. 472 */ 473 protected JavaFileObject preferredFileObject(JavaFileObject a, 474 JavaFileObject b) { 475 476 if (preferSource) 477 return (a.getKind() == JavaFileObject.Kind.SOURCE) ? a : b; 478 else { 479 long adate = a.getLastModified(); 480 long bdate = b.getLastModified(); 481 // 6449326: policy for bad lastModifiedTime in ClassReader 482 //assert adate >= 0 && bdate >= 0; 483 return (adate > bdate) ? a : b; 484 } 485 } 486 487 /** 488 * specifies types of files to be read when filling in a package symbol 489 */ 490 // Note: overridden by JavadocClassFinder 491 protected EnumSet<JavaFileObject.Kind> getPackageFileKinds() { 492 return EnumSet.of(JavaFileObject.Kind.CLASS, JavaFileObject.Kind.SOURCE); 493 } 494 495 /** 496 * this is used to support javadoc 497 */ 498 protected void extraFileActions(PackageSymbol pack, JavaFileObject fe) { 499 } 500 501 protected Location currentLoc; // FIXME 502 503 private boolean verbosePath = true; 504 505 // Set to true when the currently selected file should be kept 506 private boolean preferCurrent; 507 508 /** Load directory of package into members scope. 509 */ 510 private void fillIn(PackageSymbol p) throws IOException { 511 if (p.members_field == null) 512 p.members_field = WriteableScope.create(p); 513 514 ModuleSymbol msym = p.modle; 515 516 Assert.checkNonNull(msym, () -> p.toString()); 517 518 msym.complete(); 519 520 if (msym == syms.noModule) { 521 preferCurrent = false; 522 if (userPathsFirst) { 523 scanUserPaths(p, true); 524 preferCurrent = true; 525 scanPlatformPath(p); 526 } else { 527 scanPlatformPath(p); 528 scanUserPaths(p, true); 529 } 530 } else if (msym.classLocation == StandardLocation.CLASS_PATH) { 531 scanUserPaths(p, msym.sourceLocation == StandardLocation.SOURCE_PATH); 532 } else { 533 scanModulePaths(p, msym); 534 } 535 } 536 537 // TODO: for now, this is a much simplified form of scanUserPaths 538 // and (deliberately) does not default sourcepath to classpath. 539 // But, we need to think about retaining existing behavior for 540 // -classpath and -sourcepath for single module mode. 541 // One plausible solution is to detect if the module's sourceLocation 542 // is the same as the module's classLocation. 543 private void scanModulePaths(PackageSymbol p, ModuleSymbol msym) throws IOException { 544 Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); 545 546 Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds); 547 classKinds.remove(JavaFileObject.Kind.SOURCE); 548 boolean wantClassFiles = !classKinds.isEmpty(); 549 550 Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds); 551 sourceKinds.remove(JavaFileObject.Kind.CLASS); 552 boolean wantSourceFiles = !sourceKinds.isEmpty(); 553 554 String packageName = p.fullname.toString(); 555 556 Location classLocn = msym.classLocation; 557 Location sourceLocn = msym.sourceLocation; 558 559 if (wantClassFiles && (classLocn != null)) { 560 fillIn(p, classLocn, 561 fileManager.list(classLocn, 562 packageName, 563 classKinds, 564 false)); 565 } 566 if (wantSourceFiles && (sourceLocn != null)) { 567 fillIn(p, sourceLocn, 568 fileManager.list(sourceLocn, 569 packageName, 570 sourceKinds, 571 false)); 572 } 573 } 574 575 /** 576 * Scans class path and source path for files in given package. 577 */ 578 private void scanUserPaths(PackageSymbol p, boolean includeSourcePath) throws IOException { 579 Set<JavaFileObject.Kind> kinds = getPackageFileKinds(); 580 581 Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds); 582 classKinds.remove(JavaFileObject.Kind.SOURCE); 583 boolean wantClassFiles = !classKinds.isEmpty(); 584 585 Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds); 586 sourceKinds.remove(JavaFileObject.Kind.CLASS); 587 boolean wantSourceFiles = !sourceKinds.isEmpty(); 588 589 boolean haveSourcePath = includeSourcePath && fileManager.hasLocation(SOURCE_PATH); 590 591 if (verbose && verbosePath) { 592 if (fileManager instanceof StandardJavaFileManager) { 593 StandardJavaFileManager fm = (StandardJavaFileManager)fileManager; 594 if (haveSourcePath && wantSourceFiles) { 595 List<Path> path = List.nil(); 596 for (Path sourcePath : fm.getLocationAsPaths(SOURCE_PATH)) { 597 path = path.prepend(sourcePath); 598 } 599 log.printVerbose("sourcepath", path.reverse().toString()); 600 } else if (wantSourceFiles) { 601 List<Path> path = List.nil(); 602 for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { 603 path = path.prepend(classPath); 604 } 605 log.printVerbose("sourcepath", path.reverse().toString()); 606 } 607 if (wantClassFiles) { 608 List<Path> path = List.nil(); 609 for (Path platformPath : fm.getLocationAsPaths(PLATFORM_CLASS_PATH)) { 610 path = path.prepend(platformPath); 611 } 612 for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { 613 path = path.prepend(classPath); 614 } 615 log.printVerbose("classpath", path.reverse().toString()); 616 } 617 } 618 } 619 620 String packageName = p.fullname.toString(); 621 if (wantSourceFiles && !haveSourcePath) { 622 fillIn(p, CLASS_PATH, 623 fileManager.list(CLASS_PATH, 624 packageName, 625 kinds, 626 false)); 627 } else { 628 if (wantClassFiles) 629 fillIn(p, CLASS_PATH, 630 fileManager.list(CLASS_PATH, 631 packageName, 632 classKinds, 633 false)); 634 if (wantSourceFiles) 635 fillIn(p, SOURCE_PATH, 636 fileManager.list(SOURCE_PATH, 637 packageName, 638 sourceKinds, 639 false)); 640 } 641 } 642 643 /** 644 * Scans platform class path for files in given package. 645 */ 646 private void scanPlatformPath(PackageSymbol p) throws IOException { 647 fillIn(p, PLATFORM_CLASS_PATH, 648 fileManager.list(PLATFORM_CLASS_PATH, 649 p.fullname.toString(), 650 allowSigFiles ? EnumSet.of(JavaFileObject.Kind.CLASS, 651 JavaFileObject.Kind.OTHER) 652 : EnumSet.of(JavaFileObject.Kind.CLASS), 653 false)); 654 } 655 // where 656 @SuppressWarnings("fallthrough") 657 private void fillIn(PackageSymbol p, 658 Location location, 659 Iterable<JavaFileObject> files) 660 { 661 currentLoc = location; 662 for (JavaFileObject fo : files) { 663 switch (fo.getKind()) { 664 case OTHER: 665 boolean sigFile = location == PLATFORM_CLASS_PATH && 666 allowSigFiles && 667 fo.getName().endsWith(".sig"); 668 if (!sigFile) { 669 extraFileActions(p, fo); 670 break; 671 } 672 //intentional fall-through: 673 case CLASS: 674 case SOURCE: { 675 // TODO pass binaryName to includeClassFile 676 String binaryName = fileManager.inferBinaryName(currentLoc, fo); 677 String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1); 678 if (SourceVersion.isIdentifier(simpleName) || 679 simpleName.equals("package-info")) 680 includeClassFile(p, fo); 681 break; 682 } 683 default: 684 extraFileActions(p, fo); 685 } 686 } 687 } 688 689 /** 690 * Used for bad class definition files, such as bad .class files or 691 * for .java files with unexpected package or class names. 692 */ 693 public static class BadClassFile extends CompletionFailure { 694 private static final long serialVersionUID = 0; 695 696 public BadClassFile(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag, 697 JCDiagnostic.Factory diagFactory) { 698 super(sym, createBadClassFileDiagnostic(file, diag, diagFactory)); 699 } 700 // where 701 private static JCDiagnostic createBadClassFileDiagnostic( 702 JavaFileObject file, JCDiagnostic diag, JCDiagnostic.Factory diagFactory) { 703 String key = (file.getKind() == JavaFileObject.Kind.SOURCE 704 ? "bad.source.file.header" : "bad.class.file.header"); 705 return diagFactory.fragment(key, file, diag); 706 } 707 } 708 709 public static class BadEnclosingMethodAttr extends BadClassFile { 710 private static final long serialVersionUID = 0; 711 712 public BadEnclosingMethodAttr(TypeSymbol sym, JavaFileObject file, JCDiagnostic diag, 713 JCDiagnostic.Factory diagFactory) { 714 super(sym, file, diag, diagFactory); 715 } 716 } 717} 718