Modules.java revision 3451:a8fefe4d1826
113546Sjulian/* 2113661Sdeischen * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. 335509Sjb * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 413546Sjulian * 513546Sjulian * This code is free software; you can redistribute it and/or modify it 613546Sjulian * under the terms of the GNU General Public License version 2 only, as 713546Sjulian * published by the Free Software Foundation. Oracle designates this 813546Sjulian * particular file as subject to the "Classpath" exception as provided 913546Sjulian * by Oracle in the LICENSE file that accompanied this code. 1013546Sjulian * 1113546Sjulian * This code is distributed in the hope that it will be useful, but WITHOUT 1213546Sjulian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1313546Sjulian * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1413546Sjulian * version 2 for more details (a copy is included in the LICENSE file that 1513546Sjulian * accompanied this code). 1613546Sjulian * 1713546Sjulian * You should have received a copy of the GNU General Public License version 1813546Sjulian * 2 along with this work; if not, write to the Free Software Foundation, 1913546Sjulian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2013546Sjulian * 2113546Sjulian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2213546Sjulian * or visit www.oracle.com if you need additional information or have any 2313546Sjulian * questions. 2444963Sjb */ 2513546Sjulian 2613546Sjulian 2713546Sjulianpackage com.sun.tools.javac.comp; 2813546Sjulian 2913546Sjulianimport java.io.IOException; 3013546Sjulianimport java.util.Arrays; 3113546Sjulianimport java.util.Collection; 3213546Sjulianimport java.util.Collections; 3350476Speterimport java.util.EnumSet; 3413546Sjulianimport java.util.HashMap; 3513546Sjulianimport java.util.HashSet; 3613546Sjulianimport java.util.LinkedHashMap; 3713546Sjulianimport java.util.LinkedHashSet; 3813546Sjulianimport java.util.Map; 3971581Sdeischenimport java.util.Map.Entry; 4071581Sdeischenimport java.util.Set; 4171581Sdeischenimport java.util.function.Predicate; 42116977Sdavidxuimport java.util.regex.Matcher; 4371581Sdeischenimport java.util.regex.Pattern; 4471581Sdeischenimport java.util.stream.Stream; 4553812Salfred 4671581Sdeischenimport javax.lang.model.SourceVersion; 4771581Sdeischenimport javax.tools.JavaFileManager; 4871581Sdeischenimport javax.tools.JavaFileManager.Location; 4971581Sdeischenimport javax.tools.JavaFileObject; 5071581Sdeischenimport javax.tools.JavaFileObject.Kind; 5148046Sjbimport javax.tools.StandardLocation; 5213546Sjulian 5338208Sjbimport com.sun.tools.javac.code.Directive; 5471581Sdeischenimport com.sun.tools.javac.code.Directive.ExportsDirective; 5548569Sjasoneimport com.sun.tools.javac.code.Directive.RequiresDirective; 5671581Sdeischenimport com.sun.tools.javac.code.Directive.RequiresFlag; 5771581Sdeischenimport com.sun.tools.javac.code.Directive.UsesDirective; 5871581Sdeischenimport com.sun.tools.javac.code.Flags; 5971581Sdeischenimport com.sun.tools.javac.code.Kinds; 6013546Sjulianimport com.sun.tools.javac.code.ModuleFinder; 61113658Sdeischenimport com.sun.tools.javac.code.Source; 6271581Sdeischenimport com.sun.tools.javac.code.Symbol; 6371581Sdeischenimport com.sun.tools.javac.code.Symbol.ClassSymbol; 6471581Sdeischenimport com.sun.tools.javac.code.Symbol.Completer; 6571581Sdeischenimport com.sun.tools.javac.code.Symbol.CompletionFailure; 6671581Sdeischenimport com.sun.tools.javac.code.Symbol.MethodSymbol; 6771581Sdeischenimport com.sun.tools.javac.code.Symbol.ModuleSymbol; 6871581Sdeischenimport com.sun.tools.javac.code.Symbol.PackageSymbol; 69113658Sdeischenimport com.sun.tools.javac.code.Symtab; 70103388Sminiimport com.sun.tools.javac.code.Type; 71113658Sdeischenimport com.sun.tools.javac.code.Types; 7213546Sjulianimport com.sun.tools.javac.jvm.ClassWriter; 73113658Sdeischenimport com.sun.tools.javac.jvm.JNIWriter; 74113658Sdeischenimport com.sun.tools.javac.main.Option; 75113658Sdeischenimport com.sun.tools.javac.resources.CompilerProperties.Errors; 76115080Sdeischenimport com.sun.tools.javac.resources.CompilerProperties.Warnings; 77113658Sdeischenimport com.sun.tools.javac.tree.JCTree; 78113658Sdeischenimport com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 79113658Sdeischenimport com.sun.tools.javac.tree.JCTree.JCExports; 80113658Sdeischenimport com.sun.tools.javac.tree.JCTree.JCExpression; 8170702Sobrienimport com.sun.tools.javac.tree.JCTree.JCModuleDecl; 8271581Sdeischenimport com.sun.tools.javac.tree.JCTree.JCPackageDecl; 83113658Sdeischenimport com.sun.tools.javac.tree.JCTree.JCProvides; 8471581Sdeischenimport com.sun.tools.javac.tree.JCTree.JCRequires; 8571581Sdeischenimport com.sun.tools.javac.tree.JCTree.JCUses; 8671581Sdeischenimport com.sun.tools.javac.tree.TreeInfo; 8771581Sdeischenimport com.sun.tools.javac.util.Assert; 8871581Sdeischenimport com.sun.tools.javac.util.Context; 8971581Sdeischenimport com.sun.tools.javac.util.JCDiagnostic; 9071581Sdeischenimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 9171581Sdeischenimport com.sun.tools.javac.util.List; 9271581Sdeischenimport com.sun.tools.javac.util.ListBuffer; 9371581Sdeischenimport com.sun.tools.javac.util.Log; 9471581Sdeischenimport com.sun.tools.javac.util.Name; 9571581Sdeischenimport com.sun.tools.javac.util.Names; 9671581Sdeischenimport com.sun.tools.javac.util.Options; 9771581Sdeischen 9871581Sdeischenimport static com.sun.tools.javac.code.Flags.UNATTRIBUTED; 9971581Sdeischenimport static com.sun.tools.javac.code.Kinds.Kind.MDL; 10071581Sdeischenimport static com.sun.tools.javac.code.TypeTag.CLASS; 10171581Sdeischen 10271581Sdeischenimport com.sun.tools.javac.tree.JCTree.JCDirective; 10371581Sdeischenimport com.sun.tools.javac.tree.JCTree.Tag; 10471581Sdeischen 10571581Sdeischenimport static com.sun.tools.javac.code.Flags.ABSTRACT; 10671581Sdeischenimport static com.sun.tools.javac.code.Flags.ENUM; 10771581Sdeischenimport static com.sun.tools.javac.code.Flags.PUBLIC; 10871581Sdeischenimport static com.sun.tools.javac.tree.JCTree.Tag.MODULEDEF; 10971581Sdeischen 11071581Sdeischen/** 11171581Sdeischen * TODO: fill in 11271581Sdeischen * 11371581Sdeischen * <p><b>This is NOT part of any supported API. 11471581Sdeischen * If you write code that depends on this, you do so at your own risk. 11571581Sdeischen * This code and its internal interfaces are subject to change or 11671581Sdeischen * deletion without notice.</b> 11771581Sdeischen */ 11871581Sdeischenpublic class Modules extends JCTree.Visitor { 11971581Sdeischen private static final String ALL_SYSTEM = "ALL-SYSTEM"; 12071581Sdeischen private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; 12171581Sdeischen 12271581Sdeischen private final Log log; 12371581Sdeischen private final Names names; 12471581Sdeischen private final Symtab syms; 12571581Sdeischen private final Attr attr; 12671581Sdeischen private final TypeEnvs typeEnvs; 12771581Sdeischen private final Types types; 12871581Sdeischen private final JavaFileManager fileManager; 12971581Sdeischen private final ModuleFinder moduleFinder; 13071581Sdeischen private final boolean allowModules; 13171581Sdeischen 13271581Sdeischen public final boolean multiModuleMode; 13371581Sdeischen 13471581Sdeischen private final String moduleOverride; 13571581Sdeischen 136115080Sdeischen private final Name java_se; 13771581Sdeischen private final Name java_; 13871581Sdeischen 13971581Sdeischen ModuleSymbol defaultModule; 14071581Sdeischen 14171581Sdeischen private final String addExportsOpt; 14271581Sdeischen private Map<ModuleSymbol, Set<ExportsDirective>> addExports; 14370702Sobrien private final String addReadsOpt; 14470702Sobrien private Map<ModuleSymbol, Set<RequiresDirective>> addReads; 14570702Sobrien private final String addModsOpt; 14670702Sobrien private final String limitModsOpt; 14770702Sobrien 14871581Sdeischen private Set<ModuleSymbol> rootModules = Collections.emptySet(); 14971581Sdeischen 15071581Sdeischen public static Modules instance(Context context) { 15171581Sdeischen Modules instance = context.get(Modules.class); 15271581Sdeischen if (instance == null) 15371581Sdeischen instance = new Modules(context); 15471581Sdeischen return instance; 15571581Sdeischen } 15671581Sdeischen 15771581Sdeischen protected Modules(Context context) { 15871581Sdeischen context.put(Modules.class, this); 15970702Sobrien log = Log.instance(context); 16070702Sobrien names = Names.instance(context); 161113658Sdeischen syms = Symtab.instance(context); 162113658Sdeischen attr = Attr.instance(context); 16333292Sjulian typeEnvs = TypeEnvs.instance(context); 164113658Sdeischen moduleFinder = ModuleFinder.instance(context); 165113658Sdeischen types = Types.instance(context); 166113658Sdeischen fileManager = context.get(JavaFileManager.class); 167113658Sdeischen allowModules = Source.instance(context).allowModules(); 168113658Sdeischen Options options = Options.instance(context); 169113658Sdeischen 170113658Sdeischen moduleOverride = options.get(Option.XMODULE); 171113658Sdeischen 172113658Sdeischen multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); 173113658Sdeischen ClassWriter classWriter = ClassWriter.instance(context); 174113658Sdeischen classWriter.multiModuleMode = multiModuleMode; 175113658Sdeischen JNIWriter jniWriter = JNIWriter.instance(context); 176113658Sdeischen jniWriter.multiModuleMode = multiModuleMode; 177113658Sdeischen 178113658Sdeischen java_se = names.fromString("java.se"); 179113658Sdeischen java_ = names.fromString("java."); 180113658Sdeischen 181113658Sdeischen addExportsOpt = options.get(Option.XADDEXPORTS); 182113658Sdeischen addReadsOpt = options.get(Option.XADDREADS); 183113658Sdeischen addModsOpt = options.get(Option.ADDMODS); 184113658Sdeischen limitModsOpt = options.get(Option.LIMITMODS); 185113658Sdeischen } 186113658Sdeischen 187113658Sdeischen int depth = -1; 188113658Sdeischen private void dprintln(String msg) { 189113658Sdeischen for (int i = 0; i < depth; i++) 190113658Sdeischen System.err.print(" "); 191113658Sdeischen System.err.println(msg); 192113658Sdeischen } 193113658Sdeischen 194113658Sdeischen public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) { 195113658Sdeischen if (!allowModules) { 196113658Sdeischen for (JCCompilationUnit tree: trees) { 197113658Sdeischen tree.modle = syms.noModule; 198113658Sdeischen } 199113658Sdeischen defaultModule = syms.noModule; 20022315Sjulian return true; 201113658Sdeischen } 202113658Sdeischen 203113658Sdeischen int startErrors = log.nerrors; 204113658Sdeischen 205113658Sdeischen depth++; 206113658Sdeischen try { 207113658Sdeischen // scan trees for module defs 208113658Sdeischen Set<ModuleSymbol> roots = enterModules(trees, c); 209113658Sdeischen 21022315Sjulian setCompilationUnitModules(trees, roots); 21113546Sjulian 212113658Sdeischen if (!roots.isEmpty() && this.rootModules.isEmpty()) { 21313546Sjulian this.rootModules = roots; 214113658Sdeischen allModules(); //ensure errors reported 21596501Salfred } 216111035Smini 217113658Sdeischen for (ModuleSymbol msym: roots) { 218113658Sdeischen msym.complete(); 219111035Smini } 220111035Smini } finally { 22138208Sjb depth--; 22271581Sdeischen } 22370702Sobrien 22470702Sobrien return (log.nerrors == startErrors); 22571581Sdeischen } 22671581Sdeischen 22770702Sobrien public Completer getCompleter() { 22870702Sobrien return mainCompleter; 229113658Sdeischen } 230113658Sdeischen 231113658Sdeischen public ModuleSymbol getDefaultModule() { 232113658Sdeischen return defaultModule; 233113658Sdeischen } 234113658Sdeischen 235113658Sdeischen private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) { 236113658Sdeischen Set<ModuleSymbol> modules = new LinkedHashSet<>(); 23738208Sjb for (JCCompilationUnit tree : trees) { 23838208Sjb JavaFileObject prev = log.useSource(tree.sourcefile); 23938208Sjb try { 240113658Sdeischen enterModule(tree, c, modules); 24138208Sjb } finally { 24238208Sjb log.useSource(prev); 24338208Sjb } 24438208Sjb } 24548569Sjasone return modules; 24638208Sjb } 24748569Sjasone 24838208Sjb 24971581Sdeischen private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set<ModuleSymbol> modules) { 25038208Sjb boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE); 25148569Sjasone boolean isModuleDecl = toplevel.defs.nonEmpty() && toplevel.defs.head.hasTag(MODULEDEF); 25238208Sjb if (isModuleInfo && isModuleDecl) { 25397204Sdeischen JCModuleDecl decl = (JCModuleDecl) toplevel.defs.head; 25438208Sjb Name name = TreeInfo.fullName(decl.qualId); 25538208Sjb ModuleSymbol sym; 25638208Sjb if (c != null) { 257113658Sdeischen sym = (ModuleSymbol) c.owner; 258113658Sdeischen if (sym.name == null) { 259113658Sdeischen //ModuleFinder.findSingleModule creates a stub of a ModuleSymbol without a name, 26013546Sjulian //fill the name here after the module-info.java has been parsed 261113658Sdeischen //also enter the ModuleSymbol among modules: 262113658Sdeischen syms.enterModule(sym, name); 263113658Sdeischen } else { 264113658Sdeischen // TODO: validate name 265113658Sdeischen } 266113658Sdeischen } else { 267113658Sdeischen sym = syms.enterModule(name); 268113658Sdeischen if (sym.module_info.sourcefile != null && sym.module_info.sourcefile != toplevel.sourcefile) { 26944963Sjb log.error(decl.pos(), Errors.DuplicateModule(sym)); 270113870Sdeischen return; 271113870Sdeischen } 272113870Sdeischen } 273113658Sdeischen sym.completer = getSourceCompleter(toplevel); 274113658Sdeischen sym.module_info.sourcefile = toplevel.sourcefile; 275113658Sdeischen decl.sym = sym; 276113658Sdeischen 277113658Sdeischen if (multiModuleMode || modules.isEmpty()) { 278113658Sdeischen modules.add(sym); 279113658Sdeischen } else { 280113658Sdeischen log.error(toplevel.pos(), Errors.TooManyModules); 281113658Sdeischen } 28255222Sjasone 283113658Sdeischen Env<AttrContext> provisionalEnv = new Env<>(decl, null); 284113658Sdeischen 285113658Sdeischen provisionalEnv.toplevel = toplevel; 28655222Sjasone typeEnvs.put(sym, provisionalEnv); 287113658Sdeischen } else if (isModuleInfo) { 288113658Sdeischen if (multiModuleMode) { 289113661Sdeischen JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head; 290113658Sdeischen log.error(tree.pos(), Errors.ExpectedModule); 291113658Sdeischen } 292113658Sdeischen } else if (isModuleDecl) { 29355193Sdeischen JCTree tree = toplevel.defs.head; 294113658Sdeischen log.error(tree.pos(), Errors.ModuleDeclSbInModuleInfoJava); 295113658Sdeischen } 296113658Sdeischen } 297113658Sdeischen 298113658Sdeischen private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules) { 299113661Sdeischen // update the module for each compilation unit 30056277Sjasone if (multiModuleMode) { 301113658Sdeischen checkNoAllModulePath(); 302113658Sdeischen for (JCCompilationUnit tree: trees) { 303113658Sdeischen if (tree.defs.isEmpty()) { 304113658Sdeischen tree.modle = syms.unnamedModule; 305113658Sdeischen continue; 306113658Sdeischen } 307113658Sdeischen 308116977Sdavidxu JavaFileObject prev = log.useSource(tree.sourcefile); 309115399Skan try { 310113658Sdeischen Location locn = getModuleLocation(tree); 31156277Sjasone if (locn != null) { 312113658Sdeischen Name name = names.fromString(fileManager.inferModuleName(locn)); 313113658Sdeischen ModuleSymbol msym; 314113658Sdeischen if (tree.defs.head.hasTag(MODULEDEF)) { 315113658Sdeischen JCModuleDecl decl = (JCModuleDecl) tree.defs.head; 316113658Sdeischen msym = decl.sym; 317113658Sdeischen if (msym.name != name) { 318113658Sdeischen log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name)); 319114295Sdeischen } 320113658Sdeischen } else { 32167097Sdeischen msym = syms.enterModule(name); 322113658Sdeischen } 323114295Sdeischen if (msym.sourceLocation == null) { 324113658Sdeischen msym.sourceLocation = locn; 325114295Sdeischen if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) { 326106786Smini msym.classLocation = fileManager.getModuleLocation( 327113658Sdeischen StandardLocation.CLASS_OUTPUT, msym.name.toString()); 328113658Sdeischen } 32944963Sjb } 330113658Sdeischen tree.modle = msym; 331113658Sdeischen rootModules.add(msym); 332113658Sdeischen } else { 333113658Sdeischen log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules); 334113658Sdeischen tree.modle = syms.errModule; 335113658Sdeischen } 336113658Sdeischen } catch (IOException e) { 337113658Sdeischen throw new Error(e); // FIXME 338113658Sdeischen } finally { 339113658Sdeischen log.useSource(prev); 340113658Sdeischen } 341113658Sdeischen } 342113658Sdeischen if (syms.unnamedModule.sourceLocation == null) { 34353812Salfred syms.unnamedModule.completer = getUnnamedModuleCompleter(); 344113658Sdeischen syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH; 345113658Sdeischen syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH; 346113658Sdeischen } 347113658Sdeischen defaultModule = syms.unnamedModule; 348113658Sdeischen } else { 349113658Sdeischen if (defaultModule == null) { 350113658Sdeischen switch (rootModules.size()) { 351113658Sdeischen case 0: 352113658Sdeischen defaultModule = moduleFinder.findSingleModule(); 353113658Sdeischen if (defaultModule == syms.unnamedModule) { 354113658Sdeischen if (moduleOverride != null) { 355113658Sdeischen checkNoAllModulePath(); 356113658Sdeischen defaultModule = moduleFinder.findModule(names.fromString(moduleOverride)); 357103419Smini } else { 358113658Sdeischen // Question: why not do findAllModules and initVisiblePackages here? 359113658Sdeischen // i.e. body of unnamedModuleCompleter 360113658Sdeischen defaultModule.completer = getUnnamedModuleCompleter(); 361113658Sdeischen defaultModule.classLocation = StandardLocation.CLASS_PATH; 362113658Sdeischen } 36313546Sjulian } else { 364113658Sdeischen checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleClasspath); 365113658Sdeischen checkNoAllModulePath(); 366113658Sdeischen defaultModule.complete(); 36713546Sjulian // Question: why not do completeModule here? 368113658Sdeischen defaultModule.completer = new Completer() { 369116977Sdavidxu @Override 37071581Sdeischen public void complete(Symbol sym) throws CompletionFailure { 371113658Sdeischen completeModule((ModuleSymbol) sym); 372113658Sdeischen } 373113658Sdeischen }; 374113658Sdeischen } 375113658Sdeischen rootModules.add(defaultModule); 376113658Sdeischen break; 377113658Sdeischen case 1: 37813546Sjulian checkSpecifiedModule(trees, Errors.ModuleInfoWithXmoduleSourcepath); 379113658Sdeischen checkNoAllModulePath(); 380113658Sdeischen defaultModule = rootModules.iterator().next(); 381113658Sdeischen defaultModule.classLocation = StandardLocation.CLASS_OUTPUT; 382113658Sdeischen break; 38344963Sjb default: 384113658Sdeischen Assert.error("too many modules"); 385113658Sdeischen } 38656236Sdeischen defaultModule.sourceLocation = StandardLocation.SOURCE_PATH; 387113658Sdeischen } else if (rootModules.size() == 1 && defaultModule == rootModules.iterator().next()) { 388113658Sdeischen defaultModule.complete(); 389113658Sdeischen defaultModule.completer = sym -> completeModule((ModuleSymbol) sym); 390113658Sdeischen } else { 391113658Sdeischen Assert.check(rootModules.isEmpty()); 392113658Sdeischen } 393113658Sdeischen 394113658Sdeischen if (defaultModule != syms.unnamedModule) { 39567097Sdeischen syms.unnamedModule.completer = getUnnamedModuleCompleter(); 396113658Sdeischen syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH; 397113658Sdeischen syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH; 398113658Sdeischen } 399113658Sdeischen 400113658Sdeischen for (JCCompilationUnit tree: trees) { 40113546Sjulian tree.modle = defaultModule; 402113658Sdeischen } 403113658Sdeischen } 404113658Sdeischen } 405111035Smini 406113658Sdeischen private Location getModuleLocation(JCCompilationUnit tree) throws IOException { 407113658Sdeischen switch (tree.defs.head.getTag()) { 408113658Sdeischen case MODULEDEF: 409113658Sdeischen return getModuleLocation(tree.sourcefile, null); 410113658Sdeischen 411113658Sdeischen case PACKAGEDEF: 412111035Smini JCPackageDecl pkg = (JCPackageDecl) tree.defs.head; 413113658Sdeischen return getModuleLocation(tree.sourcefile, TreeInfo.fullName(pkg.pid)); 414113658Sdeischen 415113658Sdeischen default: 416113658Sdeischen // code in unnamed module 417113658Sdeischen return null; 418113658Sdeischen } 419113658Sdeischen } 420113658Sdeischen 421113658Sdeischen private Location getModuleLocation(JavaFileObject fo, Name pkgName) throws IOException { 422113658Sdeischen // For now, just check module source path. 423113658Sdeischen // We may want to check source path as well. 424111035Smini return fileManager.getModuleLocation(StandardLocation.MODULE_SOURCE_PATH, 425113658Sdeischen fo, (pkgName == null) ? null : pkgName.toString()); 426113658Sdeischen } 427113658Sdeischen 428113658Sdeischen private void checkSpecifiedModule(List<JCCompilationUnit> trees, JCDiagnostic.Error error) { 429113658Sdeischen if (moduleOverride != null) { 430113658Sdeischen JavaFileObject prev = log.useSource(trees.head.sourcefile); 431113658Sdeischen try { 432113658Sdeischen log.error(trees.head.pos(), error); 433113658Sdeischen } finally { 434113658Sdeischen log.useSource(prev); 435113658Sdeischen } 436113658Sdeischen } 437111035Smini } 43848046Sjb 43948046Sjb private void checkNoAllModulePath() { 44048046Sjb if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) { 44148046Sjb log.error(Errors.AddmodsAllModulePathInvalid); 44248046Sjb } 443113658Sdeischen } 444113658Sdeischen 445113658Sdeischen private final Completer mainCompleter = new Completer() { 44648046Sjb @Override 447113658Sdeischen public void complete(Symbol sym) throws CompletionFailure { 448113658Sdeischen ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym); 449113658Sdeischen 450113658Sdeischen if (msym.kind == Kinds.Kind.ERR) { 451113658Sdeischen log.error(Errors.CantFindModule(msym)); 452113658Sdeischen //make sure the module is initialized: 453113658Sdeischen msym.directives = List.nil(); 454113658Sdeischen msym.exports = List.nil(); 455113658Sdeischen msym.provides = List.nil(); 456113658Sdeischen msym.requires = List.nil(); 457113658Sdeischen msym.uses = List.nil(); 458113658Sdeischen } else if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) { 459113658Sdeischen completeAutomaticModule(msym); 46013546Sjulian } else { 46133292Sjulian msym.module_info.complete(); 462113658Sdeischen } 463113658Sdeischen 464113658Sdeischen // If module-info comes from a .java file, the underlying 46513546Sjulian // call of classFinder.fillIn will have called through the 466115828Sdavidxu // source completer, to Enter, and then to Modules.enter, 467115828Sdavidxu // which will call completeModule. 468113658Sdeischen // But, if module-info comes from a .class file, the underlying 469113658Sdeischen // call of classFinder.fillIn will just call ClassReader to read 470113658Sdeischen // the .class file, and so we call completeModule here. 471113658Sdeischen if (msym.module_info.classfile == null || msym.module_info.classfile.getKind() == Kind.CLASS) { 472113658Sdeischen completeModule(msym); 473113658Sdeischen } 474113658Sdeischen } 475114254Sdeischen 476113658Sdeischen @Override 477113658Sdeischen public String toString() { 478113658Sdeischen return "mainCompleter"; 479113658Sdeischen } 480113658Sdeischen }; 481113658Sdeischen 482113658Sdeischen private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure { 483113658Sdeischen try { 484113658Sdeischen ListBuffer<Directive> directives = new ListBuffer<>(); 485113658Sdeischen ListBuffer<ExportsDirective> exports = new ListBuffer<>(); 486115381Sdeischen Set<String> seenPackages = new HashSet<>(); 487113658Sdeischen 488113658Sdeischen for (JavaFileObject clazz : fileManager.list(msym.classLocation, "", EnumSet.of(Kind.CLASS), true)) { 489116977Sdavidxu String binName = fileManager.inferBinaryName(msym.classLocation, clazz); 490113658Sdeischen String pack = binName.lastIndexOf('.') != (-1) ? binName.substring(0, binName.lastIndexOf('.')) : ""; //unnamed package???? 491113658Sdeischen if (seenPackages.add(pack)) { 492113658Sdeischen ExportsDirective d = new ExportsDirective(syms.enterPackage(msym, names.fromString(pack)), null); 493113658Sdeischen directives.add(d); 494113658Sdeischen exports.add(d); 49513546Sjulian } 496 } 497 498 ListBuffer<RequiresDirective> requires = new ListBuffer<>(); 499 500 //ensure all modules are found: 501 moduleFinder.findAllModules(); 502 503 for (ModuleSymbol ms : allModules()) { 504 if (ms == syms.unnamedModule || ms == msym) 505 continue; 506 RequiresDirective d = new RequiresDirective(ms, EnumSet.of(RequiresFlag.PUBLIC)); 507 directives.add(d); 508 requires.add(d); 509 } 510 511 RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule); 512 directives.add(requiresUnnamed); 513 requires.add(requiresUnnamed); 514 515 msym.exports = exports.toList(); 516 msym.provides = List.nil(); 517 msym.requires = requires.toList(); 518 msym.uses = List.nil(); 519 msym.directives = directives.toList(); 520 msym.flags_field |= Flags.ACYCLIC; 521 } catch (IOException ex) { 522 throw new IllegalStateException(ex); 523 } 524 } 525 526 private Completer getSourceCompleter(JCCompilationUnit tree) { 527 return new Completer() { 528 @Override 529 public void complete(Symbol sym) throws CompletionFailure { 530 ModuleSymbol msym = (ModuleSymbol) sym; 531 msym.flags_field |= UNATTRIBUTED; 532 ModuleVisitor v = new ModuleVisitor(); 533 JavaFileObject prev = log.useSource(tree.sourcefile); 534 try { 535 tree.defs.head.accept(v); 536 completeModule(msym); 537 checkCyclicDependencies((JCModuleDecl) tree.defs.head); 538 } finally { 539 log.useSource(prev); 540 msym.flags_field &= ~UNATTRIBUTED; 541 } 542 } 543 544 @Override 545 public String toString() { 546 return "SourceCompleter: " + tree.sourcefile.getName(); 547 } 548 549 }; 550 } 551 552 class ModuleVisitor extends JCTree.Visitor { 553 private ModuleSymbol sym; 554 private final Set<ModuleSymbol> allRequires = new HashSet<>(); 555 private final Set<PackageSymbol> allExports = new HashSet<>(); 556 557 @Override 558 public void visitModuleDef(JCModuleDecl tree) { 559 sym = Assert.checkNonNull(tree.sym); 560 561 sym.requires = List.nil(); 562 sym.exports = List.nil(); 563 tree.directives.forEach(t -> t.accept(this)); 564 sym.requires = sym.requires.reverse(); 565 sym.exports = sym.exports.reverse(); 566 ensureJavaBase(); 567 } 568 569 @Override 570 public void visitRequires(JCRequires tree) { 571 ModuleSymbol msym = lookupModule(tree.moduleName); 572 if (msym.kind != MDL) { 573 log.error(tree.moduleName.pos(), Errors.ModuleNotFound(msym)); 574 } else if (allRequires.contains(msym)) { 575 log.error(tree.moduleName.pos(), Errors.DuplicateRequires(msym)); 576 } else { 577 allRequires.add(msym); 578 Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class); 579 if (tree.isPublic) 580 flags.add(RequiresFlag.PUBLIC); 581 RequiresDirective d = new RequiresDirective(msym, flags); 582 tree.directive = d; 583 sym.requires = sym.requires.prepend(d); 584 } 585 } 586 587 @Override 588 public void visitExports(JCExports tree) { 589 Name name = TreeInfo.fullName(tree.qualid); 590 PackageSymbol packge = syms.enterPackage(sym, name); 591 attr.setPackageSymbols(tree.qualid, packge); 592 if (!allExports.add(packge)) { 593 log.error(tree.qualid.pos(), Errors.DuplicateExports(packge)); 594 } 595 596 List<ModuleSymbol> toModules = null; 597 if (tree.moduleNames != null) { 598 Set<ModuleSymbol> to = new HashSet<>(); 599 for (JCExpression n: tree.moduleNames) { 600 ModuleSymbol msym = lookupModule(n); 601 if (msym.kind != MDL) { 602 log.error(n.pos(), Errors.ModuleNotFound(msym)); 603 } else if (!to.add(msym)) { 604 log.error(n.pos(), Errors.DuplicateExports(msym)); 605 } 606 } 607 toModules = List.from(to); 608 } 609 610 if (toModules == null || !toModules.isEmpty()) { 611 ExportsDirective d = new ExportsDirective(packge, toModules); 612 tree.directive = d; 613 sym.exports = sym.exports.prepend(d); 614 } 615 } 616 617 @Override 618 public void visitProvides(JCProvides tree) { } 619 620 @Override 621 public void visitUses(JCUses tree) { } 622 623 private void ensureJavaBase() { 624 if (sym.name == names.java_base) 625 return; 626 627 for (RequiresDirective d: sym.requires) { 628 if (d.module.name == names.java_base) 629 return; 630 } 631 632 ModuleSymbol java_base = syms.enterModule(names.java_base); 633 Directive.RequiresDirective d = 634 new Directive.RequiresDirective(java_base, 635 EnumSet.of(Directive.RequiresFlag.MANDATED)); 636 sym.requires = sym.requires.prepend(d); 637 } 638 639 private ModuleSymbol lookupModule(JCExpression moduleName) { 640 try { 641 Name name = TreeInfo.fullName(moduleName); 642 ModuleSymbol msym = moduleFinder.findModule(name); 643 TreeInfo.setSymbol(moduleName, msym); 644 return msym; 645 } catch (Throwable t) { 646 System.err.println("Module " + sym + "; lookup export " + moduleName); 647 throw t; 648 } 649 } 650 } 651 652 public Completer getUsesProvidesCompleter() { 653 return sym -> { 654 ModuleSymbol msym = (ModuleSymbol) sym; 655 Env<AttrContext> env = typeEnvs.get(msym); 656 UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env); 657 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 658 try { 659 env.toplevel.defs.head.accept(v); 660 } finally { 661 log.useSource(prev); 662 } 663 }; 664 } 665 666 class UsesProvidesVisitor extends JCTree.Visitor { 667 private final ModuleSymbol msym; 668 private final Env<AttrContext> env; 669 670 private final Set<Directive.UsesDirective> allUses = new HashSet<>(); 671 private final Set<Directive.ProvidesDirective> allProvides = new HashSet<>(); 672 673 public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) { 674 this.msym = msym; 675 this.env = env; 676 } 677 678 @Override @SuppressWarnings("unchecked") 679 public void visitModuleDef(JCModuleDecl tree) { 680 msym.directives = List.nil(); 681 msym.provides = List.nil(); 682 msym.uses = List.nil(); 683 tree.directives.forEach(t -> t.accept(this)); 684 msym.directives = msym.directives.reverse(); 685 msym.provides = msym.provides.reverse(); 686 msym.uses = msym.uses.reverse(); 687 688 if (msym.requires.nonEmpty() && msym.requires.head.flags.contains(RequiresFlag.MANDATED)) 689 msym.directives = msym.directives.prepend(msym.requires.head); 690 691 msym.directives = msym.directives.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet()))); 692 693 checkForCorrectness(); 694 } 695 696 @Override 697 public void visitExports(JCExports tree) { 698 if (tree.directive.packge.members().isEmpty()) { 699 log.error(tree.qualid.pos(), Errors.PackageEmptyOrNotFound(tree.directive.packge)); 700 } 701 msym.directives = msym.directives.prepend(tree.directive); 702 } 703 704 MethodSymbol noArgsConstructor(ClassSymbol tsym) { 705 for (Symbol sym : tsym.members().getSymbolsByName(names.init)) { 706 MethodSymbol mSym = (MethodSymbol)sym; 707 if (mSym.params().isEmpty()) { 708 return mSym; 709 } 710 } 711 return null; 712 } 713 714 Map<Directive.ProvidesDirective, JCProvides> directiveToTreeMap = new HashMap<>(); 715 716 @Override 717 public void visitProvides(JCProvides tree) { 718 Type st = attr.attribType(tree.serviceName, env, syms.objectType); 719 Type it = attr.attribType(tree.implName, env, syms.objectType); 720 ClassSymbol service = (ClassSymbol) st.tsym; 721 ClassSymbol impl = (ClassSymbol) it.tsym; 722 if (!types.isSubtype(it, st)) { 723 log.error(tree.implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface); 724 } 725 if ((impl.flags() & ABSTRACT) != 0) { 726 log.error(tree.implName.pos(), Errors.ServiceImplementationIsAbstract(impl)); 727 } else if (impl.isInner()) { 728 log.error(tree.implName.pos(), Errors.ServiceImplementationIsInner(impl)); 729 } else if (service.isInner()) { 730 log.error(tree.serviceName.pos(), Errors.ServiceDefinitionIsInner(service)); 731 } else { 732 MethodSymbol constr = noArgsConstructor(impl); 733 if (constr == null) { 734 log.error(tree.implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl)); 735 } else if ((constr.flags() & PUBLIC) == 0) { 736 log.error(tree.implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl)); 737 } 738 } 739 if (st.hasTag(CLASS) && it.hasTag(CLASS)) { 740 Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impl); 741 if (!allProvides.add(d)) { 742 log.error(tree.pos(), Errors.DuplicateProvides(service, impl)); 743 } 744 msym.provides = msym.provides.prepend(d); 745 msym.directives = msym.directives.prepend(d); 746 directiveToTreeMap.put(d, tree); 747 } 748 } 749 750 @Override 751 public void visitRequires(JCRequires tree) { 752 msym.directives = msym.directives.prepend(tree.directive); 753 } 754 755 @Override 756 public void visitUses(JCUses tree) { 757 Type st = attr.attribType(tree.qualid, env, syms.objectType); 758 Symbol sym = TreeInfo.symbol(tree.qualid); 759 if ((sym.flags() & ENUM) != 0) { 760 log.error(tree.qualid.pos(), Errors.ServiceDefinitionIsEnum(st.tsym)); 761 } else if (st.hasTag(CLASS)) { 762 ClassSymbol service = (ClassSymbol) st.tsym; 763 Directive.UsesDirective d = new Directive.UsesDirective(service); 764 if (!allUses.add(d)) { 765 log.error(tree.pos(), Errors.DuplicateUses(service)); 766 } 767 msym.uses = msym.uses.prepend(d); 768 msym.directives = msym.directives.prepend(d); 769 } 770 } 771 772 private void checkForCorrectness() { 773 for (Directive.ProvidesDirective provides : allProvides) { 774 JCProvides tree = directiveToTreeMap.get(provides); 775 /* The implementation must be defined in the same module as the provides directive 776 * (else, error) 777 */ 778 PackageSymbol implementationDefiningPackage = provides.impl.packge(); 779 if (implementationDefiningPackage.modle != msym) { 780 log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle)); 781 } 782 783 /* There is no inherent requirement that module that provides a service should actually 784 * use it itself. However, it is a pointless declaration if the service package is not 785 * exported and there is no uses for the service. 786 */ 787 PackageSymbol interfaceDeclaringPackage = provides.service.packge(); 788 boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym; 789 boolean isInterfaceExportedFromAReadableModule = 790 msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage; 791 if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) { 792 // ok the interface is declared in this module. Let's check if it's exported 793 boolean warn = true; 794 for (ExportsDirective export : msym.exports) { 795 if (interfaceDeclaringPackage == export.packge) { 796 warn = false; 797 break; 798 } 799 } 800 if (warn) { 801 for (UsesDirective uses : msym.uses) { 802 if (provides.service == uses.service) { 803 warn = false; 804 break; 805 } 806 } 807 } 808 if (warn) { 809 log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service)); 810 } 811 } 812 } 813 } 814 } 815 816 private Set<ModuleSymbol> allModulesCache; 817 818 private Set<ModuleSymbol> allModules() { 819 if (allModulesCache != null) 820 return allModulesCache; 821 822 Set<ModuleSymbol> observable; 823 824 if (limitModsOpt == null) { 825 observable = null; 826 } else { 827 Set<ModuleSymbol> limitMods = new HashSet<>(); 828 for (String limit : limitModsOpt.split(",")) { 829 limitMods.add(syms.enterModule(names.fromString(limit))); 830 } 831 observable = computeTransitiveClosure(limitMods, null); 832 observable.addAll(rootModules); 833 } 834 835 Predicate<ModuleSymbol> observablePred = sym -> observable == null || observable.contains(sym); 836 Predicate<ModuleSymbol> systemModulePred = sym -> (sym.flags() & Flags.SYSTEM_MODULE) != 0; 837 Set<ModuleSymbol> enabledRoot = new LinkedHashSet<>(); 838 839 if (rootModules.contains(syms.unnamedModule)) { 840 ModuleSymbol javaSE = syms.getModule(java_se); 841 Predicate<ModuleSymbol> jdkModulePred; 842 843 if (javaSE != null && (observable == null || observable.contains(javaSE))) { 844 jdkModulePred = sym -> { 845 sym.complete(); 846 return !sym.name.startsWith(java_) 847 && sym.exports.stream().anyMatch(e -> e.modules == null); 848 }; 849 enabledRoot.add(javaSE); 850 } else { 851 jdkModulePred = sym -> true; 852 } 853 854 for (ModuleSymbol sym : new HashSet<>(syms.getAllModules())) { 855 if (systemModulePred.test(sym) && observablePred.test(sym) && jdkModulePred.test(sym)) { 856 enabledRoot.add(sym); 857 } 858 } 859 } 860 861 enabledRoot.addAll(rootModules); 862 863 if (addModsOpt != null) { 864 for (String added : addModsOpt.split(",")) { 865 Stream<ModuleSymbol> modules; 866 switch (added) { 867 case ALL_SYSTEM: 868 modules = syms.getAllModules() 869 .stream() 870 .filter(systemModulePred.and(observablePred)); 871 break; 872 case ALL_MODULE_PATH: 873 modules = syms.getAllModules() 874 .stream() 875 .filter(systemModulePred.negate().and(observablePred)); 876 break; 877 default: 878 modules = Stream.of(syms.enterModule(names.fromString(added))); 879 break; 880 } 881 modules.forEach(sym -> { 882 enabledRoot.add(sym); 883 if (observable != null) 884 observable.add(sym); 885 }); 886 } 887 } 888 889 Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, observable); 890 891 result.add(syms.unnamedModule); 892 893 if (!rootModules.isEmpty()) 894 allModulesCache = result; 895 896 return result; 897 } 898 899 public void enableAllModules() { 900 allModulesCache = new HashSet<>(); 901 902 moduleFinder.findAllModules(); 903 904 for (ModuleSymbol msym : syms.getAllModules()) { 905 allModulesCache.add(msym); 906 } 907 } 908 909 private Set<ModuleSymbol> computeTransitiveClosure(Iterable<? extends ModuleSymbol> base, Set<ModuleSymbol> observable) { 910 List<ModuleSymbol> todo = List.nil(); 911 912 for (ModuleSymbol ms : base) { 913 todo = todo.prepend(ms); 914 } 915 916 Set<ModuleSymbol> result = new LinkedHashSet<>(); 917 result.add(syms.java_base); 918 919 while (todo.nonEmpty()) { 920 ModuleSymbol current = todo.head; 921 todo = todo.tail; 922 if (observable != null && !observable.contains(current)) 923 continue; 924 if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0)) 925 continue; 926 current.complete(); 927 for (RequiresDirective rd : current.requires) { 928 todo = todo.prepend(rd.module); 929 } 930 } 931 932 return result; 933 } 934 935 public ModuleSymbol getObservableModule(Name name) { 936 ModuleSymbol mod = syms.getModule(name); 937 938 if (allModules().contains(mod)) { 939 return mod; 940 } 941 942 return null; 943 } 944 945 private Completer getUnnamedModuleCompleter() { 946 moduleFinder.findAllModules(); 947 return new Symbol.Completer() { 948 @Override 949 public void complete(Symbol sym) throws CompletionFailure { 950 ModuleSymbol msym = (ModuleSymbol) sym; 951 Set<ModuleSymbol> allModules = allModules(); 952 for (ModuleSymbol m : allModules) { 953 m.complete(); 954 } 955 initVisiblePackages(msym, allModules); 956 } 957 958 @Override 959 public String toString() { 960 return "unnamedModule Completer"; 961 } 962 }; 963 } 964 965 private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresPublicCache = new HashMap<>(); 966 967 private void completeModule(ModuleSymbol msym) { 968 Assert.checkNonNull(msym.requires); 969 970 initAddReads(); 971 972 msym.requires = msym.requires.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet()))); 973 974 List<RequiresDirective> requires = msym.requires; 975 List<RequiresDirective> previous = null; 976 977 while (requires.nonEmpty()) { 978 if (!allModules().contains(requires.head.module)) { 979 Env<AttrContext> env = typeEnvs.get(msym); 980 if (env != null) { 981 JavaFileObject origSource = log.useSource(env.toplevel.sourcefile); 982 try { 983 log.error(/*XXX*/env.tree, Errors.ModuleNotFound(requires.head.module)); 984 } finally { 985 log.useSource(origSource); 986 } 987 } else { 988 Assert.check((msym.flags() & Flags.AUTOMATIC_MODULE) == 0); 989 } 990 if (previous != null) { 991 previous.tail = requires.tail; 992 } else { 993 msym.requires.tail = requires.tail; 994 } 995 } else { 996 previous = requires; 997 } 998 requires = requires.tail; 999 } 1000 1001 Set<ModuleSymbol> readable = new LinkedHashSet<>(); 1002 Set<ModuleSymbol> requiresPublic = new HashSet<>(); 1003 if ((msym.flags() & Flags.AUTOMATIC_MODULE) == 0) { 1004 for (RequiresDirective d : msym.requires) { 1005 d.module.complete(); 1006 readable.add(d.module); 1007 Set<ModuleSymbol> s = retrieveRequiresPublic(d.module); 1008 Assert.checkNonNull(s, () -> "no entry in cache for " + d.module); 1009 readable.addAll(s); 1010 if (d.flags.contains(RequiresFlag.PUBLIC)) { 1011 requiresPublic.add(d.module); 1012 requiresPublic.addAll(s); 1013 } 1014 } 1015 } else { 1016 //the module graph may contain cycles involving automatic modules 1017 //handle automatic modules separatelly: 1018 Set<ModuleSymbol> s = retrieveRequiresPublic(msym); 1019 1020 readable.addAll(s); 1021 requiresPublic.addAll(s); 1022 1023 //ensure the unnamed module is added (it is not requires public): 1024 readable.add(syms.unnamedModule); 1025 } 1026 requiresPublicCache.put(msym, requiresPublic); 1027 initVisiblePackages(msym, readable); 1028 for (ExportsDirective d: msym.exports) { 1029 d.packge.modle = msym; 1030 } 1031 1032 } 1033 1034 private Set<ModuleSymbol> retrieveRequiresPublic(ModuleSymbol msym) { 1035 Set<ModuleSymbol> requiresPublic = requiresPublicCache.get(msym); 1036 1037 if (requiresPublic == null) { 1038 //the module graph may contain cycles involving automatic modules or -XaddReads edges 1039 requiresPublic = new HashSet<>(); 1040 1041 Set<ModuleSymbol> seen = new HashSet<>(); 1042 List<ModuleSymbol> todo = List.of(msym); 1043 1044 while (todo.nonEmpty()) { 1045 ModuleSymbol current = todo.head; 1046 todo = todo.tail; 1047 if (!seen.add(current)) 1048 continue; 1049 requiresPublic.add(current); 1050 current.complete(); 1051 Iterable<? extends RequiresDirective> requires; 1052 if (current != syms.unnamedModule) { 1053 Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym); 1054 requires = current.requires; 1055 for (RequiresDirective rd : requires) { 1056 if (rd.isPublic()) 1057 todo = todo.prepend(rd.module); 1058 } 1059 } else { 1060 for (ModuleSymbol mod : allModules()) { 1061 todo = todo.prepend(mod); 1062 } 1063 } 1064 } 1065 1066 requiresPublic.remove(msym); 1067 } 1068 1069 return requiresPublic; 1070 } 1071 1072 private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) { 1073 initAddExports(); 1074 1075 msym.visiblePackages = new LinkedHashMap<>(); 1076 1077 Map<Name, ModuleSymbol> seen = new HashMap<>(); 1078 1079 for (ModuleSymbol rm : readable) { 1080 if (rm == syms.unnamedModule) 1081 continue; 1082 addVisiblePackages(msym, seen, rm, rm.exports); 1083 } 1084 1085 for (Entry<ModuleSymbol, Set<ExportsDirective>> addExportsEntry : addExports.entrySet()) 1086 addVisiblePackages(msym, seen, addExportsEntry.getKey(), addExportsEntry.getValue()); 1087 } 1088 1089 private void addVisiblePackages(ModuleSymbol msym, 1090 Map<Name, ModuleSymbol> seenPackages, 1091 ModuleSymbol exportsFrom, 1092 Collection<ExportsDirective> exports) { 1093 for (ExportsDirective d : exports) { 1094 if (d.modules == null || d.modules.contains(msym)) { 1095 Name packageName = d.packge.fullname; 1096 ModuleSymbol previousModule = seenPackages.get(packageName); 1097 1098 if (previousModule != null && previousModule != exportsFrom) { 1099 Env<AttrContext> env = typeEnvs.get(msym); 1100 JavaFileObject origSource = env != null ? log.useSource(env.toplevel.sourcefile) 1101 : null; 1102 DiagnosticPosition pos = env != null ? env.tree.pos() : null; 1103 try { 1104 log.error(pos, Errors.PackageClashFromRequires(msym, packageName, 1105 previousModule, exportsFrom)); 1106 } finally { 1107 if (env != null) 1108 log.useSource(origSource); 1109 } 1110 continue; 1111 } 1112 1113 seenPackages.put(packageName, exportsFrom); 1114 msym.visiblePackages.put(d.packge.fullname, d.packge); 1115 } 1116 } 1117 } 1118 1119 private void initAddExports() { 1120 if (addExports != null) 1121 return; 1122 1123 addExports = new LinkedHashMap<>(); 1124 1125 if (addExportsOpt == null) 1126 return; 1127 1128// System.err.println("Modules.addExports:\n " + addExportsOpt.replace("\0", "\n ")); 1129 1130 Pattern ep = Pattern.compile("([^/]+)/([^=]+)=(.*)"); 1131 for (String s: addExportsOpt.split("\0+")) { 1132 if (s.isEmpty()) 1133 continue; 1134 Matcher em = ep.matcher(s); 1135 if (!em.matches()) { 1136 continue; 1137 } 1138 1139 // Terminology comes from 1140 // -XaddExports:module/package=target,... 1141 // Compare to 1142 // module module { exports package to target, ... } 1143 String moduleName = em.group(1); 1144 String packageName = em.group(2); 1145 String targetNames = em.group(3); 1146 1147 ModuleSymbol msym = syms.enterModule(names.fromString(moduleName)); 1148 PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName)); 1149 p.modle = msym; // TODO: do we need this? 1150 1151 List<ModuleSymbol> targetModules = List.nil(); 1152 for (String toModule : targetNames.split("[ ,]+")) { 1153 ModuleSymbol m; 1154 if (toModule.equals("ALL-UNNAMED")) { 1155 m = syms.unnamedModule; 1156 } else { 1157 if (!SourceVersion.isName(toModule)) { 1158 // TODO: error: invalid module name 1159 continue; 1160 } 1161 m = syms.enterModule(names.fromString(toModule)); 1162 } 1163 targetModules = targetModules.prepend(m); 1164 } 1165 1166 Set<ExportsDirective> extra = addExports.computeIfAbsent(msym, _x -> new LinkedHashSet<>()); 1167 ExportsDirective d = new ExportsDirective(p, targetModules); 1168 extra.add(d); 1169 } 1170 } 1171 1172 private void initAddReads() { 1173 if (addReads != null) 1174 return; 1175 1176 addReads = new LinkedHashMap<>(); 1177 1178 if (addReadsOpt == null) 1179 return; 1180 1181// System.err.println("Modules.addReads:\n " + addReadsOpt.replace("\0", "\n ")); 1182 1183 Pattern rp = Pattern.compile("([^=]+)=(.*)"); 1184 for (String s : addReadsOpt.split("\0+")) { 1185 if (s.isEmpty()) 1186 continue; 1187 Matcher rm = rp.matcher(s); 1188 if (!rm.matches()) { 1189 continue; 1190 } 1191 1192 // Terminology comes from 1193 // -XaddReads:target-module=source-module,... 1194 // Compare to 1195 // module target-module { requires source-module; ... } 1196 String targetName = rm.group(1); 1197 String sources = rm.group(2); 1198 1199 ModuleSymbol msym = syms.enterModule(names.fromString(targetName)); 1200 for (String source : sources.split("[ ,]+")) { 1201 ModuleSymbol sourceModule; 1202 if (source.equals("ALL-UNNAMED")) { 1203 sourceModule = syms.unnamedModule; 1204 } else { 1205 if (!SourceVersion.isName(source)) { 1206 // TODO: error: invalid module name 1207 continue; 1208 } 1209 sourceModule = syms.enterModule(names.fromString(source)); 1210 } 1211 addReads.computeIfAbsent(msym, m -> new HashSet<>()) 1212 .add(new RequiresDirective(sourceModule, EnumSet.of(RequiresFlag.EXTRA))); 1213 } 1214 } 1215 } 1216 1217 private void checkCyclicDependencies(JCModuleDecl mod) { 1218 for (JCDirective d : mod.directives) { 1219 if (!d.hasTag(Tag.REQUIRES)) 1220 continue; 1221 JCRequires rd = (JCRequires) d; 1222 Set<ModuleSymbol> nonSyntheticDeps = new HashSet<>(); 1223 List<ModuleSymbol> queue = List.of(rd.directive.module); 1224 while (queue.nonEmpty()) { 1225 ModuleSymbol current = queue.head; 1226 queue = queue.tail; 1227 if (!nonSyntheticDeps.add(current)) 1228 continue; 1229 if ((current.flags() & Flags.ACYCLIC) != 0) 1230 continue; 1231 current.complete(); 1232 Assert.checkNonNull(current.requires, () -> current.toString()); 1233 for (RequiresDirective dep : current.requires) { 1234 if (!dep.flags.contains(RequiresFlag.EXTRA)) 1235 queue = queue.prepend(dep.module); 1236 } 1237 } 1238 if (nonSyntheticDeps.contains(mod.sym)) { 1239 log.error(rd.moduleName.pos(), Errors.CyclicRequires(rd.directive.module)); 1240 } 1241 mod.sym.flags_field |= Flags.ACYCLIC; 1242 } 1243 } 1244 1245 // DEBUG 1246 private String toString(ModuleSymbol msym) { 1247 return msym.name + "[" 1248 + "kind:" + msym.kind + ";" 1249 + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";" 1250 + "info:" + toString(msym.module_info.sourcefile) + "," 1251 + toString(msym.module_info.classfile) + "," 1252 + msym.module_info.completer 1253 + "]"; 1254 } 1255 1256 // DEBUG 1257 String toString(Location locn) { 1258 return (locn == null) ? "--" : locn.getName(); 1259 } 1260 1261 // DEBUG 1262 String toString(JavaFileObject fo) { 1263 return (fo == null) ? "--" : fo.getName(); 1264 } 1265 1266 public void newRound() { 1267 } 1268} 1269