51 import javax.tools.JavaFileManager.Location; |
51 import javax.tools.JavaFileManager.Location; |
52 import javax.tools.JavaFileObject; |
52 import javax.tools.JavaFileObject; |
53 import javax.tools.StandardLocation; |
53 import javax.tools.StandardLocation; |
54 |
54 |
55 import com.sun.tools.javac.code.Kinds.Kind; |
55 import com.sun.tools.javac.code.Kinds.Kind; |
|
56 import com.sun.tools.javac.code.Source; |
56 import com.sun.tools.javac.code.Symbol; |
57 import com.sun.tools.javac.code.Symbol; |
57 import com.sun.tools.javac.code.Symbol.ClassSymbol; |
58 import com.sun.tools.javac.code.Symbol.ClassSymbol; |
58 import com.sun.tools.javac.code.Symbol.CompletionFailure; |
59 import com.sun.tools.javac.code.Symbol.CompletionFailure; |
59 import com.sun.tools.javac.code.Symbol.ModuleSymbol; |
60 import com.sun.tools.javac.code.Symbol.ModuleSymbol; |
60 import com.sun.tools.javac.code.Symbol.PackageSymbol; |
61 import com.sun.tools.javac.code.Symbol.PackageSymbol; |
61 import com.sun.tools.javac.code.Symtab; |
62 import com.sun.tools.javac.code.Symtab; |
62 import com.sun.tools.javac.comp.Modules; |
63 import com.sun.tools.javac.comp.Modules; |
|
64 import com.sun.tools.javac.main.JavaCompiler; |
63 import com.sun.tools.javac.tree.JCTree.JCClassDecl; |
65 import com.sun.tools.javac.tree.JCTree.JCClassDecl; |
64 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; |
66 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; |
|
67 import com.sun.tools.javac.tree.JCTree.JCModuleDecl; |
|
68 import com.sun.tools.javac.tree.TreeInfo; |
65 import com.sun.tools.javac.util.Context; |
69 import com.sun.tools.javac.util.Context; |
66 import com.sun.tools.javac.util.ListBuffer; |
70 import com.sun.tools.javac.util.ListBuffer; |
67 import com.sun.tools.javac.util.Name; |
71 import com.sun.tools.javac.util.Name; |
68 import com.sun.tools.javac.util.Names; |
72 import com.sun.tools.javac.util.Names; |
69 import jdk.javadoc.doclet.DocletEnvironment; |
73 import jdk.javadoc.doclet.DocletEnvironment; |
70 import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; |
74 import jdk.javadoc.doclet.DocletEnvironment.ModuleMode; |
71 |
75 |
72 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; |
76 import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE; |
|
77 |
73 import static javax.tools.JavaFileObject.Kind.*; |
78 import static javax.tools.JavaFileObject.Kind.*; |
|
79 |
74 import static jdk.javadoc.internal.tool.Main.Result.*; |
80 import static jdk.javadoc.internal.tool.Main.Result.*; |
75 import static jdk.javadoc.internal.tool.JavadocTool.isValidClassName; |
81 import static jdk.javadoc.internal.tool.JavadocTool.isValidClassName; |
76 |
82 |
77 |
83 |
78 /** |
84 /** |
151 |
157 |
152 private final ToolEnvironment toolEnv; |
158 private final ToolEnvironment toolEnv; |
153 private final Symtab syms; |
159 private final Symtab syms; |
154 private final Names names; |
160 private final Names names; |
155 private final JavaFileManager fm; |
161 private final JavaFileManager fm; |
156 private final Location location; |
162 private final List<Location> locations; |
157 private final Modules modules; |
163 private final Modules modules; |
158 private final Map<ToolOption, Object> opts; |
164 private final Map<ToolOption, Object> opts; |
159 private final Messager messager; |
165 private final Messager messager; |
|
166 private final JavaCompiler compiler; |
160 |
167 |
161 private final Map<String, Entry> entries = new LinkedHashMap<>(); |
168 private final Map<String, Entry> entries = new LinkedHashMap<>(); |
162 |
169 |
163 // specified elements |
170 // specified elements |
164 private Set<ModuleElement> specifiedModuleElements = new LinkedHashSet<>(); |
171 private Set<ModuleElement> specifiedModuleElements = new LinkedHashSet<>(); |
199 this.names = Names.instance(context); |
206 this.names = Names.instance(context); |
200 this.fm = toolEnv.fileManager; |
207 this.fm = toolEnv.fileManager; |
201 this.modules = Modules.instance(context); |
208 this.modules = Modules.instance(context); |
202 this.opts = opts; |
209 this.opts = opts; |
203 this.messager = Messager.instance0(context); |
210 this.messager = Messager.instance0(context); |
204 |
211 this.compiler = JavaCompiler.instance(context); |
205 this.location = modules.multiModuleMode |
212 Source source = Source.instance(context); |
206 ? StandardLocation.MODULE_SOURCE_PATH |
213 |
207 : toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH) |
214 List<Location> locs = new ArrayList<>(); |
208 ? StandardLocation.SOURCE_PATH |
215 if (modules.multiModuleMode) { |
209 : StandardLocation.CLASS_PATH; |
216 locs.add(StandardLocation.MODULE_SOURCE_PATH); |
|
217 } else { |
|
218 if (toolEnv.fileManager.hasLocation(StandardLocation.SOURCE_PATH)) |
|
219 locs.add(StandardLocation.SOURCE_PATH); |
|
220 else |
|
221 locs.add(StandardLocation.CLASS_PATH); |
|
222 } |
|
223 if (source.allowModules() && toolEnv.fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) |
|
224 locs.add(StandardLocation.PATCH_MODULE_PATH); |
|
225 this.locations = Collections.unmodifiableList(locs); |
|
226 |
210 getEntry("").excluded = false; |
227 getEntry("").excluded = false; |
211 |
228 |
212 accessFilter = new ModifierFilter(opts); |
229 accessFilter = new ModifierFilter(opts); |
213 xclasses = (boolean)opts.getOrDefault(ToolOption.XCLASSES, false); |
230 xclasses = (boolean)opts.getOrDefault(ToolOption.XCLASSES, false); |
214 expandRequires = (AccessKind)opts.get(ToolOption.EXPAND_REQUIRES); |
231 expandRequires = (AccessKind)opts.get(ToolOption.EXPAND_REQUIRES); |
339 ElementsTable classTrees(com.sun.tools.javac.util.List<JCCompilationUnit> classTrees) { |
356 ElementsTable classTrees(com.sun.tools.javac.util.List<JCCompilationUnit> classTrees) { |
340 this.classTreeList = classTrees; |
357 this.classTreeList = classTrees; |
341 return this; |
358 return this; |
342 } |
359 } |
343 |
360 |
|
361 /* |
|
362 * This method sanity checks the following cases: |
|
363 * a. a source-path containing a single module and many modules specified with --module |
|
364 * b. no modules on source-path |
|
365 * c. mismatched source-path and many modules specified with --module |
|
366 */ |
|
367 void sanityCheckSourcePathModules(List<String> moduleNames) throws ToolException { |
|
368 if (!haveSourceLocationWithModule) |
|
369 return; |
|
370 |
|
371 if (moduleNames.size() > 1) { |
|
372 String text = messager.getText("main.cannot_use_sourcepath_for_modules", |
|
373 String.join(", ", moduleNames)); |
|
374 throw new ToolException(CMDERR, text); |
|
375 } |
|
376 |
|
377 String foundModule = getModuleName(StandardLocation.SOURCE_PATH); |
|
378 if (foundModule == null) { |
|
379 String text = messager.getText("main.module_not_found_on_sourcepath", moduleNames.get(0)); |
|
380 throw new ToolException(CMDERR, text); |
|
381 } |
|
382 |
|
383 if (!moduleNames.get(0).equals(foundModule)) { |
|
384 String text = messager.getText("main.sourcepath_does_not_contain_module", moduleNames.get(0)); |
|
385 throw new ToolException(CMDERR, text); |
|
386 } |
|
387 } |
|
388 |
|
389 private String getModuleName(Location location) throws ToolException { |
|
390 try { |
|
391 JavaFileObject jfo = fm.getJavaFileForInput(location, |
|
392 "module-info", JavaFileObject.Kind.SOURCE); |
|
393 if (jfo != null) { |
|
394 JCCompilationUnit jcu = compiler.parse(jfo); |
|
395 JCModuleDecl module = TreeInfo.getModule(jcu); |
|
396 if (module != null) { |
|
397 return module.getName().toString(); |
|
398 } |
|
399 } |
|
400 } catch (IOException ioe) { |
|
401 String text = messager.getText("main.file.manager.list", location); |
|
402 throw new ToolException(SYSERR, text, ioe); |
|
403 } |
|
404 return null; |
|
405 } |
|
406 |
344 @SuppressWarnings("unchecked") |
407 @SuppressWarnings("unchecked") |
345 ElementsTable scanSpecifiedItems() throws ToolException { |
408 ElementsTable scanSpecifiedItems() throws ToolException { |
346 |
409 |
347 // scan modules specified on the command line |
410 // scan modules specified on the command line |
348 List<String> moduleNames = (List<String>) opts.computeIfAbsent(ToolOption.MODULE, |
411 List<String> moduleNames = (List<String>) opts.computeIfAbsent(ToolOption.MODULE, |
349 s -> Collections.EMPTY_LIST); |
412 s -> Collections.EMPTY_LIST); |
350 List<String> mlist = new ArrayList<>(); |
413 List<String> mlist = new ArrayList<>(); |
351 for (String m : moduleNames) { |
414 for (String m : moduleNames) { |
352 Location moduleLoc = getModuleLocation(location, m); |
415 List<Location> moduleLocations = getModuleLocation(locations, m); |
353 if (moduleLoc == null) { |
416 if (moduleLocations.isEmpty()) { |
354 String text = messager.getText("main.module_not_found", m); |
417 String text = messager.getText("main.module_not_found", m); |
355 throw new ToolException(CMDERR, text); |
418 throw new ToolException(CMDERR, text); |
356 } else { |
419 } |
357 mlist.add(m); |
420 if (moduleLocations.contains(StandardLocation.SOURCE_PATH)) { |
358 ModuleSymbol msym = syms.enterModule(names.fromString(m)); |
421 sanityCheckSourcePathModules(moduleNames); |
359 specifiedModuleElements.add((ModuleElement) msym); |
422 } |
360 } |
423 mlist.add(m); |
|
424 ModuleSymbol msym = syms.enterModule(names.fromString(m)); |
|
425 specifiedModuleElements.add((ModuleElement) msym); |
361 } |
426 } |
362 |
427 |
363 // scan for modules with qualified packages |
428 // scan for modules with qualified packages |
364 cmdLinePackages.stream() |
429 cmdLinePackages.stream() |
365 .filter((mpkg) -> (mpkg.hasModule())) |
430 .filter((mpkg) -> (mpkg.hasModule())) |
446 excludePackages.forEach((p) -> { |
511 excludePackages.forEach((p) -> { |
447 getEntry(p).excluded = true; |
512 getEntry(p).excluded = true; |
448 }); |
513 }); |
449 |
514 |
450 for (ModulePackage modpkg : subPackages) { |
515 for (ModulePackage modpkg : subPackages) { |
451 Location packageLocn = getLocation(modpkg); |
516 List<Location> locs = getLocation(modpkg); |
452 Iterable<JavaFileObject> list = null; |
517 for (Location loc : locs) { |
453 try { |
518 addPackagesFromLocations(loc, modpkg); |
454 list = fm.list(packageLocn, modpkg.packageName, sourceKinds, true); |
519 } |
455 } catch (IOException ioe) { |
520 } |
456 String text = messager.getText("main.file.manager.list", modpkg.packageName); |
521 } |
457 throw new ToolException(SYSERR, text, ioe); |
522 |
458 } |
523 private void addPackagesFromLocations(Location packageLocn, ModulePackage modpkg) throws ToolException { |
459 for (JavaFileObject fo : list) { |
524 Iterable<JavaFileObject> list = null; |
460 String binaryName = fm.inferBinaryName(packageLocn, fo); |
525 try { |
461 String pn = getPackageName(binaryName); |
526 list = fm.list(packageLocn, modpkg.packageName, sourceKinds, true); |
462 String simpleName = getSimpleName(binaryName); |
527 } catch (IOException ioe) { |
463 Entry e = getEntry(pn); |
528 String text = messager.getText("main.file.manager.list", modpkg.packageName); |
464 if (!e.isExcluded() && isValidClassName(simpleName)) { |
529 throw new ToolException(SYSERR, text, ioe); |
465 ModuleSymbol msym = (modpkg.hasModule()) |
530 } |
466 ? syms.getModule(names.fromString(modpkg.moduleName)) |
531 for (JavaFileObject fo : list) { |
467 : findModuleOfPackageName(modpkg.packageName); |
532 String binaryName = fm.inferBinaryName(packageLocn, fo); |
468 |
533 String pn = getPackageName(binaryName); |
469 if (msym != null && !msym.isUnnamed()) { |
534 String simpleName = getSimpleName(binaryName); |
470 syms.enterPackage(msym, names.fromString(pn)); |
535 Entry e = getEntry(pn); |
471 ModulePackage npkg = new ModulePackage(msym.toString(), pn); |
536 if (!e.isExcluded() && isValidClassName(simpleName)) { |
472 cmdLinePackages.add(npkg); |
537 ModuleSymbol msym = (modpkg.hasModule()) |
473 } else { |
538 ? syms.getModule(names.fromString(modpkg.moduleName)) |
474 cmdLinePackages.add(e.modpkg); |
539 : findModuleOfPackageName(modpkg.packageName); |
475 } |
540 |
476 e.files = (e.files == null |
541 if (msym != null && !msym.isUnnamed()) { |
477 ? com.sun.tools.javac.util.List.of(fo) |
542 syms.enterPackage(msym, names.fromString(pn)); |
478 : e.files.prepend(fo)); |
543 ModulePackage npkg = new ModulePackage(msym.toString(), pn); |
479 } |
544 cmdLinePackages.add(npkg); |
|
545 } else { |
|
546 cmdLinePackages.add(e.modpkg); |
|
547 } |
|
548 e.files = (e.files == null |
|
549 ? com.sun.tools.javac.util.List.of(fo) |
|
550 : e.files.prepend(fo)); |
480 } |
551 } |
481 } |
552 } |
482 } |
553 } |
483 |
554 |
484 /** |
555 /** |
542 } |
613 } |
543 |
614 |
544 private Set<PackageElement> getAllModulePackages(ModuleElement mdle) throws ToolException { |
615 private Set<PackageElement> getAllModulePackages(ModuleElement mdle) throws ToolException { |
545 Set<PackageElement> result = new HashSet<>(); |
616 Set<PackageElement> result = new HashSet<>(); |
546 ModuleSymbol msym = (ModuleSymbol) mdle; |
617 ModuleSymbol msym = (ModuleSymbol) mdle; |
547 Location msymloc = getModuleLocation(location, msym.name.toString()); |
618 List<Location> msymlocs = getModuleLocation(locations, msym.name.toString()); |
548 try { |
619 for (Location msymloc : msymlocs) { |
549 for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) { |
620 try { |
550 if (fo.getName().endsWith("module-info.java")) |
621 for (JavaFileObject fo : fm.list(msymloc, "", sourceKinds, true)) { |
551 continue; |
622 if (fo.getName().endsWith("module-info.java")) { |
552 String binaryName = fm.inferBinaryName(msymloc, fo); |
623 continue; |
553 String pn = getPackageName(binaryName); |
624 } |
554 PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn)); |
625 String binaryName = fm.inferBinaryName(msymloc, fo); |
555 result.add((PackageElement) psym); |
626 String pn = getPackageName(binaryName); |
556 } |
627 PackageSymbol psym = syms.enterPackage(msym, names.fromString(pn)); |
557 |
628 result.add((PackageElement) psym); |
558 } catch (IOException ioe) { |
629 } |
559 String text = messager.getText("main.file.manager.list", msymloc.getName()); |
630 |
560 throw new ToolException(SYSERR, text, ioe); |
631 } catch (IOException ioe) { |
|
632 String text = messager.getText("main.file.manager.list", msymloc.getName()); |
|
633 throw new ToolException(SYSERR, text, ioe); |
|
634 } |
561 } |
635 } |
562 return result; |
636 return result; |
563 } |
637 } |
564 |
638 |
565 private Set<PackageElement> computeModulePackages() throws ToolException { |
639 private Set<PackageElement> computeModulePackages() throws ToolException { |
739 if (e.files != null) { |
813 if (e.files != null) { |
740 return e.files; |
814 return e.files; |
741 } |
815 } |
742 |
816 |
743 ListBuffer<JavaFileObject> lb = new ListBuffer<>(); |
817 ListBuffer<JavaFileObject> lb = new ListBuffer<>(); |
744 Location packageLocn = getLocation(modpkg); |
818 List<Location> locs = getLocation(modpkg); |
745 if (packageLocn == null) { |
819 if (locs.isEmpty()) { |
746 return Collections.emptyList(); |
820 return Collections.emptyList(); |
747 } |
821 } |
748 String pname = modpkg.packageName; |
822 String pname = modpkg.packageName; |
749 |
823 for (Location packageLocn : locs) { |
750 try { |
824 try { |
751 for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) { |
825 for (JavaFileObject fo : fm.list(packageLocn, pname, sourceKinds, recurse)) { |
752 String binaryName = fm.inferBinaryName(packageLocn, fo); |
826 String binaryName = fm.inferBinaryName(packageLocn, fo); |
753 String simpleName = getSimpleName(binaryName); |
827 String simpleName = getSimpleName(binaryName); |
754 if (isValidClassName(simpleName)) { |
828 if (isValidClassName(simpleName)) { |
755 lb.append(fo); |
829 lb.append(fo); |
756 } |
830 } |
757 } |
831 } |
758 } catch (IOException ioe) { |
832 } catch (IOException ioe) { |
759 String text = messager.getText("main.file.manager.list", pname); |
833 String text = messager.getText("main.file.manager.list", pname); |
760 throw new ToolException(SYSERR, text, ioe); |
834 throw new ToolException(SYSERR, text, ioe); |
761 } |
835 } |
762 |
836 } |
763 return lb.toList(); |
837 return lb.toList(); |
764 } |
838 } |
765 |
839 |
766 private ModuleSymbol findModuleOfPackageName(String packageName) { |
840 private ModuleSymbol findModuleOfPackageName(String packageName) { |
767 Name pack = names.fromString(packageName); |
841 Name pack = names.fromString(packageName); |
772 } |
846 } |
773 } |
847 } |
774 return null; |
848 return null; |
775 } |
849 } |
776 |
850 |
777 private Location getLocation(ModulePackage modpkg) throws ToolException { |
851 private List<Location> getLocation(ModulePackage modpkg) throws ToolException { |
778 if (location != StandardLocation.MODULE_SOURCE_PATH) { |
852 if (locations.size() == 1 && !locations.contains(StandardLocation.MODULE_SOURCE_PATH)) { |
779 return location; |
853 return Collections.singletonList(locations.get(0)); |
780 } |
854 } |
781 |
855 |
782 if (modpkg.hasModule()) { |
856 if (modpkg.hasModule()) { |
783 return getModuleLocation(location, modpkg.moduleName); |
857 return getModuleLocation(locations, modpkg.moduleName); |
784 } |
858 } |
785 // TODO: handle invalid results better. |
859 // TODO: handle invalid results better. |
786 ModuleSymbol msym = findModuleOfPackageName(modpkg.packageName); |
860 ModuleSymbol msym = findModuleOfPackageName(modpkg.packageName); |
787 if (msym == null) { |
861 if (msym == null) { |
788 return null; |
862 return Collections.emptyList(); |
789 } |
863 } |
790 return getModuleLocation(location, msym.name.toString()); |
864 return getModuleLocation(locations, msym.name.toString()); |
791 } |
865 } |
792 |
866 |
793 private Location getModuleLocation(Location location, String msymName) |
867 boolean haveSourceLocationWithModule = false; |
794 throws ToolException { |
868 |
|
869 private List<Location> getModuleLocation(List<Location> locations, String msymName) throws ToolException { |
|
870 List<Location> out = new ArrayList<>(); |
|
871 // search in the patch module first, this overrides others |
|
872 if (locations.contains(StandardLocation.PATCH_MODULE_PATH)) { |
|
873 Location loc = getModuleLocation(StandardLocation.PATCH_MODULE_PATH, msymName); |
|
874 if (loc != null) |
|
875 out.add(loc); |
|
876 } |
|
877 for (Location location : locations) { |
|
878 // skip patch module, already done |
|
879 if (location == StandardLocation.PATCH_MODULE_PATH) { |
|
880 continue; |
|
881 } else if (location == StandardLocation.MODULE_SOURCE_PATH) { |
|
882 Location loc = getModuleLocation(location, msymName); |
|
883 if (loc != null) |
|
884 out.add(loc); |
|
885 } else if (location == StandardLocation.SOURCE_PATH) { |
|
886 haveSourceLocationWithModule = true; |
|
887 out.add(StandardLocation.SOURCE_PATH); |
|
888 } |
|
889 } |
|
890 return out; |
|
891 } |
|
892 |
|
893 private Location getModuleLocation(Location location, String msymName) throws ToolException { |
795 try { |
894 try { |
796 return fm.getLocationForModule(location, msymName); |
895 return fm.getLocationForModule(location, msymName); |
797 } catch (IOException ioe) { |
896 } catch (IOException ioe) { |
798 String text = messager.getText("main.doclet_could_not_get_location", msymName); |
897 String text = messager.getText("main.doclet_could_not_get_location", msymName); |
799 throw new ToolException(ERROR, text, ioe); |
898 throw new ToolException(ERROR, text, ioe); |