128 */
129 public class Modules extends JCTree.Visitor {
130 private static final String ALL_SYSTEM = "ALL-SYSTEM";
131 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
132
133 private final Log log;
134 private final Names names;
135 private final Symtab syms;
136 private final Attr attr;
137 private final Check chk;
138 private final DeferredLintHandler deferredLintHandler;
139 private final TypeEnvs typeEnvs;
140 private final Types types;
141 private final JavaFileManager fileManager;
142 private final ModuleFinder moduleFinder;
143 private final Source source;
144 private final boolean allowModules;
145
146 public final boolean multiModuleMode;
147
148 private final String moduleOverride;
149
150 private final Name java_se;
151 private final Name java_;
152
153 ModuleSymbol defaultModule;
154
155 private final String addExportsOpt;
156 private Map<ModuleSymbol, Set<ExportsDirective>> addExports;
157 private final String addReadsOpt;
158 private Map<ModuleSymbol, Set<RequiresDirective>> addReads;
159 private final String addModsOpt;
160 private final Set<String> extraAddMods = new HashSet<>();
161 private final String limitModsOpt;
162 private final Set<String> extraLimitMods = new HashSet<>();
163 private final String moduleVersionOpt;
164
165 private final boolean lintOptions;
166
167 private Set<ModuleSymbol> rootModules = null;
168 private final Set<ModuleSymbol> warnedMissing = new HashSet<>();
175 }
176
177 protected Modules(Context context) {
178 context.put(Modules.class, this);
179 log = Log.instance(context);
180 names = Names.instance(context);
181 syms = Symtab.instance(context);
182 attr = Attr.instance(context);
183 chk = Check.instance(context);
184 deferredLintHandler = DeferredLintHandler.instance(context);
185 typeEnvs = TypeEnvs.instance(context);
186 moduleFinder = ModuleFinder.instance(context);
187 types = Types.instance(context);
188 fileManager = context.get(JavaFileManager.class);
189 source = Source.instance(context);
190 allowModules = source.allowModules();
191 Options options = Options.instance(context);
192
193 lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
194
195 moduleOverride = options.get(Option.XMODULE);
196
197 multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
198 ClassWriter classWriter = ClassWriter.instance(context);
199 classWriter.multiModuleMode = multiModuleMode;
200 JNIWriter jniWriter = JNIWriter.instance(context);
201 jniWriter.multiModuleMode = multiModuleMode;
202
203 java_se = names.fromString("java.se");
204 java_ = names.fromString("java.");
205
206 addExportsOpt = options.get(Option.ADD_EXPORTS);
207 addReadsOpt = options.get(Option.ADD_READS);
208 addModsOpt = options.get(Option.ADD_MODULES);
209 limitModsOpt = options.get(Option.LIMIT_MODULES);
210 moduleVersionOpt = options.get(Option.MODULE_VERSION);
211 }
212
213 int depth = -1;
214 private void dprintln(String msg) {
215 for (int i = 0; i < depth; i++)
349 } else if (isModuleInfo) {
350 if (multiModuleMode) {
351 JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head;
352 log.error(tree.pos(), Errors.ExpectedModule);
353 }
354 }
355 }
356
357 private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules, ClassSymbol c) {
358 // update the module for each compilation unit
359 if (multiModuleMode) {
360 checkNoAllModulePath();
361 for (JCCompilationUnit tree: trees) {
362 if (tree.defs.isEmpty()) {
363 tree.modle = syms.unnamedModule;
364 continue;
365 }
366
367 JavaFileObject prev = log.useSource(tree.sourcefile);
368 try {
369 Location locn = getModuleLocation(tree);
370 if (locn != null) {
371 Name name = names.fromString(fileManager.inferModuleName(locn));
372 ModuleSymbol msym;
373 JCModuleDecl decl = tree.getModuleDecl();
374 if (decl != null) {
375 msym = decl.sym;
376 if (msym.name != name) {
377 log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
378 }
379 } else {
380 if (tree.getPackage() == null) {
381 log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules);
382 }
383 msym = syms.enterModule(name);
384 }
385 if (msym.sourceLocation == null) {
386 msym.sourceLocation = locn;
387 if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
388 msym.classLocation = fileManager.getLocationForModule(
389 StandardLocation.CLASS_OUTPUT, msym.name.toString());
390 }
391 }
392 tree.modle = msym;
393 rootModules.add(msym);
394 } else if (c != null && c.packge().modle == syms.unnamedModule) {
395 tree.modle = syms.unnamedModule;
396 } else {
397 if (tree.getModuleDecl() != null) {
398 log.error(tree.pos(), Errors.ModuleNotFoundOnModuleSourcePath);
399 } else {
400 log.error(tree.pos(), Errors.NotInModuleOnModuleSourcePath);
401 }
402 tree.modle = syms.errModule;
403 }
404 } catch (IOException e) {
405 throw new Error(e); // FIXME
406 } finally {
407 log.useSource(prev);
408 }
409 }
410 if (syms.unnamedModule.sourceLocation == null) {
411 syms.unnamedModule.completer = getUnnamedModuleCompleter();
412 syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
413 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
414 }
415 defaultModule = syms.unnamedModule;
416 } else {
417 if (defaultModule == null) {
418 switch (rootModules.size()) {
419 case 0:
420 defaultModule = moduleFinder.findSingleModule();
421 if (defaultModule == syms.unnamedModule) {
422 if (moduleOverride != null) {
423 checkNoAllModulePath();
424 defaultModule = moduleFinder.findModule(names.fromString(moduleOverride));
425 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
426 } else {
427 // Question: why not do findAllModules and initVisiblePackages here?
428 // i.e. body of unnamedModuleCompleter
429 defaultModule.completer = getUnnamedModuleCompleter();
430 defaultModule.classLocation = StandardLocation.CLASS_PATH;
431 }
432 } else {
433 checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleClasspath);
434 checkNoAllModulePath();
435 defaultModule.complete();
436 // Question: why not do completeModule here?
437 defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
438 }
439 rootModules.add(defaultModule);
440 break;
441 case 1:
442 checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleSourcepath);
443 checkNoAllModulePath();
444 defaultModule = rootModules.iterator().next();
445 defaultModule.classLocation = StandardLocation.CLASS_OUTPUT;
446 break;
447 default:
448 Assert.error("too many modules");
449 }
450 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
451 } else if (rootModules.size() == 1 && defaultModule == rootModules.iterator().next()) {
452 defaultModule.complete();
453 defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
454 } else {
455 Assert.check(rootModules.isEmpty());
456 rootModules.add(defaultModule);
457 }
458
459 if (defaultModule != syms.unnamedModule) {
460 syms.unnamedModule.completer = getUnnamedModuleCompleter();
461 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
462 }
463
464 for (JCCompilationUnit tree: trees) {
465 tree.modle = defaultModule;
466 }
467 }
468 }
469
470 /**
471 * Determine the location for the module on the module source path
472 * or source output directory which contains a given CompilationUnit.
473 * If the source output directory is unset, the class output directory
474 * will be checked instead.
475 * {@code null} is returned if no such module can be found.
476 * @param tree the compilation unit tree
477 * @return the location for the enclosing module
478 * @throws IOException if there is a problem while searching for the module.
479 */
480 private Location getModuleLocation(JCCompilationUnit tree) throws IOException {
481 Name pkgName;
482 if (tree.getModuleDecl() != null) {
483 pkgName = null;
484 } else {
485 JCPackageDecl pkg = tree.getPackage();
486 pkgName = (pkg == null) ? names.empty : TreeInfo.fullName(pkg.pid);
487 }
488
489 JavaFileObject fo = tree.sourcefile;
490
491 // For now, just check module source path.
492 // We may want to check source path as well.
493 Location loc =
494 fileManager.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH,
495 fo, (pkgName == null) ? null : pkgName.toString());
496 if (loc == null) {
497 Location sourceOutput = fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT) ?
498 StandardLocation.SOURCE_OUTPUT : StandardLocation.CLASS_OUTPUT;
499 loc =
500 fileManager.getLocationForModule(sourceOutput,
501 fo, (pkgName == null) ? null : pkgName.toString());
502 }
503 return loc;
504 }
505
506 private void checkSpecifiedModule(List<JCCompilationUnit> trees, JCDiagnostic.Error error) {
507 if (moduleOverride != null) {
508 JavaFileObject prev = log.useSource(trees.head.sourcefile);
509 try {
510 log.error(trees.head.pos(), error);
511 } finally {
512 log.useSource(prev);
513 }
514 }
515 }
516
517 private void checkNoAllModulePath() {
518 if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) {
519 log.error(Errors.AddmodsAllModulePathInvalid);
520 }
521 }
522
523 private final Completer mainCompleter = new Completer() {
524 @Override
525 public void complete(Symbol sym) throws CompletionFailure {
526 ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
1583 return msym.name + "["
1584 + "kind:" + msym.kind + ";"
1585 + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";"
1586 + "info:" + toString(msym.module_info.sourcefile) + ","
1587 + toString(msym.module_info.classfile) + ","
1588 + msym.module_info.completer
1589 + "]";
1590 }
1591
1592 // DEBUG
1593 String toString(Location locn) {
1594 return (locn == null) ? "--" : locn.getName();
1595 }
1596
1597 // DEBUG
1598 String toString(JavaFileObject fo) {
1599 return (fo == null) ? "--" : fo.getName();
1600 }
1601
1602 public void newRound() {
1603 rootModules = null;
1604 allModules = null;
1605 warnedMissing.clear();
1606 }
1607 }
|
128 */
129 public class Modules extends JCTree.Visitor {
130 private static final String ALL_SYSTEM = "ALL-SYSTEM";
131 private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH";
132
133 private final Log log;
134 private final Names names;
135 private final Symtab syms;
136 private final Attr attr;
137 private final Check chk;
138 private final DeferredLintHandler deferredLintHandler;
139 private final TypeEnvs typeEnvs;
140 private final Types types;
141 private final JavaFileManager fileManager;
142 private final ModuleFinder moduleFinder;
143 private final Source source;
144 private final boolean allowModules;
145
146 public final boolean multiModuleMode;
147
148 private final String legacyModuleOverride;
149
150 private final Name java_se;
151 private final Name java_;
152
153 ModuleSymbol defaultModule;
154
155 private final String addExportsOpt;
156 private Map<ModuleSymbol, Set<ExportsDirective>> addExports;
157 private final String addReadsOpt;
158 private Map<ModuleSymbol, Set<RequiresDirective>> addReads;
159 private final String addModsOpt;
160 private final Set<String> extraAddMods = new HashSet<>();
161 private final String limitModsOpt;
162 private final Set<String> extraLimitMods = new HashSet<>();
163 private final String moduleVersionOpt;
164
165 private final boolean lintOptions;
166
167 private Set<ModuleSymbol> rootModules = null;
168 private final Set<ModuleSymbol> warnedMissing = new HashSet<>();
175 }
176
177 protected Modules(Context context) {
178 context.put(Modules.class, this);
179 log = Log.instance(context);
180 names = Names.instance(context);
181 syms = Symtab.instance(context);
182 attr = Attr.instance(context);
183 chk = Check.instance(context);
184 deferredLintHandler = DeferredLintHandler.instance(context);
185 typeEnvs = TypeEnvs.instance(context);
186 moduleFinder = ModuleFinder.instance(context);
187 types = Types.instance(context);
188 fileManager = context.get(JavaFileManager.class);
189 source = Source.instance(context);
190 allowModules = source.allowModules();
191 Options options = Options.instance(context);
192
193 lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
194
195 legacyModuleOverride = options.get(Option.XMODULE);
196
197 multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
198 ClassWriter classWriter = ClassWriter.instance(context);
199 classWriter.multiModuleMode = multiModuleMode;
200 JNIWriter jniWriter = JNIWriter.instance(context);
201 jniWriter.multiModuleMode = multiModuleMode;
202
203 java_se = names.fromString("java.se");
204 java_ = names.fromString("java.");
205
206 addExportsOpt = options.get(Option.ADD_EXPORTS);
207 addReadsOpt = options.get(Option.ADD_READS);
208 addModsOpt = options.get(Option.ADD_MODULES);
209 limitModsOpt = options.get(Option.LIMIT_MODULES);
210 moduleVersionOpt = options.get(Option.MODULE_VERSION);
211 }
212
213 int depth = -1;
214 private void dprintln(String msg) {
215 for (int i = 0; i < depth; i++)
349 } else if (isModuleInfo) {
350 if (multiModuleMode) {
351 JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head;
352 log.error(tree.pos(), Errors.ExpectedModule);
353 }
354 }
355 }
356
357 private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules, ClassSymbol c) {
358 // update the module for each compilation unit
359 if (multiModuleMode) {
360 checkNoAllModulePath();
361 for (JCCompilationUnit tree: trees) {
362 if (tree.defs.isEmpty()) {
363 tree.modle = syms.unnamedModule;
364 continue;
365 }
366
367 JavaFileObject prev = log.useSource(tree.sourcefile);
368 try {
369 Location msplocn = getModuleLocation(tree);
370 Location plocn = fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH) ?
371 fileManager.getLocationForModule(StandardLocation.PATCH_MODULE_PATH,
372 tree.sourcefile, getPackageName(tree)) :
373 null;
374
375 if (msplocn != null) {
376 if (plocn != null) {
377 log.error(tree.pos(), Errors.FilePatchedAndMsp);
378 }
379 Name name = names.fromString(fileManager.inferModuleName(msplocn));
380 ModuleSymbol msym;
381 JCModuleDecl decl = tree.getModuleDecl();
382 if (decl != null) {
383 msym = decl.sym;
384 if (msym.name != name) {
385 log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
386 }
387 } else {
388 if (tree.getPackage() == null) {
389 log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules);
390 }
391 msym = syms.enterModule(name);
392 }
393 if (msym.sourceLocation == null) {
394 msym.sourceLocation = msplocn;
395 if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
396 msym.classLocation = fileManager.getLocationForModule(
397 StandardLocation.CLASS_OUTPUT, msym.name.toString());
398 }
399 }
400 tree.modle = msym;
401 rootModules.add(msym);
402 } else if (plocn != null) {
403 Name name = names.fromString(fileManager.inferModuleName(plocn));
404 ModuleSymbol msym = moduleFinder.findModule(name);
405 tree.modle = msym;
406 rootModules.add(msym);
407 } else if (c != null && c.packge().modle == syms.unnamedModule) {
408 tree.modle = syms.unnamedModule;
409 } else {
410 if (tree.getModuleDecl() != null) {
411 log.error(tree.pos(), Errors.ModuleNotFoundOnModuleSourcePath);
412 } else {
413 log.error(tree.pos(), Errors.NotInModuleOnModuleSourcePath);
414 }
415 tree.modle = syms.errModule;
416 }
417 } catch (IOException e) {
418 throw new Error(e); // FIXME
419 } finally {
420 log.useSource(prev);
421 }
422 }
423 if (syms.unnamedModule.sourceLocation == null) {
424 syms.unnamedModule.completer = getUnnamedModuleCompleter();
425 syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
426 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
427 }
428 defaultModule = syms.unnamedModule;
429 } else {
430 ModuleSymbol module = null;
431 if (defaultModule == null) {
432 String moduleOverride = singleModuleOverride(trees);
433 switch (rootModules.size()) {
434 case 0:
435 defaultModule = moduleFinder.findSingleModule();
436 if (defaultModule == syms.unnamedModule) {
437 if (moduleOverride != null) {
438 checkNoAllModulePath();
439 defaultModule = moduleFinder.findModule(names.fromString(moduleOverride));
440 if (legacyModuleOverride != null) {
441 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
442 }
443 } else {
444 // Question: why not do findAllModules and initVisiblePackages here?
445 // i.e. body of unnamedModuleCompleter
446 defaultModule.completer = getUnnamedModuleCompleter();
447 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
448 defaultModule.classLocation = StandardLocation.CLASS_PATH;
449 }
450 } else {
451 checkSpecifiedModule(trees, moduleOverride, Errors.ModuleInfoWithPatchedModuleClasspath);
452 checkNoAllModulePath();
453 defaultModule.complete();
454 // Question: why not do completeModule here?
455 defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
456 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
457 }
458 rootModules.add(defaultModule);
459 break;
460 case 1:
461 checkSpecifiedModule(trees, moduleOverride, Errors.ModuleInfoWithPatchedModuleSourcepath);
462 checkNoAllModulePath();
463 defaultModule = rootModules.iterator().next();
464 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
465 defaultModule.classLocation = StandardLocation.CLASS_OUTPUT;
466 break;
467 default:
468 Assert.error("too many modules");
469 }
470 } else if (rootModules.size() == 1 && defaultModule == rootModules.iterator().next()) {
471 defaultModule.complete();
472 defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
473 } else {
474 Assert.check(rootModules.isEmpty());
475 String moduleOverride = singleModuleOverride(trees);
476 if (moduleOverride != null) {
477 module = moduleFinder.findModule(names.fromString(moduleOverride));
478 } else {
479 module = defaultModule;
480 }
481 rootModules.add(module);
482 }
483
484 if (defaultModule != syms.unnamedModule) {
485 syms.unnamedModule.completer = getUnnamedModuleCompleter();
486 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
487 }
488
489 if (module == null) {
490 module = defaultModule;
491 }
492
493 for (JCCompilationUnit tree: trees) {
494 tree.modle = module;
495 }
496 }
497 }
498
499 private String singleModuleOverride(List<JCCompilationUnit> trees) {
500 if (!fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) {
501 return legacyModuleOverride;
502 }
503
504 Set<String> override = new LinkedHashSet<>();
505 for (JCCompilationUnit tree : trees) {
506 JavaFileObject fo = tree.sourcefile;
507
508 try {
509 Location loc =
510 fileManager.getLocationForModule(StandardLocation.PATCH_MODULE_PATH,
511 fo, getPackageName(tree));
512
513 if (loc != null) {
514 try {
515 override.add(fileManager.inferModuleName(loc));
516 } catch (IOException ex) {
517 throw new Error(ex);
518 }
519 }
520 } catch (IOException ex) {
521 ex.printStackTrace();
522 }
523 }
524
525 switch (override.size()) {
526 case 0: return legacyModuleOverride;
527 case 1: return override.iterator().next();
528 default:
529 log.error(Errors.TooManyPatchedModules(override));
530 return null;
531 }
532 }
533
534 private String getPackageName(JCCompilationUnit tree) {
535 if (tree.getModuleDecl() != null) {
536 return null;
537 } else {
538 JCPackageDecl pkg = tree.getPackage();
539 return (pkg == null) ? "" : TreeInfo.fullName(pkg.pid).toString();
540 }
541 }
542
543 /**
544 * Determine the location for the module on the module source path
545 * or source output directory which contains a given CompilationUnit.
546 * If the source output directory is unset, the class output directory
547 * will be checked instead.
548 * {@code null} is returned if no such module can be found.
549 * @param tree the compilation unit tree
550 * @return the location for the enclosing module
551 * @throws IOException if there is a problem while searching for the module.
552 */
553 private Location getModuleLocation(JCCompilationUnit tree) throws IOException {
554 String pkgName = getPackageName(tree);
555 JavaFileObject fo = tree.sourcefile;
556
557 Location loc =
558 fileManager.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH,
559 fo, (pkgName == null) ? null : pkgName);
560 if (loc == null) {
561 Location sourceOutput = fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT) ?
562 StandardLocation.SOURCE_OUTPUT : StandardLocation.CLASS_OUTPUT;
563 loc =
564 fileManager.getLocationForModule(sourceOutput,
565 fo, (pkgName == null) ? null : pkgName);
566 }
567 return loc;
568 }
569
570 private void checkSpecifiedModule(List<JCCompilationUnit> trees, String moduleOverride, JCDiagnostic.Error error) {
571 if (moduleOverride != null) {
572 JavaFileObject prev = log.useSource(trees.head.sourcefile);
573 try {
574 log.error(trees.head.pos(), error);
575 } finally {
576 log.useSource(prev);
577 }
578 }
579 }
580
581 private void checkNoAllModulePath() {
582 if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) {
583 log.error(Errors.AddmodsAllModulePathInvalid);
584 }
585 }
586
587 private final Completer mainCompleter = new Completer() {
588 @Override
589 public void complete(Symbol sym) throws CompletionFailure {
590 ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
1647 return msym.name + "["
1648 + "kind:" + msym.kind + ";"
1649 + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";"
1650 + "info:" + toString(msym.module_info.sourcefile) + ","
1651 + toString(msym.module_info.classfile) + ","
1652 + msym.module_info.completer
1653 + "]";
1654 }
1655
1656 // DEBUG
1657 String toString(Location locn) {
1658 return (locn == null) ? "--" : locn.getName();
1659 }
1660
1661 // DEBUG
1662 String toString(JavaFileObject fo) {
1663 return (fo == null) ? "--" : fo.getName();
1664 }
1665
1666 public void newRound() {
1667 allModules = null;
1668 rootModules = null;
1669 warnedMissing.clear();
1670 }
1671 }
|