141 private final Source source;
142 private final boolean allowModules;
143
144 public final boolean multiModuleMode;
145
146 private final String moduleOverride;
147
148 private final Name java_se;
149 private final Name java_;
150
151 ModuleSymbol defaultModule;
152
153 private final String addExportsOpt;
154 private Map<ModuleSymbol, Set<ExportsDirective>> addExports;
155 private final String addReadsOpt;
156 private Map<ModuleSymbol, Set<RequiresDirective>> addReads;
157 private final String addModsOpt;
158 private final Set<String> extraAddMods = new HashSet<>();
159 private final String limitModsOpt;
160 private final Set<String> extraLimitMods = new HashSet<>();
161
162 private final boolean lintOptions;
163
164 private Set<ModuleSymbol> rootModules = null;
165
166 public static Modules instance(Context context) {
167 Modules instance = context.get(Modules.class);
168 if (instance == null)
169 instance = new Modules(context);
170 return instance;
171 }
172
173 protected Modules(Context context) {
174 context.put(Modules.class, this);
175 log = Log.instance(context);
176 names = Names.instance(context);
177 syms = Symtab.instance(context);
178 attr = Attr.instance(context);
179 chk = Check.instance(context);
180 deferredLintHandler = DeferredLintHandler.instance(context);
186 allowModules = source.allowModules();
187 Options options = Options.instance(context);
188
189 lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
190
191 moduleOverride = options.get(Option.XMODULE);
192
193 multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
194 ClassWriter classWriter = ClassWriter.instance(context);
195 classWriter.multiModuleMode = multiModuleMode;
196 JNIWriter jniWriter = JNIWriter.instance(context);
197 jniWriter.multiModuleMode = multiModuleMode;
198
199 java_se = names.fromString("java.se");
200 java_ = names.fromString("java.");
201
202 addExportsOpt = options.get(Option.ADD_EXPORTS);
203 addReadsOpt = options.get(Option.ADD_READS);
204 addModsOpt = options.get(Option.ADD_MODULES);
205 limitModsOpt = options.get(Option.LIMIT_MODULES);
206 }
207
208 int depth = -1;
209 private void dprintln(String msg) {
210 for (int i = 0; i < depth; i++)
211 System.err.print(" ");
212 System.err.println(msg);
213 }
214
215 public void addExtraAddModules(String... extras) {
216 extraAddMods.addAll(Arrays.asList(extras));
217 }
218
219 public void addExtraLimitModules(String... extras) {
220 extraLimitMods.addAll(Arrays.asList(extras));
221 }
222
223 boolean inInitModules;
224 public void initModules(List<JCCompilationUnit> trees) {
225 Assert.check(!inInitModules);
578 directives.add(d);
579 requires.add(d);
580 }
581
582 RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
583 directives.add(requiresUnnamed);
584 requires.add(requiresUnnamed);
585
586 msym.requires = requires.toList();
587 msym.directives = directives.toList();
588 }
589
590 private Completer getSourceCompleter(JCCompilationUnit tree) {
591 return new Completer() {
592 @Override
593 public void complete(Symbol sym) throws CompletionFailure {
594 ModuleSymbol msym = (ModuleSymbol) sym;
595 msym.flags_field |= UNATTRIBUTED;
596 ModuleVisitor v = new ModuleVisitor();
597 JavaFileObject prev = log.useSource(tree.sourcefile);
598 try {
599 JCModuleDecl moduleDecl = tree.getModuleDecl();
600 moduleDecl.accept(v);
601 completeModule(msym);
602 checkCyclicDependencies(moduleDecl);
603 } finally {
604 log.useSource(prev);
605 msym.flags_field &= ~UNATTRIBUTED;
606 }
607 }
608
609 @Override
610 public String toString() {
611 return "SourceCompleter: " + tree.sourcefile.getName();
612 }
613
614 };
615 }
616
617 class ModuleVisitor extends JCTree.Visitor {
618 private ModuleSymbol sym;
619 private final Set<ModuleSymbol> allRequires = new HashSet<>();
620 private final Map<PackageSymbol,List<ExportsDirective>> allExports = new HashMap<>();
621 private final Map<PackageSymbol,List<OpensDirective>> allOpens = new HashMap<>();
622
623 @Override
624 public void visitModuleDef(JCModuleDecl tree) {
661
662 @Override
663 public void visitExports(JCExports tree) {
664 Name name = TreeInfo.fullName(tree.qualid);
665 PackageSymbol packge = syms.enterPackage(sym, name);
666 attr.setPackageSymbols(tree.qualid, packge);
667
668 if (tree.hasTag(Tag.OPENS) && sym.flags.contains(ModuleFlags.OPEN)) {
669 log.error(tree.pos(), Errors.NoOpensUnlessStrong);
670 }
671 List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil());
672 for (ExportsDirective d : exportsForPackage) {
673 reportExportsConflict(tree, packge);
674 }
675
676 List<ModuleSymbol> toModules = null;
677 if (tree.moduleNames != null) {
678 Set<ModuleSymbol> to = new LinkedHashSet<>();
679 for (JCExpression n: tree.moduleNames) {
680 ModuleSymbol msym = lookupModule(n);
681 if (msym.kind != MDL) {
682 log.error(n.pos(), Errors.ModuleNotFound(msym));
683 } else {
684 for (ExportsDirective d : exportsForPackage) {
685 checkDuplicateExportsToModule(n, msym, d);
686 }
687 if (!to.add(msym)) {
688 reportExportsConflictToModule(n, msym);
689 }
690 }
691 }
692 toModules = List.from(to);
693 }
694
695 if (toModules == null || !toModules.isEmpty()) {
696 Set<ExportsFlag> flags = EnumSet.noneOf(ExportsFlag.class);
697 ExportsDirective d = new ExportsDirective(packge, toModules, flags);
698 sym.exports = sym.exports.prepend(d);
699 tree.directive = d;
700
701 allExports.put(packge, exportsForPackage.prepend(d));
702 }
703 }
704
705 private void reportExportsConflict(JCExports tree, PackageSymbol packge) {
706 log.error(tree.qualid.pos(), Errors.ConflictingExports(packge));
707 }
708
709 private void checkDuplicateExportsToModule(JCExpression name, ModuleSymbol msym,
710 ExportsDirective d) {
711 if (d.modules != null) {
723
724 @Override
725 public void visitOpens(JCOpens tree) {
726 Name name = TreeInfo.fullName(tree.qualid);
727 PackageSymbol packge = syms.enterPackage(sym, name);
728 attr.setPackageSymbols(tree.qualid, packge);
729
730 if (sym.flags.contains(ModuleFlags.OPEN)) {
731 log.error(tree.pos(), Errors.NoOpensUnlessStrong);
732 }
733 List<OpensDirective> opensForPackage = allOpens.computeIfAbsent(packge, p -> List.nil());
734 for (OpensDirective d : opensForPackage) {
735 reportOpensConflict(tree, packge);
736 }
737
738 List<ModuleSymbol> toModules = null;
739 if (tree.moduleNames != null) {
740 Set<ModuleSymbol> to = new LinkedHashSet<>();
741 for (JCExpression n: tree.moduleNames) {
742 ModuleSymbol msym = lookupModule(n);
743 if (msym.kind != MDL) {
744 log.error(n.pos(), Errors.ModuleNotFound(msym));
745 } else {
746 for (OpensDirective d : opensForPackage) {
747 checkDuplicateOpensToModule(n, msym, d);
748 }
749 if (!to.add(msym)) {
750 reportOpensConflictToModule(n, msym);
751 }
752 }
753 }
754 toModules = List.from(to);
755 }
756
757 if (toModules == null || !toModules.isEmpty()) {
758 Set<OpensFlag> flags = EnumSet.noneOf(OpensFlag.class);
759 OpensDirective d = new OpensDirective(packge, toModules, flags);
760 sym.opens = sym.opens.prepend(d);
761 tree.directive = d;
762
763 allOpens.put(packge, opensForPackage.prepend(d));
764 }
765 }
766
767 private void reportOpensConflict(JCOpens tree, PackageSymbol packge) {
768 log.error(tree.qualid.pos(), Errors.ConflictingOpens(packge));
769 }
770
771 private void checkDuplicateOpensToModule(JCExpression name, ModuleSymbol msym,
772 OpensDirective d) {
773 if (d.modules != null) {
1116 break;
1117 default:
1118 if (!isValidName(added))
1119 continue;
1120 modules = Stream.of(syms.enterModule(names.fromString(added)));
1121 break;
1122 }
1123 modules.forEach(sym -> {
1124 enabledRoot.add(sym);
1125 if (observable != null)
1126 observable.add(sym);
1127 });
1128 }
1129 }
1130
1131 Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable);
1132
1133 result.add(syms.unnamedModule);
1134
1135 allModules = result;
1136 }
1137
1138 public boolean isInModuleGraph(ModuleSymbol msym) {
1139 return allModules == null || allModules.contains(msym);
1140 }
1141
1142 private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
1143 List<ModuleSymbol> todo = List.nil();
1144
1145 for (ModuleSymbol ms : base) {
1146 todo = todo.prepend(ms);
1147 }
1148
1149 Set<ModuleSymbol> result = new LinkedHashSet<>();
1150 result.add(syms.java_base);
1151
1152 while (todo.nonEmpty()) {
1153 ModuleSymbol current = todo.head;
1154 todo = todo.tail;
1155 if (observable != null && !observable.contains(current))
|
141 private final Source source;
142 private final boolean allowModules;
143
144 public final boolean multiModuleMode;
145
146 private final String moduleOverride;
147
148 private final Name java_se;
149 private final Name java_;
150
151 ModuleSymbol defaultModule;
152
153 private final String addExportsOpt;
154 private Map<ModuleSymbol, Set<ExportsDirective>> addExports;
155 private final String addReadsOpt;
156 private Map<ModuleSymbol, Set<RequiresDirective>> addReads;
157 private final String addModsOpt;
158 private final Set<String> extraAddMods = new HashSet<>();
159 private final String limitModsOpt;
160 private final Set<String> extraLimitMods = new HashSet<>();
161 private final String moduleVersionOpt;
162
163 private final boolean lintOptions;
164
165 private Set<ModuleSymbol> rootModules = null;
166
167 public static Modules instance(Context context) {
168 Modules instance = context.get(Modules.class);
169 if (instance == null)
170 instance = new Modules(context);
171 return instance;
172 }
173
174 protected Modules(Context context) {
175 context.put(Modules.class, this);
176 log = Log.instance(context);
177 names = Names.instance(context);
178 syms = Symtab.instance(context);
179 attr = Attr.instance(context);
180 chk = Check.instance(context);
181 deferredLintHandler = DeferredLintHandler.instance(context);
187 allowModules = source.allowModules();
188 Options options = Options.instance(context);
189
190 lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
191
192 moduleOverride = options.get(Option.XMODULE);
193
194 multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
195 ClassWriter classWriter = ClassWriter.instance(context);
196 classWriter.multiModuleMode = multiModuleMode;
197 JNIWriter jniWriter = JNIWriter.instance(context);
198 jniWriter.multiModuleMode = multiModuleMode;
199
200 java_se = names.fromString("java.se");
201 java_ = names.fromString("java.");
202
203 addExportsOpt = options.get(Option.ADD_EXPORTS);
204 addReadsOpt = options.get(Option.ADD_READS);
205 addModsOpt = options.get(Option.ADD_MODULES);
206 limitModsOpt = options.get(Option.LIMIT_MODULES);
207 moduleVersionOpt = options.get(Option.MODULE_VERSION);
208 }
209
210 int depth = -1;
211 private void dprintln(String msg) {
212 for (int i = 0; i < depth; i++)
213 System.err.print(" ");
214 System.err.println(msg);
215 }
216
217 public void addExtraAddModules(String... extras) {
218 extraAddMods.addAll(Arrays.asList(extras));
219 }
220
221 public void addExtraLimitModules(String... extras) {
222 extraLimitMods.addAll(Arrays.asList(extras));
223 }
224
225 boolean inInitModules;
226 public void initModules(List<JCCompilationUnit> trees) {
227 Assert.check(!inInitModules);
580 directives.add(d);
581 requires.add(d);
582 }
583
584 RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule);
585 directives.add(requiresUnnamed);
586 requires.add(requiresUnnamed);
587
588 msym.requires = requires.toList();
589 msym.directives = directives.toList();
590 }
591
592 private Completer getSourceCompleter(JCCompilationUnit tree) {
593 return new Completer() {
594 @Override
595 public void complete(Symbol sym) throws CompletionFailure {
596 ModuleSymbol msym = (ModuleSymbol) sym;
597 msym.flags_field |= UNATTRIBUTED;
598 ModuleVisitor v = new ModuleVisitor();
599 JavaFileObject prev = log.useSource(tree.sourcefile);
600 JCModuleDecl moduleDecl = tree.getModuleDecl();
601 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(moduleDecl.pos());
602
603 try {
604 moduleDecl.accept(v);
605 completeModule(msym);
606 checkCyclicDependencies(moduleDecl);
607 } finally {
608 log.useSource(prev);
609 deferredLintHandler.setPos(prevLintPos);
610 msym.flags_field &= ~UNATTRIBUTED;
611 }
612 }
613
614 @Override
615 public String toString() {
616 return "SourceCompleter: " + tree.sourcefile.getName();
617 }
618
619 };
620 }
621
622 class ModuleVisitor extends JCTree.Visitor {
623 private ModuleSymbol sym;
624 private final Set<ModuleSymbol> allRequires = new HashSet<>();
625 private final Map<PackageSymbol,List<ExportsDirective>> allExports = new HashMap<>();
626 private final Map<PackageSymbol,List<OpensDirective>> allOpens = new HashMap<>();
627
628 @Override
629 public void visitModuleDef(JCModuleDecl tree) {
666
667 @Override
668 public void visitExports(JCExports tree) {
669 Name name = TreeInfo.fullName(tree.qualid);
670 PackageSymbol packge = syms.enterPackage(sym, name);
671 attr.setPackageSymbols(tree.qualid, packge);
672
673 if (tree.hasTag(Tag.OPENS) && sym.flags.contains(ModuleFlags.OPEN)) {
674 log.error(tree.pos(), Errors.NoOpensUnlessStrong);
675 }
676 List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil());
677 for (ExportsDirective d : exportsForPackage) {
678 reportExportsConflict(tree, packge);
679 }
680
681 List<ModuleSymbol> toModules = null;
682 if (tree.moduleNames != null) {
683 Set<ModuleSymbol> to = new LinkedHashSet<>();
684 for (JCExpression n: tree.moduleNames) {
685 ModuleSymbol msym = lookupModule(n);
686 chk.checkModuleExists(n.pos(), msym);
687 for (ExportsDirective d : exportsForPackage) {
688 checkDuplicateExportsToModule(n, msym, d);
689 }
690 if (!to.add(msym)) {
691 reportExportsConflictToModule(n, msym);
692 }
693 }
694 toModules = List.from(to);
695 }
696
697 if (toModules == null || !toModules.isEmpty()) {
698 Set<ExportsFlag> flags = EnumSet.noneOf(ExportsFlag.class);
699 ExportsDirective d = new ExportsDirective(packge, toModules, flags);
700 sym.exports = sym.exports.prepend(d);
701 tree.directive = d;
702
703 allExports.put(packge, exportsForPackage.prepend(d));
704 }
705 }
706
707 private void reportExportsConflict(JCExports tree, PackageSymbol packge) {
708 log.error(tree.qualid.pos(), Errors.ConflictingExports(packge));
709 }
710
711 private void checkDuplicateExportsToModule(JCExpression name, ModuleSymbol msym,
712 ExportsDirective d) {
713 if (d.modules != null) {
725
726 @Override
727 public void visitOpens(JCOpens tree) {
728 Name name = TreeInfo.fullName(tree.qualid);
729 PackageSymbol packge = syms.enterPackage(sym, name);
730 attr.setPackageSymbols(tree.qualid, packge);
731
732 if (sym.flags.contains(ModuleFlags.OPEN)) {
733 log.error(tree.pos(), Errors.NoOpensUnlessStrong);
734 }
735 List<OpensDirective> opensForPackage = allOpens.computeIfAbsent(packge, p -> List.nil());
736 for (OpensDirective d : opensForPackage) {
737 reportOpensConflict(tree, packge);
738 }
739
740 List<ModuleSymbol> toModules = null;
741 if (tree.moduleNames != null) {
742 Set<ModuleSymbol> to = new LinkedHashSet<>();
743 for (JCExpression n: tree.moduleNames) {
744 ModuleSymbol msym = lookupModule(n);
745 chk.checkModuleExists(n.pos(), msym);
746 for (OpensDirective d : opensForPackage) {
747 checkDuplicateOpensToModule(n, msym, d);
748 }
749 if (!to.add(msym)) {
750 reportOpensConflictToModule(n, msym);
751 }
752 }
753 toModules = List.from(to);
754 }
755
756 if (toModules == null || !toModules.isEmpty()) {
757 Set<OpensFlag> flags = EnumSet.noneOf(OpensFlag.class);
758 OpensDirective d = new OpensDirective(packge, toModules, flags);
759 sym.opens = sym.opens.prepend(d);
760 tree.directive = d;
761
762 allOpens.put(packge, opensForPackage.prepend(d));
763 }
764 }
765
766 private void reportOpensConflict(JCOpens tree, PackageSymbol packge) {
767 log.error(tree.qualid.pos(), Errors.ConflictingOpens(packge));
768 }
769
770 private void checkDuplicateOpensToModule(JCExpression name, ModuleSymbol msym,
771 OpensDirective d) {
772 if (d.modules != null) {
1115 break;
1116 default:
1117 if (!isValidName(added))
1118 continue;
1119 modules = Stream.of(syms.enterModule(names.fromString(added)));
1120 break;
1121 }
1122 modules.forEach(sym -> {
1123 enabledRoot.add(sym);
1124 if (observable != null)
1125 observable.add(sym);
1126 });
1127 }
1128 }
1129
1130 Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable);
1131
1132 result.add(syms.unnamedModule);
1133
1134 allModules = result;
1135
1136 //add module versions from options, if any:
1137 if (moduleVersionOpt != null) {
1138 Name version = names.fromString(moduleVersionOpt);
1139 rootModules.forEach(m -> m.version = version);
1140 }
1141 }
1142
1143 public boolean isInModuleGraph(ModuleSymbol msym) {
1144 return allModules == null || allModules.contains(msym);
1145 }
1146
1147 private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) {
1148 List<ModuleSymbol> todo = List.nil();
1149
1150 for (ModuleSymbol ms : base) {
1151 todo = todo.prepend(ms);
1152 }
1153
1154 Set<ModuleSymbol> result = new LinkedHashSet<>();
1155 result.add(syms.java_base);
1156
1157 while (todo.nonEmpty()) {
1158 ModuleSymbol current = todo.head;
1159 todo = todo.tail;
1160 if (observable != null && !observable.contains(current))
|