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);
1577 return msym.name + "["
1578 + "kind:" + msym.kind + ";"
1579 + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";"
1580 + "info:" + toString(msym.module_info.sourcefile) + ","
1581 + toString(msym.module_info.classfile) + ","
1582 + msym.module_info.completer
1583 + "]";
1584 }
1585
1586 // DEBUG
1587 String toString(Location locn) {
1588 return (locn == null) ? "--" : locn.getName();
1589 }
1590
1591 // DEBUG
1592 String toString(JavaFileObject fo) {
1593 return (fo == null) ? "--" : fo.getName();
1594 }
1595
1596 public void newRound() {
1597 rootModules = null;
1598 allModules = null;
1599 warnedMissing.clear();
1600 }
1601 }
|
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 (plocn != null) {
376 Name name = names.fromString(fileManager.inferModuleName(plocn));
377 ModuleSymbol msym = moduleFinder.findModule(name);
378 tree.modle = msym;
379 rootModules.add(msym);
380
381 if (msplocn != null) {
382 Name mspname = names.fromString(fileManager.inferModuleName(msplocn));
383 if (name != mspname) {
384 log.error(tree.pos(), Errors.FilePatchedAndMsp(name, mspname));
385 }
386 }
387 } else if (msplocn != null) {
388 Name name = names.fromString(fileManager.inferModuleName(msplocn));
389 ModuleSymbol msym;
390 JCModuleDecl decl = tree.getModuleDecl();
391 if (decl != null) {
392 msym = decl.sym;
393 if (msym.name != name) {
394 log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name));
395 }
396 } else {
397 if (tree.getPackage() == null) {
398 log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules);
399 }
400 msym = syms.enterModule(name);
401 }
402 if (msym.sourceLocation == null) {
403 msym.sourceLocation = msplocn;
404 if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) {
405 msym.classLocation = fileManager.getLocationForModule(
406 StandardLocation.CLASS_OUTPUT, msym.name.toString());
407 }
408 }
409 tree.modle = msym;
410 rootModules.add(msym);
411 } else if (c != null && c.packge().modle == syms.unnamedModule) {
412 tree.modle = syms.unnamedModule;
413 } else {
414 if (tree.getModuleDecl() != null) {
415 log.error(tree.pos(), Errors.ModuleNotFoundOnModuleSourcePath);
416 } else {
417 log.error(tree.pos(), Errors.NotInModuleOnModuleSourcePath);
418 }
419 tree.modle = syms.errModule;
420 }
421 } catch (IOException e) {
422 throw new Error(e); // FIXME
423 } finally {
424 log.useSource(prev);
425 }
426 }
427 if (syms.unnamedModule.sourceLocation == null) {
428 syms.unnamedModule.completer = getUnnamedModuleCompleter();
429 syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH;
430 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
431 }
432 defaultModule = syms.unnamedModule;
433 } else {
434 ModuleSymbol module = null;
435 if (defaultModule == null) {
436 String moduleOverride = singleModuleOverride(trees);
437 switch (rootModules.size()) {
438 case 0:
439 defaultModule = moduleFinder.findSingleModule();
440 if (defaultModule == syms.unnamedModule) {
441 if (moduleOverride != null) {
442 checkNoAllModulePath();
443 defaultModule = moduleFinder.findModule(names.fromString(moduleOverride));
444 if (legacyModuleOverride != null) {
445 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
446 }
447 defaultModule.patchOutputLocation = StandardLocation.CLASS_OUTPUT;
448 } else {
449 // Question: why not do findAllModules and initVisiblePackages here?
450 // i.e. body of unnamedModuleCompleter
451 defaultModule.completer = getUnnamedModuleCompleter();
452 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
453 defaultModule.classLocation = StandardLocation.CLASS_PATH;
454 }
455 } else {
456 checkSpecifiedModule(trees, moduleOverride, Errors.ModuleInfoWithPatchedModuleClassoutput);
457 checkNoAllModulePath();
458 defaultModule.complete();
459 // Question: why not do completeModule here?
460 defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
461 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
462 }
463 rootModules.add(defaultModule);
464 break;
465 case 1:
466 checkSpecifiedModule(trees, moduleOverride, Errors.ModuleInfoWithPatchedModuleSourcepath);
467 checkNoAllModulePath();
468 defaultModule = rootModules.iterator().next();
469 defaultModule.sourceLocation = StandardLocation.SOURCE_PATH;
470 defaultModule.classLocation = StandardLocation.CLASS_OUTPUT;
471 break;
472 default:
473 Assert.error("too many modules");
474 }
475 } else if (rootModules.size() == 1 && defaultModule == rootModules.iterator().next()) {
476 defaultModule.complete();
477 defaultModule.completer = sym -> completeModule((ModuleSymbol) sym);
478 } else {
479 Assert.check(rootModules.isEmpty());
480 String moduleOverride = singleModuleOverride(trees);
481 if (moduleOverride != null) {
482 module = moduleFinder.findModule(names.fromString(moduleOverride));
483 } else {
484 module = defaultModule;
485 }
486 rootModules.add(module);
487 }
488
489 if (defaultModule != syms.unnamedModule) {
490 syms.unnamedModule.completer = getUnnamedModuleCompleter();
491 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH;
492 }
493
494 if (module == null) {
495 module = defaultModule;
496 }
497
498 for (JCCompilationUnit tree: trees) {
499 tree.modle = module;
500 }
501 }
502 }
503
504 private String singleModuleOverride(List<JCCompilationUnit> trees) {
505 if (!fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) {
506 return legacyModuleOverride;
507 }
508
509 Set<String> override = new LinkedHashSet<>();
510 for (JCCompilationUnit tree : trees) {
511 JavaFileObject fo = tree.sourcefile;
512
513 try {
514 Location loc =
515 fileManager.getLocationForModule(StandardLocation.PATCH_MODULE_PATH,
516 fo, getPackageName(tree));
517
518 if (loc != null) {
519 try {
520 override.add(fileManager.inferModuleName(loc));
521 } catch (IOException ex) {
522 throw new Error(ex);
523 }
524 }
525 } catch (IOException ex) {
526 ex.printStackTrace();
527 }
528 }
529
530 switch (override.size()) {
531 case 0: return legacyModuleOverride;
532 case 1: return override.iterator().next();
533 default:
534 log.error(Errors.TooManyPatchedModules(override));
535 return null;
536 }
537 }
538
539 private String getPackageName(JCCompilationUnit tree) {
540 if (tree.getModuleDecl() != null) {
541 return null;
542 } else {
543 JCPackageDecl pkg = tree.getPackage();
544 return (pkg == null) ? "" : TreeInfo.fullName(pkg.pid).toString();
545 }
546 }
547
548 /**
549 * Determine the location for the module on the module source path
550 * or source output directory which contains a given CompilationUnit.
551 * If the source output directory is unset, the class output directory
552 * will be checked instead.
553 * {@code null} is returned if no such module can be found.
554 * @param tree the compilation unit tree
555 * @return the location for the enclosing module
556 * @throws IOException if there is a problem while searching for the module.
557 */
558 private Location getModuleLocation(JCCompilationUnit tree) throws IOException {
559 String pkgName = getPackageName(tree);
560 JavaFileObject fo = tree.sourcefile;
561
562 Location loc =
563 fileManager.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH,
564 fo, (pkgName == null) ? null : pkgName);
565 if (loc == null) {
566 Location sourceOutput = fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT) ?
567 StandardLocation.SOURCE_OUTPUT : StandardLocation.CLASS_OUTPUT;
568 loc =
569 fileManager.getLocationForModule(sourceOutput,
570 fo, (pkgName == null) ? null : pkgName);
571 }
572 return loc;
573 }
574
575 private void checkSpecifiedModule(List<JCCompilationUnit> trees, String moduleOverride, JCDiagnostic.Error error) {
576 if (moduleOverride != null) {
577 JavaFileObject prev = log.useSource(trees.head.sourcefile);
578 try {
579 log.error(trees.head.pos(), error);
580 } finally {
581 log.useSource(prev);
582 }
583 }
584 }
585
586 private void checkNoAllModulePath() {
587 if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) {
588 log.error(Errors.AddmodsAllModulePathInvalid);
589 }
590 }
591
592 private final Completer mainCompleter = new Completer() {
593 @Override
594 public void complete(Symbol sym) throws CompletionFailure {
595 ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym);
1646 return msym.name + "["
1647 + "kind:" + msym.kind + ";"
1648 + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";"
1649 + "info:" + toString(msym.module_info.sourcefile) + ","
1650 + toString(msym.module_info.classfile) + ","
1651 + msym.module_info.completer
1652 + "]";
1653 }
1654
1655 // DEBUG
1656 String toString(Location locn) {
1657 return (locn == null) ? "--" : locn.getName();
1658 }
1659
1660 // DEBUG
1661 String toString(JavaFileObject fo) {
1662 return (fo == null) ? "--" : fo.getName();
1663 }
1664
1665 public void newRound() {
1666 allModules = null;
1667 rootModules = null;
1668 warnedMissing.clear();
1669 }
1670 }
|