Modules.java revision 4202:2bd34895dda2
1205859Sjoel/* 2159687Snetchild * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. 3159687Snetchild * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4159687Snetchild * 5159687Snetchild * This code is free software; you can redistribute it and/or modify it 6159687Snetchild * under the terms of the GNU General Public License version 2 only, as 7159687Snetchild * published by the Free Software Foundation. Oracle designates this 8159687Snetchild * particular file as subject to the "Classpath" exception as provided 9159687Snetchild * by Oracle in the LICENSE file that accompanied this code. 10159687Snetchild * 11159687Snetchild * This code is distributed in the hope that it will be useful, but WITHOUT 12159687Snetchild * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13159687Snetchild * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14159687Snetchild * version 2 for more details (a copy is included in the LICENSE file that 15159687Snetchild * accompanied this code). 16159687Snetchild * 17159687Snetchild * You should have received a copy of the GNU General Public License version 18159687Snetchild * 2 along with this work; if not, write to the Free Software Foundation, 19159687Snetchild * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20159687Snetchild * 21159687Snetchild * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22159687Snetchild * or visit www.oracle.com if you need additional information or have any 23159687Snetchild * questions. 24159687Snetchild */ 25159687Snetchild 26159687Snetchild 27159687Snetchildpackage com.sun.tools.javac.comp; 28159687Snetchild 29159687Snetchildimport java.io.IOException; 30159687Snetchildimport java.util.Arrays; 31159687Snetchildimport java.util.Collection; 32159687Snetchildimport java.util.Collections; 33159687Snetchildimport java.util.EnumSet; 34159687Snetchildimport java.util.HashMap; 35159687Snetchildimport java.util.HashSet; 36159687Snetchildimport java.util.LinkedHashMap; 37159687Snetchildimport java.util.LinkedHashSet; 38159687Snetchildimport java.util.Map; 39159687Snetchildimport java.util.Set; 40159687Snetchildimport java.util.function.Consumer; 41159687Snetchildimport java.util.function.Predicate; 42159687Snetchildimport java.util.regex.Matcher; 43159687Snetchildimport java.util.regex.Pattern; 44159687Snetchildimport java.util.stream.Collectors; 45159687Snetchildimport java.util.stream.Stream; 46159687Snetchild 47159687Snetchildimport javax.lang.model.SourceVersion; 48159687Snetchildimport javax.tools.JavaFileManager; 49159687Snetchildimport javax.tools.JavaFileManager.Location; 50159687Snetchildimport javax.tools.JavaFileObject; 51159687Snetchildimport javax.tools.JavaFileObject.Kind; 52159687Snetchildimport javax.tools.StandardLocation; 53159687Snetchild 54159687Snetchildimport com.sun.source.tree.ModuleTree.ModuleKind; 55159687Snetchildimport com.sun.tools.javac.code.ClassFinder; 56159687Snetchildimport com.sun.tools.javac.code.DeferredLintHandler; 57159687Snetchildimport com.sun.tools.javac.code.Directive; 58159687Snetchildimport com.sun.tools.javac.code.Directive.ExportsDirective; 59159687Snetchildimport com.sun.tools.javac.code.Directive.ExportsFlag; 60159687Snetchildimport com.sun.tools.javac.code.Directive.OpensDirective; 61159687Snetchildimport com.sun.tools.javac.code.Directive.OpensFlag; 62159687Snetchildimport com.sun.tools.javac.code.Directive.RequiresDirective; 63159687Snetchildimport com.sun.tools.javac.code.Directive.RequiresFlag; 64159687Snetchildimport com.sun.tools.javac.code.Directive.UsesDirective; 65159687Snetchildimport com.sun.tools.javac.code.Flags; 66159687Snetchildimport com.sun.tools.javac.code.Lint.LintCategory; 67159687Snetchildimport com.sun.tools.javac.code.ModuleFinder; 68159687Snetchildimport com.sun.tools.javac.code.Source; 69159687Snetchildimport com.sun.tools.javac.code.Symbol; 70159687Snetchildimport com.sun.tools.javac.code.Symbol.ClassSymbol; 71159687Snetchildimport com.sun.tools.javac.code.Symbol.Completer; 72159687Snetchildimport com.sun.tools.javac.code.Symbol.CompletionFailure; 73159687Snetchildimport com.sun.tools.javac.code.Symbol.MethodSymbol; 74159687Snetchildimport com.sun.tools.javac.code.Symbol.ModuleFlags; 75159687Snetchildimport com.sun.tools.javac.code.Symbol.ModuleSymbol; 76159687Snetchildimport com.sun.tools.javac.code.Symbol.PackageSymbol; 77159687Snetchildimport com.sun.tools.javac.code.Symtab; 78159687Snetchildimport com.sun.tools.javac.code.Type; 79159687Snetchildimport com.sun.tools.javac.code.Types; 80159687Snetchildimport com.sun.tools.javac.jvm.ClassWriter; 81159687Snetchildimport com.sun.tools.javac.jvm.JNIWriter; 82159687Snetchildimport com.sun.tools.javac.main.Option; 83159687Snetchildimport com.sun.tools.javac.resources.CompilerProperties.Errors; 84159687Snetchildimport com.sun.tools.javac.resources.CompilerProperties.Warnings; 85159687Snetchildimport com.sun.tools.javac.tree.JCTree; 86159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 87159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCDirective; 88159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCExports; 89159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCExpression; 90159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCModuleDecl; 91159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCOpens; 92159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCProvides; 93159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCRequires; 94159687Snetchildimport com.sun.tools.javac.tree.JCTree.JCUses; 95159687Snetchildimport com.sun.tools.javac.tree.JCTree.Tag; 96159687Snetchildimport com.sun.tools.javac.tree.TreeInfo; 97159687Snetchildimport com.sun.tools.javac.util.Abort; 98159687Snetchildimport com.sun.tools.javac.util.Assert; 99159687Snetchildimport com.sun.tools.javac.util.Context; 100159687Snetchildimport com.sun.tools.javac.util.JCDiagnostic; 101159687Snetchildimport com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; 102159687Snetchildimport com.sun.tools.javac.util.List; 103159687Snetchildimport com.sun.tools.javac.util.ListBuffer; 104159687Snetchildimport com.sun.tools.javac.util.Log; 105159687Snetchildimport com.sun.tools.javac.util.Name; 106159687Snetchildimport com.sun.tools.javac.util.Names; 107159687Snetchildimport com.sun.tools.javac.util.Options; 108159687Snetchildimport com.sun.tools.javac.util.Position; 109159687Snetchild 110159687Snetchildimport static com.sun.tools.javac.code.Flags.ABSTRACT; 111159687Snetchildimport static com.sun.tools.javac.code.Flags.ENUM; 112159687Snetchildimport static com.sun.tools.javac.code.Flags.PUBLIC; 113159687Snetchildimport static com.sun.tools.javac.code.Flags.UNATTRIBUTED; 114159687Snetchildimport com.sun.tools.javac.code.Kinds; 115159687Snetchildimport static com.sun.tools.javac.code.Kinds.Kind.ERR; 116159687Snetchildimport static com.sun.tools.javac.code.Kinds.Kind.MDL; 117159687Snetchildimport static com.sun.tools.javac.code.Kinds.Kind.MTH; 118159687Snetchildimport com.sun.tools.javac.code.Symbol.ModuleResolutionFlags; 119159687Snetchildimport static com.sun.tools.javac.code.TypeTag.CLASS; 120159687Snetchild 121159687Snetchild/** 122159687Snetchild * TODO: fill in 123159687Snetchild * 124159687Snetchild * <p><b>This is NOT part of any supported API. 125159687Snetchild * If you write code that depends on this, you do so at your own risk. 126159687Snetchild * This code and its internal interfaces are subject to change or 127159687Snetchild * deletion without notice.</b> 128159687Snetchild */ 129159687Snetchildpublic class Modules extends JCTree.Visitor { 130159687Snetchild private static final String ALL_SYSTEM = "ALL-SYSTEM"; 131159687Snetchild private static final String ALL_MODULE_PATH = "ALL-MODULE-PATH"; 132159687Snetchild 133159687Snetchild private final Log log; 134159687Snetchild private final Names names; 135159687Snetchild private final Symtab syms; 136159687Snetchild private final Attr attr; 137159687Snetchild private final Check chk; 138159687Snetchild private final DeferredLintHandler deferredLintHandler; 139159687Snetchild private final TypeEnvs typeEnvs; 140159687Snetchild private final Types types; 141159687Snetchild private final JavaFileManager fileManager; 142159687Snetchild private final ModuleFinder moduleFinder; 143159687Snetchild private final Source source; 144159687Snetchild private final boolean allowModules; 145159687Snetchild private final boolean allowAccessIntoSystem; 146159687Snetchild 147159687Snetchild public final boolean multiModuleMode; 148159687Snetchild 149159687Snetchild private final String legacyModuleOverride; 150159687Snetchild 151159687Snetchild private final Name java_se; 152159687Snetchild private final Name java_; 153159687Snetchild 154159687Snetchild ModuleSymbol defaultModule; 155159687Snetchild 156159687Snetchild private final String addExportsOpt; 157159687Snetchild private Map<ModuleSymbol, Set<ExportsDirective>> addExports; 158159687Snetchild private final String addReadsOpt; 159159687Snetchild private Map<ModuleSymbol, Set<RequiresDirective>> addReads; 160159687Snetchild private final String addModsOpt; 161159687Snetchild private final Set<String> extraAddMods = new HashSet<>(); 162159687Snetchild private final String limitModsOpt; 163159687Snetchild private final Set<String> extraLimitMods = new HashSet<>(); 164159687Snetchild private final String moduleVersionOpt; 165159687Snetchild 166159687Snetchild private final boolean lintOptions; 167159687Snetchild 168159687Snetchild private Set<ModuleSymbol> rootModules = null; 169159687Snetchild private final Set<ModuleSymbol> warnedMissing = new HashSet<>(); 170159687Snetchild 171159687Snetchild public PackageNameFinder findPackageInFile; 172159687Snetchild 173159687Snetchild public static Modules instance(Context context) { 174159687Snetchild Modules instance = context.get(Modules.class); 175159687Snetchild if (instance == null) 176159687Snetchild instance = new Modules(context); 177159687Snetchild return instance; 178159687Snetchild } 179159687Snetchild 180159687Snetchild protected Modules(Context context) { 181159687Snetchild context.put(Modules.class, this); 182159687Snetchild log = Log.instance(context); 183159687Snetchild names = Names.instance(context); 184159687Snetchild syms = Symtab.instance(context); 185159687Snetchild attr = Attr.instance(context); 186159687Snetchild chk = Check.instance(context); 187159687Snetchild deferredLintHandler = DeferredLintHandler.instance(context); 188159687Snetchild typeEnvs = TypeEnvs.instance(context); 189159687Snetchild moduleFinder = ModuleFinder.instance(context); 190159687Snetchild types = Types.instance(context); 191159687Snetchild fileManager = context.get(JavaFileManager.class); 192159687Snetchild source = Source.instance(context); 193159687Snetchild allowModules = source.allowModules(); 194159687Snetchild Options options = Options.instance(context); 195159687Snetchild 196159687Snetchild allowAccessIntoSystem = options.isUnset(Option.RELEASE); 197159687Snetchild lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option); 198159687Snetchild 199159687Snetchild Collection<String> xmodules = options.keySet() 200159687Snetchild .stream() 201159687Snetchild .filter(opt -> opt.startsWith(XMODULES_PREFIX)) 202159687Snetchild .map(opt -> opt.substring(XMODULES_PREFIX.length())) 203159687Snetchild .collect(Collectors.toList()); 204159687Snetchild 205159687Snetchild legacyModuleOverride = xmodules.size() == 1 ? xmodules.iterator().next() : null; 206159687Snetchild 207159687Snetchild multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH); 208159687Snetchild ClassWriter classWriter = ClassWriter.instance(context); 209159687Snetchild classWriter.multiModuleMode = multiModuleMode; 210159687Snetchild JNIWriter jniWriter = JNIWriter.instance(context); 211159687Snetchild jniWriter.multiModuleMode = multiModuleMode; 212159687Snetchild 213159687Snetchild java_se = names.fromString("java.se"); 214159687Snetchild java_ = names.fromString("java."); 215159687Snetchild 216159687Snetchild addExportsOpt = options.get(Option.ADD_EXPORTS); 217159687Snetchild addReadsOpt = options.get(Option.ADD_READS); 218159687Snetchild addModsOpt = options.get(Option.ADD_MODULES); 219159687Snetchild limitModsOpt = options.get(Option.LIMIT_MODULES); 220159687Snetchild moduleVersionOpt = options.get(Option.MODULE_VERSION); 221159687Snetchild } 222159687Snetchild //where 223159687Snetchild private static final String XMODULES_PREFIX = "-Xmodule:"; 224159687Snetchild 225159687Snetchild int depth = -1; 226159687Snetchild 227159687Snetchild public void addExtraAddModules(String... extras) { 228159687Snetchild extraAddMods.addAll(Arrays.asList(extras)); 229159687Snetchild } 230159687Snetchild 231159687Snetchild boolean inInitModules; 232159687Snetchild public void initModules(List<JCCompilationUnit> trees) { 233159687Snetchild Assert.check(!inInitModules); 234159687Snetchild try { 235159687Snetchild inInitModules = true; 236159687Snetchild Assert.checkNull(rootModules); 237159687Snetchild enter(trees, modules -> { 238159687Snetchild Assert.checkNull(rootModules); 239159687Snetchild Assert.checkNull(allModules); 240159687Snetchild this.rootModules = modules; 241159687Snetchild setupAllModules(); //initialize the module graph 242159687Snetchild Assert.checkNonNull(allModules); 243159687Snetchild inInitModules = false; 244159687Snetchild }, null); 245159687Snetchild } finally { 246159687Snetchild inInitModules = false; 247159687Snetchild } 248159687Snetchild } 249159687Snetchild 250159687Snetchild public boolean enter(List<JCCompilationUnit> trees, ClassSymbol c) { 251159687Snetchild Assert.check(rootModules != null || inInitModules || !allowModules); 252159687Snetchild return enter(trees, modules -> {}, c); 253159687Snetchild } 254159687Snetchild 255159687Snetchild private boolean enter(List<JCCompilationUnit> trees, Consumer<Set<ModuleSymbol>> init, ClassSymbol c) { 256159687Snetchild if (!allowModules) { 257159687Snetchild for (JCCompilationUnit tree: trees) { 258159687Snetchild tree.modle = syms.noModule; 259159687Snetchild } 260159687Snetchild defaultModule = syms.noModule; 261159687Snetchild return true; 262159687Snetchild } 263159687Snetchild 264159687Snetchild int startErrors = log.nerrors; 265159687Snetchild 266159687Snetchild depth++; 267159687Snetchild try { 268159687Snetchild // scan trees for module defs 269159687Snetchild Set<ModuleSymbol> roots = enterModules(trees, c); 270159687Snetchild 271159687Snetchild setCompilationUnitModules(trees, roots, c); 272159687Snetchild 273159687Snetchild init.accept(roots); 274159687Snetchild 275159687Snetchild for (ModuleSymbol msym: roots) { 276159687Snetchild msym.complete(); 277159687Snetchild } 278159687Snetchild } catch (CompletionFailure ex) { 279159687Snetchild log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, Position.NOPOS, Errors.CantAccess(ex.sym, ex.getDetailValue())); 280159687Snetchild if (ex instanceof ClassFinder.BadClassFile) throw new Abort(); 281159687Snetchild } finally { 282159687Snetchild depth--; 283159687Snetchild } 284159687Snetchild 285159687Snetchild return (log.nerrors == startErrors); 286159687Snetchild } 287159687Snetchild 288159687Snetchild public Completer getCompleter() { 289159687Snetchild return mainCompleter; 290159687Snetchild } 291159687Snetchild 292159687Snetchild public ModuleSymbol getDefaultModule() { 293159687Snetchild return defaultModule; 294159687Snetchild } 295159687Snetchild 296159687Snetchild public boolean modulesInitialized() { 297159687Snetchild return allModules != null; 298159687Snetchild } 299159687Snetchild 300159687Snetchild private Set<ModuleSymbol> enterModules(List<JCCompilationUnit> trees, ClassSymbol c) { 301159687Snetchild Set<ModuleSymbol> modules = new LinkedHashSet<>(); 302159687Snetchild for (JCCompilationUnit tree : trees) { 303159687Snetchild JavaFileObject prev = log.useSource(tree.sourcefile); 304159687Snetchild try { 305159687Snetchild enterModule(tree, c, modules); 306159687Snetchild } finally { 307159687Snetchild log.useSource(prev); 308159687Snetchild } 309159687Snetchild } 310159687Snetchild return modules; 311159687Snetchild } 312159687Snetchild 313159687Snetchild 314159687Snetchild private void enterModule(JCCompilationUnit toplevel, ClassSymbol c, Set<ModuleSymbol> modules) { 315159687Snetchild boolean isModuleInfo = toplevel.sourcefile.isNameCompatible("module-info", Kind.SOURCE); 316159687Snetchild boolean isModuleDecl = toplevel.getModuleDecl() != null; 317159687Snetchild if (isModuleDecl) { 318159687Snetchild JCModuleDecl decl = toplevel.getModuleDecl(); 319159687Snetchild if (!isModuleInfo) { 320159687Snetchild log.error(decl.pos(), Errors.ModuleDeclSbInModuleInfoJava); 321159687Snetchild } 322159687Snetchild Name name = TreeInfo.fullName(decl.qualId); 323159687Snetchild ModuleSymbol sym; 324159687Snetchild if (c != null) { 325159687Snetchild sym = (ModuleSymbol) c.owner; 326159687Snetchild Assert.checkNonNull(sym.name); 327159687Snetchild Name treeName = TreeInfo.fullName(decl.qualId); 328159687Snetchild if (sym.name != treeName) { 329159687Snetchild log.error(decl.pos(), Errors.ModuleNameMismatch(name, sym.name)); 330159687Snetchild } 331159687Snetchild } else { 332159687Snetchild sym = syms.enterModule(name); 333159687Snetchild if (sym.module_info.sourcefile != null && sym.module_info.sourcefile != toplevel.sourcefile) { 334159687Snetchild log.error(decl.pos(), Errors.DuplicateModule(sym)); 335159687Snetchild return; 336159687Snetchild } 337159687Snetchild } 338159687Snetchild sym.completer = getSourceCompleter(toplevel); 339159687Snetchild sym.module_info.sourcefile = toplevel.sourcefile; 340159687Snetchild decl.sym = sym; 341159687Snetchild 342159687Snetchild if (multiModuleMode || modules.isEmpty()) { 343159687Snetchild modules.add(sym); 344159687Snetchild } else { 345159687Snetchild log.error(toplevel.pos(), Errors.TooManyModules); 346159687Snetchild } 347159687Snetchild 348159687Snetchild Env<AttrContext> provisionalEnv = new Env<>(decl, null); 349159687Snetchild 350159687Snetchild provisionalEnv.toplevel = toplevel; 351159687Snetchild typeEnvs.put(sym, provisionalEnv); 352159687Snetchild } else if (isModuleInfo) { 353159687Snetchild if (multiModuleMode) { 354159687Snetchild JCTree tree = toplevel.defs.isEmpty() ? toplevel : toplevel.defs.head; 355159687Snetchild log.error(tree.pos(), Errors.ExpectedModule); 356159687Snetchild } 357159687Snetchild } 358159687Snetchild } 359159687Snetchild 360159687Snetchild private void setCompilationUnitModules(List<JCCompilationUnit> trees, Set<ModuleSymbol> rootModules, ClassSymbol c) { 361159687Snetchild // update the module for each compilation unit 362159687Snetchild if (multiModuleMode) { 363159687Snetchild checkNoAllModulePath(); 364159687Snetchild for (JCCompilationUnit tree: trees) { 365159687Snetchild if (tree.defs.isEmpty()) { 366159687Snetchild tree.modle = syms.unnamedModule; 367159687Snetchild continue; 368159687Snetchild } 369159687Snetchild 370159687Snetchild JavaFileObject prev = log.useSource(tree.sourcefile); 371159687Snetchild try { 372159687Snetchild Location msplocn = getModuleLocation(tree); 373159687Snetchild Location plocn = fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH) ? 374159687Snetchild fileManager.getLocationForModule(StandardLocation.PATCH_MODULE_PATH, 375159687Snetchild tree.sourcefile) : 376159687Snetchild null; 377159687Snetchild 378159687Snetchild if (plocn != null) { 379159687Snetchild Name name = names.fromString(fileManager.inferModuleName(plocn)); 380159687Snetchild ModuleSymbol msym = moduleFinder.findModule(name); 381159687Snetchild tree.modle = msym; 382159687Snetchild rootModules.add(msym); 383159687Snetchild 384159687Snetchild if (msplocn != null) { 385159687Snetchild Name mspname = names.fromString(fileManager.inferModuleName(msplocn)); 386159687Snetchild if (name != mspname) { 387159687Snetchild log.error(tree.pos(), Errors.FilePatchedAndMsp(name, mspname)); 388159687Snetchild } 389159687Snetchild } 390159687Snetchild } else if (msplocn != null) { 391159687Snetchild if (tree.getModuleDecl() != null) { 392159687Snetchild JavaFileObject canonical = 393159687Snetchild fileManager.getJavaFileForInput(msplocn, "module-info", Kind.SOURCE); 394159687Snetchild if (canonical == null || !fileManager.isSameFile(canonical, tree.sourcefile)) { 395159687Snetchild log.error(tree.pos(), Errors.ModuleNotFoundOnModuleSourcePath); 396159687Snetchild } 397159687Snetchild } 398159687Snetchild Name name = names.fromString(fileManager.inferModuleName(msplocn)); 399159687Snetchild ModuleSymbol msym; 400159687Snetchild JCModuleDecl decl = tree.getModuleDecl(); 401159687Snetchild if (decl != null) { 402159687Snetchild msym = decl.sym; 403159687Snetchild if (msym.name != name) { 404159687Snetchild log.error(decl.qualId, Errors.ModuleNameMismatch(msym.name, name)); 405159687Snetchild } 406159687Snetchild } else { 407159687Snetchild if (tree.getPackage() == null) { 408159687Snetchild log.error(tree.pos(), Errors.UnnamedPkgNotAllowedNamedModules); 409159687Snetchild } 410159687Snetchild msym = syms.enterModule(name); 411159687Snetchild } 412159687Snetchild if (msym.sourceLocation == null) { 413159687Snetchild msym.sourceLocation = msplocn; 414159687Snetchild if (fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) { 415159687Snetchild msym.patchLocation = fileManager.getLocationForModule( 416159687Snetchild StandardLocation.PATCH_MODULE_PATH, msym.name.toString()); 417159687Snetchild } 418159687Snetchild if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) { 419159687Snetchild Location outputLocn = fileManager.getLocationForModule( 420159687Snetchild StandardLocation.CLASS_OUTPUT, msym.name.toString()); 421159687Snetchild if (msym.patchLocation == null) { 422159687Snetchild msym.classLocation = outputLocn; 423159687Snetchild } else { 424159687Snetchild msym.patchOutputLocation = outputLocn; 425159687Snetchild } 426159687Snetchild } 427159687Snetchild } 428159687Snetchild tree.modle = msym; 429159687Snetchild rootModules.add(msym); 430159687Snetchild } else if (c != null && c.packge().modle == syms.unnamedModule) { 431159687Snetchild tree.modle = syms.unnamedModule; 432159687Snetchild } else { 433159687Snetchild if (tree.getModuleDecl() != null) { 434159687Snetchild log.error(tree.pos(), Errors.ModuleNotFoundOnModuleSourcePath); 435159687Snetchild } else { 436159687Snetchild log.error(tree.pos(), Errors.NotInModuleOnModuleSourcePath); 437159687Snetchild } 438159687Snetchild tree.modle = syms.errModule; 439159687Snetchild } 440159687Snetchild } catch (IOException e) { 441159687Snetchild throw new Error(e); // FIXME 442159687Snetchild } finally { 443159687Snetchild log.useSource(prev); 444159687Snetchild } 445159687Snetchild } 446159687Snetchild if (syms.unnamedModule.sourceLocation == null) { 447159687Snetchild syms.unnamedModule.completer = getUnnamedModuleCompleter(); 448159687Snetchild syms.unnamedModule.sourceLocation = StandardLocation.SOURCE_PATH; 449159687Snetchild syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH; 450159687Snetchild } 451159687Snetchild defaultModule = syms.unnamedModule; 452159687Snetchild } else { 453159687Snetchild ModuleSymbol module = null; 454159687Snetchild if (defaultModule == null) { 455159687Snetchild String moduleOverride = singleModuleOverride(trees); 456159687Snetchild switch (rootModules.size()) { 457159687Snetchild case 0: 458159687Snetchild defaultModule = moduleFinder.findSingleModule(); 459159687Snetchild if (defaultModule == syms.unnamedModule) { 460159687Snetchild if (moduleOverride != null) { 461159687Snetchild checkNoAllModulePath(); 462159687Snetchild defaultModule = moduleFinder.findModule(names.fromString(moduleOverride)); 463159687Snetchild if (legacyModuleOverride != null) { 464159687Snetchild defaultModule.sourceLocation = StandardLocation.SOURCE_PATH; 465159687Snetchild } 466159687Snetchild defaultModule.patchOutputLocation = StandardLocation.CLASS_OUTPUT; 467159687Snetchild } else { 468159687Snetchild // Question: why not do findAllModules and initVisiblePackages here? 469159687Snetchild // i.e. body of unnamedModuleCompleter 470159687Snetchild defaultModule.completer = getUnnamedModuleCompleter(); 471159687Snetchild defaultModule.sourceLocation = StandardLocation.SOURCE_PATH; 472159687Snetchild defaultModule.classLocation = StandardLocation.CLASS_PATH; 473159687Snetchild } 474159687Snetchild } else { 475159687Snetchild checkNoAllModulePath(); 476159687Snetchild defaultModule.complete(); 477159687Snetchild // Question: why not do completeModule here? 478159687Snetchild defaultModule.completer = sym -> completeModule((ModuleSymbol) sym); 479159687Snetchild defaultModule.sourceLocation = StandardLocation.SOURCE_PATH; 480159687Snetchild } 481159687Snetchild rootModules.add(defaultModule); 482170031Sjoel break; 483170031Sjoel case 1: 484170031Sjoel checkNoAllModulePath(); 485170031Sjoel defaultModule = rootModules.iterator().next(); 486170031Sjoel defaultModule.sourceLocation = StandardLocation.SOURCE_PATH; 487170031Sjoel if (fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) { 488170031Sjoel try { 489170031Sjoel defaultModule.patchLocation = fileManager.getLocationForModule( 490170031Sjoel StandardLocation.PATCH_MODULE_PATH, defaultModule.name.toString()); 491170031Sjoel } catch (IOException ex) { 492170031Sjoel throw new Error(ex); 493170031Sjoel } 494170031Sjoel } 495159687Snetchild if (defaultModule.patchLocation == null) { 496 defaultModule.classLocation = StandardLocation.CLASS_OUTPUT; 497 } else { 498 defaultModule.patchOutputLocation = StandardLocation.CLASS_OUTPUT; 499 } 500 break; 501 default: 502 Assert.error("too many modules"); 503 } 504 } else if (rootModules.size() == 1) { 505 module = rootModules.iterator().next(); 506 module.complete(); 507 module.completer = sym -> completeModule((ModuleSymbol) sym); 508 } else { 509 Assert.check(rootModules.isEmpty()); 510 String moduleOverride = singleModuleOverride(trees); 511 if (moduleOverride != null) { 512 module = moduleFinder.findModule(names.fromString(moduleOverride)); 513 } else { 514 module = defaultModule; 515 } 516 rootModules.add(module); 517 } 518 519 if (defaultModule != syms.unnamedModule) { 520 syms.unnamedModule.completer = getUnnamedModuleCompleter(); 521 syms.unnamedModule.classLocation = StandardLocation.CLASS_PATH; 522 } 523 524 if (module == null) { 525 module = defaultModule; 526 } 527 528 for (JCCompilationUnit tree : trees) { 529 if (defaultModule != syms.unnamedModule 530 && defaultModule.sourceLocation == StandardLocation.SOURCE_PATH 531 && fileManager.hasLocation(StandardLocation.SOURCE_PATH)) { 532 checkSourceLocation(tree, module); 533 } 534 tree.modle = module; 535 } 536 } 537 } 538 539 private void checkSourceLocation(JCCompilationUnit tree, ModuleSymbol msym) { 540 // skip check if legacy module override still in use 541 if (legacyModuleOverride != null) { 542 return; 543 } 544 545 try { 546 JavaFileObject fo = tree.sourcefile; 547 if (fileManager.contains(msym.sourceLocation, fo)) { 548 return; 549 } 550 if (msym.patchLocation != null && fileManager.contains(msym.patchLocation, fo)) { 551 return; 552 } 553 if (fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT)) { 554 if (fileManager.contains(StandardLocation.SOURCE_OUTPUT, fo)) { 555 return; 556 } 557 } else { 558 if (fileManager.contains(StandardLocation.CLASS_OUTPUT, fo)) { 559 return; 560 } 561 } 562 } catch (IOException e) { 563 throw new Error(e); 564 } 565 566 JavaFileObject prev = log.useSource(tree.sourcefile); 567 try { 568 log.error(tree.pos(), Errors.FileSbOnSourceOrPatchPathForModule); 569 } finally { 570 log.useSource(prev); 571 } 572 } 573 574 private String singleModuleOverride(List<JCCompilationUnit> trees) { 575 if (!fileManager.hasLocation(StandardLocation.PATCH_MODULE_PATH)) { 576 return legacyModuleOverride; 577 } 578 579 Set<String> override = new LinkedHashSet<>(); 580 for (JCCompilationUnit tree : trees) { 581 JavaFileObject fo = tree.sourcefile; 582 583 try { 584 Location loc = 585 fileManager.getLocationForModule(StandardLocation.PATCH_MODULE_PATH, fo); 586 587 if (loc != null) { 588 override.add(fileManager.inferModuleName(loc)); 589 } 590 } catch (IOException ex) { 591 throw new Error(ex); 592 } 593 } 594 595 switch (override.size()) { 596 case 0: return legacyModuleOverride; 597 case 1: return override.iterator().next(); 598 default: 599 log.error(Errors.TooManyPatchedModules(override)); 600 return null; 601 } 602 } 603 604 /** 605 * Determine the location for the module on the module source path 606 * or source output directory which contains a given CompilationUnit. 607 * If the source output directory is unset, the class output directory 608 * will be checked instead. 609 * {@code null} is returned if no such module can be found. 610 * @param tree the compilation unit tree 611 * @return the location for the enclosing module 612 * @throws IOException if there is a problem while searching for the module. 613 */ 614 private Location getModuleLocation(JCCompilationUnit tree) throws IOException { 615 JavaFileObject fo = tree.sourcefile; 616 617 Location loc = 618 fileManager.getLocationForModule(StandardLocation.MODULE_SOURCE_PATH, fo); 619 if (loc == null) { 620 Location sourceOutput = fileManager.hasLocation(StandardLocation.SOURCE_OUTPUT) ? 621 StandardLocation.SOURCE_OUTPUT : StandardLocation.CLASS_OUTPUT; 622 loc = 623 fileManager.getLocationForModule(sourceOutput, fo); 624 } 625 return loc; 626 } 627 628 private void checkNoAllModulePath() { 629 if (addModsOpt != null && Arrays.asList(addModsOpt.split(",")).contains(ALL_MODULE_PATH)) { 630 log.error(Errors.AddmodsAllModulePathInvalid); 631 } 632 } 633 634 private final Completer mainCompleter = new Completer() { 635 @Override 636 public void complete(Symbol sym) throws CompletionFailure { 637 ModuleSymbol msym = moduleFinder.findModule((ModuleSymbol) sym); 638 639 if (msym.kind == ERR) { 640 //make sure the module is initialized: 641 msym.directives = List.nil(); 642 msym.exports = List.nil(); 643 msym.provides = List.nil(); 644 msym.requires = List.nil(); 645 msym.uses = List.nil(); 646 } else if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) { 647 setupAutomaticModule(msym); 648 } else { 649 msym.module_info.complete(); 650 } 651 652 // If module-info comes from a .java file, the underlying 653 // call of classFinder.fillIn will have called through the 654 // source completer, to Enter, and then to Modules.enter, 655 // which will call completeModule. 656 // But, if module-info comes from a .class file, the underlying 657 // call of classFinder.fillIn will just call ClassReader to read 658 // the .class file, and so we call completeModule here. 659 if (msym.module_info.classfile == null || msym.module_info.classfile.getKind() == Kind.CLASS) { 660 completeModule(msym); 661 } 662 } 663 664 @Override 665 public String toString() { 666 return "mainCompleter"; 667 } 668 }; 669 670 private void setupAutomaticModule(ModuleSymbol msym) throws CompletionFailure { 671 try { 672 ListBuffer<Directive> directives = new ListBuffer<>(); 673 ListBuffer<ExportsDirective> exports = new ListBuffer<>(); 674 Set<String> seenPackages = new HashSet<>(); 675 676 for (JavaFileObject clazz : fileManager.list(msym.classLocation, "", EnumSet.of(Kind.CLASS), true)) { 677 String binName = fileManager.inferBinaryName(msym.classLocation, clazz); 678 String pack = binName.lastIndexOf('.') != (-1) ? binName.substring(0, binName.lastIndexOf('.')) : ""; //unnamed package???? 679 if (seenPackages.add(pack)) { 680 ExportsDirective d = new ExportsDirective(syms.enterPackage(msym, names.fromString(pack)), null); 681 //TODO: opens? 682 directives.add(d); 683 exports.add(d); 684 } 685 } 686 687 msym.exports = exports.toList(); 688 msym.provides = List.nil(); 689 msym.requires = List.nil(); 690 msym.uses = List.nil(); 691 msym.directives = directives.toList(); 692 msym.flags_field |= Flags.ACYCLIC; 693 } catch (IOException ex) { 694 throw new IllegalStateException(ex); 695 } 696 } 697 698 private void completeAutomaticModule(ModuleSymbol msym) throws CompletionFailure { 699 ListBuffer<Directive> directives = new ListBuffer<>(); 700 701 directives.addAll(msym.directives); 702 703 ListBuffer<RequiresDirective> requires = new ListBuffer<>(); 704 705 for (ModuleSymbol ms : allModules()) { 706 if (ms == syms.unnamedModule || ms == msym) 707 continue; 708 Set<RequiresFlag> flags = (ms.flags_field & Flags.AUTOMATIC_MODULE) != 0 ? 709 EnumSet.of(RequiresFlag.TRANSITIVE) : EnumSet.noneOf(RequiresFlag.class); 710 RequiresDirective d = new RequiresDirective(ms, flags); 711 directives.add(d); 712 requires.add(d); 713 } 714 715 RequiresDirective requiresUnnamed = new RequiresDirective(syms.unnamedModule); 716 directives.add(requiresUnnamed); 717 requires.add(requiresUnnamed); 718 719 msym.requires = requires.toList(); 720 msym.directives = directives.toList(); 721 } 722 723 private Completer getSourceCompleter(JCCompilationUnit tree) { 724 return new Completer() { 725 @Override 726 public void complete(Symbol sym) throws CompletionFailure { 727 ModuleSymbol msym = (ModuleSymbol) sym; 728 msym.flags_field |= UNATTRIBUTED; 729 ModuleVisitor v = new ModuleVisitor(); 730 JavaFileObject prev = log.useSource(tree.sourcefile); 731 JCModuleDecl moduleDecl = tree.getModuleDecl(); 732 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(moduleDecl.pos()); 733 734 try { 735 moduleDecl.accept(v); 736 completeModule(msym); 737 checkCyclicDependencies(moduleDecl); 738 } finally { 739 log.useSource(prev); 740 deferredLintHandler.setPos(prevLintPos); 741 msym.flags_field &= ~UNATTRIBUTED; 742 } 743 } 744 745 @Override 746 public String toString() { 747 return "SourceCompleter: " + tree.sourcefile.getName(); 748 } 749 750 }; 751 } 752 753 public boolean isRootModule(ModuleSymbol module) { 754 Assert.checkNonNull(rootModules); 755 return rootModules.contains(module); 756 } 757 758 public Set<ModuleSymbol> getRootModules() { 759 Assert.checkNonNull(rootModules); 760 return rootModules; 761 } 762 763 class ModuleVisitor extends JCTree.Visitor { 764 private ModuleSymbol sym; 765 private final Set<ModuleSymbol> allRequires = new HashSet<>(); 766 private final Map<PackageSymbol,List<ExportsDirective>> allExports = new HashMap<>(); 767 private final Map<PackageSymbol,List<OpensDirective>> allOpens = new HashMap<>(); 768 769 @Override 770 public void visitModuleDef(JCModuleDecl tree) { 771 sym = Assert.checkNonNull(tree.sym); 772 773 if (tree.getModuleType() == ModuleKind.OPEN) { 774 sym.flags.add(ModuleFlags.OPEN); 775 } 776 sym.flags_field |= (tree.mods.flags & Flags.DEPRECATED); 777 778 sym.requires = List.nil(); 779 sym.exports = List.nil(); 780 sym.opens = List.nil(); 781 tree.directives.forEach(t -> t.accept(this)); 782 sym.requires = sym.requires.reverse(); 783 sym.exports = sym.exports.reverse(); 784 sym.opens = sym.opens.reverse(); 785 ensureJavaBase(); 786 } 787 788 @Override 789 public void visitRequires(JCRequires tree) { 790 ModuleSymbol msym = lookupModule(tree.moduleName); 791 if (msym.kind != MDL) { 792 log.error(tree.moduleName.pos(), Errors.ModuleNotFound(msym)); 793 warnedMissing.add(msym); 794 } else if (allRequires.contains(msym)) { 795 log.error(tree.moduleName.pos(), Errors.DuplicateRequires(msym)); 796 } else { 797 allRequires.add(msym); 798 Set<RequiresFlag> flags = EnumSet.noneOf(RequiresFlag.class); 799 if (tree.isTransitive) 800 flags.add(RequiresFlag.TRANSITIVE); 801 if (tree.isStaticPhase) 802 flags.add(RequiresFlag.STATIC_PHASE); 803 RequiresDirective d = new RequiresDirective(msym, flags); 804 tree.directive = d; 805 sym.requires = sym.requires.prepend(d); 806 } 807 } 808 809 @Override 810 public void visitExports(JCExports tree) { 811 Name name = TreeInfo.fullName(tree.qualid); 812 PackageSymbol packge = syms.enterPackage(sym, name); 813 attr.setPackageSymbols(tree.qualid, packge); 814 815 List<ExportsDirective> exportsForPackage = allExports.computeIfAbsent(packge, p -> List.nil()); 816 for (ExportsDirective d : exportsForPackage) { 817 reportExportsConflict(tree, packge); 818 } 819 820 List<ModuleSymbol> toModules = null; 821 if (tree.moduleNames != null) { 822 Set<ModuleSymbol> to = new LinkedHashSet<>(); 823 for (JCExpression n: tree.moduleNames) { 824 ModuleSymbol msym = lookupModule(n); 825 chk.checkModuleExists(n.pos(), msym); 826 for (ExportsDirective d : exportsForPackage) { 827 checkDuplicateExportsToModule(n, msym, d); 828 } 829 if (!to.add(msym)) { 830 reportExportsConflictToModule(n, msym); 831 } 832 } 833 toModules = List.from(to); 834 } 835 836 if (toModules == null || !toModules.isEmpty()) { 837 Set<ExportsFlag> flags = EnumSet.noneOf(ExportsFlag.class); 838 ExportsDirective d = new ExportsDirective(packge, toModules, flags); 839 sym.exports = sym.exports.prepend(d); 840 tree.directive = d; 841 842 allExports.put(packge, exportsForPackage.prepend(d)); 843 } 844 } 845 846 private void reportExportsConflict(JCExports tree, PackageSymbol packge) { 847 log.error(tree.qualid.pos(), Errors.ConflictingExports(packge)); 848 } 849 850 private void checkDuplicateExportsToModule(JCExpression name, ModuleSymbol msym, 851 ExportsDirective d) { 852 if (d.modules != null) { 853 for (ModuleSymbol other : d.modules) { 854 if (msym == other) { 855 reportExportsConflictToModule(name, msym); 856 } 857 } 858 } 859 } 860 861 private void reportExportsConflictToModule(JCExpression name, ModuleSymbol msym) { 862 log.error(name.pos(), Errors.ConflictingExportsToModule(msym)); 863 } 864 865 @Override 866 public void visitOpens(JCOpens tree) { 867 Name name = TreeInfo.fullName(tree.qualid); 868 PackageSymbol packge = syms.enterPackage(sym, name); 869 attr.setPackageSymbols(tree.qualid, packge); 870 871 if (sym.flags.contains(ModuleFlags.OPEN)) { 872 log.error(tree.pos(), Errors.NoOpensUnlessStrong); 873 } 874 List<OpensDirective> opensForPackage = allOpens.computeIfAbsent(packge, p -> List.nil()); 875 for (OpensDirective d : opensForPackage) { 876 reportOpensConflict(tree, packge); 877 } 878 879 List<ModuleSymbol> toModules = null; 880 if (tree.moduleNames != null) { 881 Set<ModuleSymbol> to = new LinkedHashSet<>(); 882 for (JCExpression n: tree.moduleNames) { 883 ModuleSymbol msym = lookupModule(n); 884 chk.checkModuleExists(n.pos(), msym); 885 for (OpensDirective d : opensForPackage) { 886 checkDuplicateOpensToModule(n, msym, d); 887 } 888 if (!to.add(msym)) { 889 reportOpensConflictToModule(n, msym); 890 } 891 } 892 toModules = List.from(to); 893 } 894 895 if (toModules == null || !toModules.isEmpty()) { 896 Set<OpensFlag> flags = EnumSet.noneOf(OpensFlag.class); 897 OpensDirective d = new OpensDirective(packge, toModules, flags); 898 sym.opens = sym.opens.prepend(d); 899 tree.directive = d; 900 901 allOpens.put(packge, opensForPackage.prepend(d)); 902 } 903 } 904 905 private void reportOpensConflict(JCOpens tree, PackageSymbol packge) { 906 log.error(tree.qualid.pos(), Errors.ConflictingOpens(packge)); 907 } 908 909 private void checkDuplicateOpensToModule(JCExpression name, ModuleSymbol msym, 910 OpensDirective d) { 911 if (d.modules != null) { 912 for (ModuleSymbol other : d.modules) { 913 if (msym == other) { 914 reportOpensConflictToModule(name, msym); 915 } 916 } 917 } 918 } 919 920 private void reportOpensConflictToModule(JCExpression name, ModuleSymbol msym) { 921 log.error(name.pos(), Errors.ConflictingOpensToModule(msym)); 922 } 923 924 @Override 925 public void visitProvides(JCProvides tree) { } 926 927 @Override 928 public void visitUses(JCUses tree) { } 929 930 private void ensureJavaBase() { 931 if (sym.name == names.java_base) 932 return; 933 934 for (RequiresDirective d: sym.requires) { 935 if (d.module.name == names.java_base) 936 return; 937 } 938 939 ModuleSymbol java_base = syms.enterModule(names.java_base); 940 Directive.RequiresDirective d = 941 new Directive.RequiresDirective(java_base, 942 EnumSet.of(Directive.RequiresFlag.MANDATED)); 943 sym.requires = sym.requires.prepend(d); 944 } 945 946 private ModuleSymbol lookupModule(JCExpression moduleName) { 947 Name name = TreeInfo.fullName(moduleName); 948 ModuleSymbol msym = moduleFinder.findModule(name); 949 TreeInfo.setSymbol(moduleName, msym); 950 return msym; 951 } 952 } 953 954 public Completer getUsesProvidesCompleter() { 955 return sym -> { 956 ModuleSymbol msym = (ModuleSymbol) sym; 957 958 msym.complete(); 959 960 Env<AttrContext> env = typeEnvs.get(msym); 961 UsesProvidesVisitor v = new UsesProvidesVisitor(msym, env); 962 JavaFileObject prev = log.useSource(env.toplevel.sourcefile); 963 JCModuleDecl decl = env.toplevel.getModuleDecl(); 964 DiagnosticPosition prevLintPos = deferredLintHandler.setPos(decl.pos()); 965 966 try { 967 decl.accept(v); 968 } finally { 969 log.useSource(prev); 970 deferredLintHandler.setPos(prevLintPos); 971 } 972 }; 973 } 974 975 class UsesProvidesVisitor extends JCTree.Visitor { 976 private final ModuleSymbol msym; 977 private final Env<AttrContext> env; 978 979 private final Set<ClassSymbol> allUses = new HashSet<>(); 980 private final Map<ClassSymbol, Set<ClassSymbol>> allProvides = new HashMap<>(); 981 982 public UsesProvidesVisitor(ModuleSymbol msym, Env<AttrContext> env) { 983 this.msym = msym; 984 this.env = env; 985 } 986 987 @Override @SuppressWarnings("unchecked") 988 public void visitModuleDef(JCModuleDecl tree) { 989 msym.directives = List.nil(); 990 msym.provides = List.nil(); 991 msym.uses = List.nil(); 992 tree.directives.forEach(t -> t.accept(this)); 993 msym.directives = msym.directives.reverse(); 994 msym.provides = msym.provides.reverse(); 995 msym.uses = msym.uses.reverse(); 996 997 if (msym.requires.nonEmpty() && msym.requires.head.flags.contains(RequiresFlag.MANDATED)) 998 msym.directives = msym.directives.prepend(msym.requires.head); 999 1000 msym.directives = msym.directives.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet()))); 1001 1002 checkForCorrectness(); 1003 } 1004 1005 @Override 1006 public void visitExports(JCExports tree) { 1007 Iterable<Symbol> packageContent = tree.directive.packge.members().getSymbols(); 1008 List<JavaFileObject> filesToCheck = List.nil(); 1009 boolean packageNotEmpty = false; 1010 for (Symbol sym : packageContent) { 1011 if (sym.kind != Kinds.Kind.TYP) 1012 continue; 1013 ClassSymbol csym = (ClassSymbol) sym; 1014 if (sym.completer.isTerminal() || 1015 csym.classfile.getKind() == Kind.CLASS) { 1016 packageNotEmpty = true; 1017 filesToCheck = List.nil(); 1018 break; 1019 } 1020 if (csym.classfile.getKind() == Kind.SOURCE) { 1021 filesToCheck = filesToCheck.prepend(csym.classfile); 1022 } 1023 } 1024 for (JavaFileObject jfo : filesToCheck) { 1025 if (findPackageInFile.findPackageNameOf(jfo) == tree.directive.packge.fullname) { 1026 packageNotEmpty = true; 1027 break; 1028 } 1029 } 1030 if (!packageNotEmpty) { 1031 log.error(tree.qualid.pos(), Errors.PackageEmptyOrNotFound(tree.directive.packge)); 1032 } 1033 msym.directives = msym.directives.prepend(tree.directive); 1034 } 1035 1036 @Override 1037 public void visitOpens(JCOpens tree) { 1038 chk.checkPackageExistsForOpens(tree.qualid, tree.directive.packge); 1039 msym.directives = msym.directives.prepend(tree.directive); 1040 } 1041 1042 MethodSymbol noArgsConstructor(ClassSymbol tsym) { 1043 for (Symbol sym : tsym.members().getSymbolsByName(names.init)) { 1044 MethodSymbol mSym = (MethodSymbol)sym; 1045 if (mSym.params().isEmpty()) { 1046 return mSym; 1047 } 1048 } 1049 return null; 1050 } 1051 1052 MethodSymbol factoryMethod(ClassSymbol tsym) { 1053 for (Symbol sym : tsym.members().getSymbolsByName(names.provider, sym -> sym.kind == MTH)) { 1054 MethodSymbol mSym = (MethodSymbol)sym; 1055 if (mSym.isStatic() && (mSym.flags() & Flags.PUBLIC) != 0 && mSym.params().isEmpty()) { 1056 return mSym; 1057 } 1058 } 1059 return null; 1060 } 1061 1062 Map<Directive.ProvidesDirective, JCProvides> directiveToTreeMap = new HashMap<>(); 1063 1064 @Override 1065 public void visitProvides(JCProvides tree) { 1066 Type st = attr.attribType(tree.serviceName, env, syms.objectType); 1067 ClassSymbol service = (ClassSymbol) st.tsym; 1068 if (allProvides.containsKey(service)) { 1069 log.error(tree.serviceName.pos(), Errors.RepeatedProvidesForService(service)); 1070 } 1071 ListBuffer<ClassSymbol> impls = new ListBuffer<>(); 1072 for (JCExpression implName : tree.implNames) { 1073 Type it; 1074 boolean prevVisitingServiceImplementation = env.info.visitingServiceImplementation; 1075 try { 1076 env.info.visitingServiceImplementation = true; 1077 it = attr.attribType(implName, env, syms.objectType); 1078 } finally { 1079 env.info.visitingServiceImplementation = prevVisitingServiceImplementation; 1080 } 1081 ClassSymbol impl = (ClassSymbol) it.tsym; 1082 if ((impl.flags_field & PUBLIC) == 0) { 1083 log.error(implName.pos(), Errors.NotDefPublic(impl, impl.location())); 1084 } 1085 //find provider factory: 1086 MethodSymbol factory = factoryMethod(impl); 1087 if (factory != null) { 1088 Type returnType = factory.type.getReturnType(); 1089 if (!types.isSubtype(returnType, st)) { 1090 log.error(implName.pos(), Errors.ServiceImplementationProviderReturnMustBeSubtypeOfServiceInterface); 1091 } 1092 } else { 1093 if (!types.isSubtype(it, st)) { 1094 log.error(implName.pos(), Errors.ServiceImplementationMustBeSubtypeOfServiceInterface); 1095 } else if ((impl.flags() & ABSTRACT) != 0) { 1096 log.error(implName.pos(), Errors.ServiceImplementationIsAbstract(impl)); 1097 } else if (impl.isInner()) { 1098 log.error(implName.pos(), Errors.ServiceImplementationIsInner(impl)); 1099 } else { 1100 MethodSymbol constr = noArgsConstructor(impl); 1101 if (constr == null) { 1102 log.error(implName.pos(), Errors.ServiceImplementationDoesntHaveANoArgsConstructor(impl)); 1103 } else if ((constr.flags() & PUBLIC) == 0) { 1104 log.error(implName.pos(), Errors.ServiceImplementationNoArgsConstructorNotPublic(impl)); 1105 } 1106 } 1107 } 1108 if (it.hasTag(CLASS)) { 1109 if (allProvides.computeIfAbsent(service, s -> new HashSet<>()).add(impl)) { 1110 impls.append(impl); 1111 } else { 1112 log.error(implName.pos(), Errors.DuplicateProvides(service, impl)); 1113 } 1114 } 1115 } 1116 if (st.hasTag(CLASS) && !impls.isEmpty()) { 1117 Directive.ProvidesDirective d = new Directive.ProvidesDirective(service, impls.toList()); 1118 msym.provides = msym.provides.prepend(d); 1119 msym.directives = msym.directives.prepend(d); 1120 directiveToTreeMap.put(d, tree); 1121 } 1122 } 1123 1124 @Override 1125 public void visitRequires(JCRequires tree) { 1126 if (tree.directive != null && allModules().contains(tree.directive.module)) { 1127 chk.checkDeprecated(tree.moduleName.pos(), msym, tree.directive.module); 1128 chk.checkModuleRequires(tree.moduleName.pos(), tree.directive); 1129 msym.directives = msym.directives.prepend(tree.directive); 1130 } 1131 } 1132 1133 @Override 1134 public void visitUses(JCUses tree) { 1135 Type st = attr.attribType(tree.qualid, env, syms.objectType); 1136 Symbol sym = TreeInfo.symbol(tree.qualid); 1137 if ((sym.flags() & ENUM) != 0) { 1138 log.error(tree.qualid.pos(), Errors.ServiceDefinitionIsEnum(st.tsym)); 1139 } else if (st.hasTag(CLASS)) { 1140 ClassSymbol service = (ClassSymbol) st.tsym; 1141 if (allUses.add(service)) { 1142 Directive.UsesDirective d = new Directive.UsesDirective(service); 1143 msym.uses = msym.uses.prepend(d); 1144 msym.directives = msym.directives.prepend(d); 1145 } else { 1146 log.error(tree.pos(), Errors.DuplicateUses(service)); 1147 } 1148 } 1149 } 1150 1151 private void checkForCorrectness() { 1152 for (Directive.ProvidesDirective provides : msym.provides) { 1153 JCProvides tree = directiveToTreeMap.get(provides); 1154 for (ClassSymbol impl : provides.impls) { 1155 /* The implementation must be defined in the same module as the provides directive 1156 * (else, error) 1157 */ 1158 PackageSymbol implementationDefiningPackage = impl.packge(); 1159 if (implementationDefiningPackage.modle != msym) { 1160 // TODO: should use tree for the implentation name, not the entire provides tree 1161 // TODO: should improve error message to identify the implementation type 1162 log.error(tree.pos(), Errors.ServiceImplementationNotInRightModule(implementationDefiningPackage.modle)); 1163 } 1164 1165 /* There is no inherent requirement that module that provides a service should actually 1166 * use it itself. However, it is a pointless declaration if the service package is not 1167 * exported and there is no uses for the service. 1168 */ 1169 PackageSymbol interfaceDeclaringPackage = provides.service.packge(); 1170 boolean isInterfaceDeclaredInCurrentModule = interfaceDeclaringPackage.modle == msym; 1171 boolean isInterfaceExportedFromAReadableModule = 1172 msym.visiblePackages.get(interfaceDeclaringPackage.fullname) == interfaceDeclaringPackage; 1173 if (isInterfaceDeclaredInCurrentModule && !isInterfaceExportedFromAReadableModule) { 1174 // ok the interface is declared in this module. Let's check if it's exported 1175 boolean warn = true; 1176 for (ExportsDirective export : msym.exports) { 1177 if (interfaceDeclaringPackage == export.packge) { 1178 warn = false; 1179 break; 1180 } 1181 } 1182 if (warn) { 1183 for (UsesDirective uses : msym.uses) { 1184 if (provides.service == uses.service) { 1185 warn = false; 1186 break; 1187 } 1188 } 1189 } 1190 if (warn) { 1191 log.warning(tree.pos(), Warnings.ServiceProvidedButNotExportedOrUsed(provides.service)); 1192 } 1193 } 1194 } 1195 } 1196 } 1197 } 1198 1199 private Set<ModuleSymbol> allModules; 1200 1201 public Set<ModuleSymbol> allModules() { 1202 Assert.checkNonNull(allModules); 1203 return allModules; 1204 } 1205 1206 private void setupAllModules() { 1207 Assert.checkNonNull(rootModules); 1208 Assert.checkNull(allModules); 1209 1210 Set<ModuleSymbol> observable; 1211 1212 if (limitModsOpt == null && extraLimitMods.isEmpty()) { 1213 observable = null; 1214 } else { 1215 Set<ModuleSymbol> limitMods = new HashSet<>(); 1216 if (limitModsOpt != null) { 1217 for (String limit : limitModsOpt.split(",")) { 1218 if (!isValidName(limit)) 1219 continue; 1220 limitMods.add(syms.enterModule(names.fromString(limit))); 1221 } 1222 } 1223 for (String limit : extraLimitMods) { 1224 limitMods.add(syms.enterModule(names.fromString(limit))); 1225 } 1226 observable = computeTransitiveClosure(limitMods, rootModules, null); 1227 observable.addAll(rootModules); 1228 if (lintOptions) { 1229 for (ModuleSymbol msym : limitMods) { 1230 if (!observable.contains(msym)) { 1231 log.warning(LintCategory.OPTIONS, 1232 Warnings.ModuleForOptionNotFound(Option.LIMIT_MODULES, msym)); 1233 } 1234 } 1235 } 1236 } 1237 1238 Predicate<ModuleSymbol> observablePred = sym -> 1239 (observable == null) ? (moduleFinder.findModule(sym).kind != ERR) : observable.contains(sym); 1240 Predicate<ModuleSymbol> systemModulePred = sym -> (sym.flags() & Flags.SYSTEM_MODULE) != 0; 1241 Predicate<ModuleSymbol> noIncubatorPred = sym -> { 1242 sym.complete(); 1243 return !sym.resolutionFlags.contains(ModuleResolutionFlags.DO_NOT_RESOLVE_BY_DEFAULT); 1244 }; 1245 Set<ModuleSymbol> enabledRoot = new LinkedHashSet<>(); 1246 1247 if (rootModules.contains(syms.unnamedModule)) { 1248 ModuleSymbol javaSE = syms.getModule(java_se); 1249 Predicate<ModuleSymbol> jdkModulePred; 1250 1251 if (javaSE != null && (observable == null || observable.contains(javaSE))) { 1252 jdkModulePred = sym -> { 1253 sym.complete(); 1254 return !sym.name.startsWith(java_) 1255 && sym.exports.stream().anyMatch(e -> e.modules == null); 1256 }; 1257 enabledRoot.add(javaSE); 1258 } else { 1259 jdkModulePred = sym -> true; 1260 } 1261 1262 for (ModuleSymbol sym : new HashSet<>(syms.getAllModules())) { 1263 if (systemModulePred.test(sym) && observablePred.test(sym) && jdkModulePred.test(sym) && noIncubatorPred.test(sym)) { 1264 enabledRoot.add(sym); 1265 } 1266 } 1267 } 1268 1269 enabledRoot.addAll(rootModules); 1270 1271 if (addModsOpt != null || !extraAddMods.isEmpty()) { 1272 Set<String> fullAddMods = new HashSet<>(); 1273 fullAddMods.addAll(extraAddMods); 1274 1275 if (addModsOpt != null) { 1276 fullAddMods.addAll(Arrays.asList(addModsOpt.split(","))); 1277 } 1278 1279 for (String added : fullAddMods) { 1280 Stream<ModuleSymbol> modules; 1281 switch (added) { 1282 case ALL_SYSTEM: 1283 modules = new HashSet<>(syms.getAllModules()) 1284 .stream() 1285 .filter(systemModulePred.and(observablePred)); 1286 break; 1287 case ALL_MODULE_PATH: 1288 modules = new HashSet<>(syms.getAllModules()) 1289 .stream() 1290 .filter(systemModulePred.negate().and(observablePred)); 1291 break; 1292 default: 1293 if (!isValidName(added)) 1294 continue; 1295 modules = Stream.of(syms.enterModule(names.fromString(added))); 1296 break; 1297 } 1298 modules.forEach(sym -> { 1299 enabledRoot.add(sym); 1300 if (observable != null) 1301 observable.add(sym); 1302 }); 1303 } 1304 } 1305 1306 Set<ModuleSymbol> result = computeTransitiveClosure(enabledRoot, rootModules, observable); 1307 1308 result.add(syms.unnamedModule); 1309 1310 boolean hasAutomatic = result.stream().anyMatch(IS_AUTOMATIC); 1311 1312 if (hasAutomatic) { 1313 syms.getAllModules() 1314 .stream() 1315 .filter(IS_AUTOMATIC) 1316 .forEach(result::add); 1317 } 1318 1319 String incubatingModules = result.stream() 1320 .filter(msym -> msym.resolutionFlags.contains(ModuleResolutionFlags.WARN_INCUBATING)) 1321 .map(msym -> msym.name.toString()) 1322 .collect(Collectors.joining(",")); 1323 1324 if (!incubatingModules.isEmpty()) { 1325 log.warning(Warnings.IncubatingModules(incubatingModules)); 1326 } 1327 1328 allModules = result; 1329 1330 //add module versions from options, if any: 1331 if (moduleVersionOpt != null) { 1332 Name version = names.fromString(moduleVersionOpt); 1333 rootModules.forEach(m -> m.version = version); 1334 } 1335 } 1336 //where: 1337 private static final Predicate<ModuleSymbol> IS_AUTOMATIC = 1338 m -> (m.flags_field & Flags.AUTOMATIC_MODULE) != 0; 1339 1340 public boolean isInModuleGraph(ModuleSymbol msym) { 1341 return allModules == null || allModules.contains(msym); 1342 } 1343 1344 private Set<ModuleSymbol> computeTransitiveClosure(Set<? extends ModuleSymbol> base, 1345 Set<? extends ModuleSymbol> rootModules, 1346 Set<ModuleSymbol> observable) { 1347 List<ModuleSymbol> primaryTodo = List.nil(); 1348 List<ModuleSymbol> secondaryTodo = List.nil(); 1349 1350 for (ModuleSymbol ms : base) { 1351 if (rootModules.contains(ms)) { 1352 primaryTodo = primaryTodo.prepend(ms); 1353 } else { 1354 secondaryTodo = secondaryTodo.prepend(ms); 1355 } 1356 } 1357 1358 Set<ModuleSymbol> result = new LinkedHashSet<>(); 1359 result.add(syms.java_base); 1360 1361 while (primaryTodo.nonEmpty() || secondaryTodo.nonEmpty()) { 1362 ModuleSymbol current; 1363 boolean isPrimaryTodo; 1364 if (primaryTodo.nonEmpty()) { 1365 current = primaryTodo.head; 1366 primaryTodo = primaryTodo.tail; 1367 isPrimaryTodo = true; 1368 } else { 1369 current = secondaryTodo.head; 1370 secondaryTodo = secondaryTodo.tail; 1371 isPrimaryTodo = false; 1372 } 1373 if (observable != null && !observable.contains(current)) 1374 continue; 1375 if (!result.add(current) || current == syms.unnamedModule || ((current.flags_field & Flags.AUTOMATIC_MODULE) != 0)) 1376 continue; 1377 current.complete(); 1378 if (current.kind == ERR && (isPrimaryTodo || base.contains(current)) && warnedMissing.add(current)) { 1379 log.error(Errors.ModuleNotFound(current)); 1380 } 1381 for (RequiresDirective rd : current.requires) { 1382 if (rd.module == syms.java_base) continue; 1383 if ((rd.isTransitive() && isPrimaryTodo) || rootModules.contains(current)) { 1384 primaryTodo = primaryTodo.prepend(rd.module); 1385 } else { 1386 secondaryTodo = secondaryTodo.prepend(rd.module); 1387 } 1388 } 1389 } 1390 1391 return result; 1392 } 1393 1394 public ModuleSymbol getObservableModule(Name name) { 1395 ModuleSymbol mod = syms.getModule(name); 1396 1397 if (allModules().contains(mod)) { 1398 return mod; 1399 } 1400 1401 return null; 1402 } 1403 1404 private Completer getUnnamedModuleCompleter() { 1405 moduleFinder.findAllModules(); 1406 return new Symbol.Completer() { 1407 @Override 1408 public void complete(Symbol sym) throws CompletionFailure { 1409 if (inInitModules) { 1410 sym.completer = this; 1411 return ; 1412 } 1413 ModuleSymbol msym = (ModuleSymbol) sym; 1414 Set<ModuleSymbol> allModules = new HashSet<>(allModules()); 1415 allModules.remove(syms.unnamedModule); 1416 for (ModuleSymbol m : allModules) { 1417 m.complete(); 1418 } 1419 initVisiblePackages(msym, allModules); 1420 } 1421 1422 @Override 1423 public String toString() { 1424 return "unnamedModule Completer"; 1425 } 1426 }; 1427 } 1428 1429 private final Map<ModuleSymbol, Set<ModuleSymbol>> requiresTransitiveCache = new HashMap<>(); 1430 1431 private void completeModule(ModuleSymbol msym) { 1432 if (inInitModules) { 1433 msym.completer = sym -> completeModule(msym); 1434 return ; 1435 } 1436 1437 if ((msym.flags_field & Flags.AUTOMATIC_MODULE) != 0) { 1438 completeAutomaticModule(msym); 1439 } 1440 1441 Assert.checkNonNull(msym.requires); 1442 1443 initAddReads(); 1444 1445 msym.requires = msym.requires.appendList(List.from(addReads.getOrDefault(msym, Collections.emptySet()))); 1446 1447 List<RequiresDirective> requires = msym.requires; 1448 1449 while (requires.nonEmpty()) { 1450 if (!allModules().contains(requires.head.module)) { 1451 Env<AttrContext> env = typeEnvs.get(msym); 1452 if (env != null) { 1453 JavaFileObject origSource = log.useSource(env.toplevel.sourcefile); 1454 try { 1455 log.error(/*XXX*/env.tree, Errors.ModuleNotFound(requires.head.module)); 1456 } finally { 1457 log.useSource(origSource); 1458 } 1459 } else { 1460 Assert.check((msym.flags() & Flags.AUTOMATIC_MODULE) == 0); 1461 } 1462 msym.requires = List.filter(msym.requires, requires.head); 1463 } 1464 requires = requires.tail; 1465 } 1466 1467 Set<ModuleSymbol> readable = new LinkedHashSet<>(); 1468 Set<ModuleSymbol> requiresTransitive = new HashSet<>(); 1469 1470 for (RequiresDirective d : msym.requires) { 1471 d.module.complete(); 1472 readable.add(d.module); 1473 Set<ModuleSymbol> s = retrieveRequiresTransitive(d.module); 1474 Assert.checkNonNull(s, () -> "no entry in cache for " + d.module); 1475 readable.addAll(s); 1476 if (d.flags.contains(RequiresFlag.TRANSITIVE)) { 1477 requiresTransitive.add(d.module); 1478 requiresTransitive.addAll(s); 1479 } 1480 } 1481 1482 requiresTransitiveCache.put(msym, requiresTransitive); 1483 initVisiblePackages(msym, readable); 1484 for (ExportsDirective d: msym.exports) { 1485 if (d.packge != null) { 1486 d.packge.modle = msym; 1487 } 1488 } 1489 1490 if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0 && 1491 msym.patchLocation != null) { 1492 log.error(Errors.PatchModuleWithRelease(msym)); 1493 } 1494 } 1495 1496 private Set<ModuleSymbol> retrieveRequiresTransitive(ModuleSymbol msym) { 1497 Set<ModuleSymbol> requiresTransitive = requiresTransitiveCache.get(msym); 1498 1499 if (requiresTransitive == null) { 1500 //the module graph may contain cycles involving automatic modules or --add-reads edges 1501 requiresTransitive = new HashSet<>(); 1502 1503 Set<ModuleSymbol> seen = new HashSet<>(); 1504 List<ModuleSymbol> todo = List.of(msym); 1505 1506 while (todo.nonEmpty()) { 1507 ModuleSymbol current = todo.head; 1508 todo = todo.tail; 1509 if (!seen.add(current)) 1510 continue; 1511 requiresTransitive.add(current); 1512 current.complete(); 1513 Iterable<? extends RequiresDirective> requires; 1514 if (current != syms.unnamedModule) { 1515 Assert.checkNonNull(current.requires, () -> current + ".requires == null; " + msym); 1516 requires = current.requires; 1517 for (RequiresDirective rd : requires) { 1518 if (rd.isTransitive()) 1519 todo = todo.prepend(rd.module); 1520 } 1521 } else { 1522 for (ModuleSymbol mod : allModules()) { 1523 todo = todo.prepend(mod); 1524 } 1525 } 1526 } 1527 1528 requiresTransitive.remove(msym); 1529 } 1530 1531 return requiresTransitive; 1532 } 1533 1534 private void initVisiblePackages(ModuleSymbol msym, Collection<ModuleSymbol> readable) { 1535 initAddExports(); 1536 1537 msym.visiblePackages = new LinkedHashMap<>(); 1538 msym.readModules = new HashSet<>(readable); 1539 1540 Map<Name, ModuleSymbol> seen = new HashMap<>(); 1541 1542 for (ModuleSymbol rm : readable) { 1543 if (rm == syms.unnamedModule) 1544 continue; 1545 addVisiblePackages(msym, seen, rm, rm.exports); 1546 } 1547 1548 addExports.forEach((exportsFrom, exports) -> { 1549 addVisiblePackages(msym, seen, exportsFrom, exports); 1550 }); 1551 } 1552 1553 private void addVisiblePackages(ModuleSymbol msym, 1554 Map<Name, ModuleSymbol> seenPackages, 1555 ModuleSymbol exportsFrom, 1556 Collection<ExportsDirective> exports) { 1557 for (ExportsDirective d : exports) { 1558 if (d.modules == null || d.modules.contains(msym)) { 1559 Name packageName = d.packge.fullname; 1560 ModuleSymbol previousModule = seenPackages.get(packageName); 1561 1562 if (previousModule != null && previousModule != exportsFrom) { 1563 Env<AttrContext> env = typeEnvs.get(msym); 1564 JavaFileObject origSource = env != null ? log.useSource(env.toplevel.sourcefile) 1565 : null; 1566 DiagnosticPosition pos = env != null ? env.tree.pos() : null; 1567 try { 1568 log.error(pos, Errors.PackageClashFromRequires(msym, packageName, 1569 previousModule, exportsFrom)); 1570 } finally { 1571 if (env != null) 1572 log.useSource(origSource); 1573 } 1574 continue; 1575 } 1576 1577 seenPackages.put(packageName, exportsFrom); 1578 msym.visiblePackages.put(d.packge.fullname, d.packge); 1579 } 1580 } 1581 } 1582 1583 private void initAddExports() { 1584 if (addExports != null) 1585 return; 1586 1587 addExports = new LinkedHashMap<>(); 1588 Set<ModuleSymbol> unknownModules = new HashSet<>(); 1589 1590 if (addExportsOpt == null) 1591 return; 1592 1593 Pattern ep = Pattern.compile("([^/]+)/([^=]+)=(.*)"); 1594 for (String s: addExportsOpt.split("\0+")) { 1595 if (s.isEmpty()) 1596 continue; 1597 Matcher em = ep.matcher(s); 1598 if (!em.matches()) { 1599 continue; 1600 } 1601 1602 // Terminology comes from 1603 // --add-exports module/package=target,... 1604 // Compare to 1605 // module module { exports package to target, ... } 1606 String moduleName = em.group(1); 1607 String packageName = em.group(2); 1608 String targetNames = em.group(3); 1609 1610 if (!isValidName(moduleName)) 1611 continue; 1612 1613 ModuleSymbol msym = syms.enterModule(names.fromString(moduleName)); 1614 if (!isKnownModule(msym, unknownModules)) 1615 continue; 1616 1617 if (!isValidName(packageName)) 1618 continue; 1619 1620 if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0) { 1621 log.error(Errors.AddExportsWithRelease(msym)); 1622 continue; 1623 } 1624 1625 PackageSymbol p = syms.enterPackage(msym, names.fromString(packageName)); 1626 p.modle = msym; // TODO: do we need this? 1627 1628 List<ModuleSymbol> targetModules = List.nil(); 1629 for (String toModule : targetNames.split("[ ,]+")) { 1630 ModuleSymbol m; 1631 if (toModule.equals("ALL-UNNAMED")) { 1632 m = syms.unnamedModule; 1633 } else { 1634 if (!isValidName(toModule)) 1635 continue; 1636 m = syms.enterModule(names.fromString(toModule)); 1637 if (!isKnownModule(m, unknownModules)) 1638 continue; 1639 } 1640 targetModules = targetModules.prepend(m); 1641 } 1642 1643 Set<ExportsDirective> extra = addExports.computeIfAbsent(msym, _x -> new LinkedHashSet<>()); 1644 ExportsDirective d = new ExportsDirective(p, targetModules); 1645 extra.add(d); 1646 } 1647 } 1648 1649 private boolean isKnownModule(ModuleSymbol msym, Set<ModuleSymbol> unknownModules) { 1650 if (allModules.contains(msym)) { 1651 return true; 1652 } 1653 1654 if (!unknownModules.contains(msym)) { 1655 if (lintOptions) { 1656 log.warning(LintCategory.OPTIONS, 1657 Warnings.ModuleForOptionNotFound(Option.ADD_EXPORTS, msym)); 1658 } 1659 unknownModules.add(msym); 1660 } 1661 return false; 1662 } 1663 1664 private void initAddReads() { 1665 if (addReads != null) 1666 return; 1667 1668 addReads = new LinkedHashMap<>(); 1669 1670 if (addReadsOpt == null) 1671 return; 1672 1673 Pattern rp = Pattern.compile("([^=]+)=(.*)"); 1674 for (String s : addReadsOpt.split("\0+")) { 1675 if (s.isEmpty()) 1676 continue; 1677 Matcher rm = rp.matcher(s); 1678 if (!rm.matches()) { 1679 continue; 1680 } 1681 1682 // Terminology comes from 1683 // --add-reads source-module=target-module,... 1684 // Compare to 1685 // module source-module { requires target-module; ... } 1686 String sourceName = rm.group(1); 1687 String targetNames = rm.group(2); 1688 1689 if (!isValidName(sourceName)) 1690 continue; 1691 1692 ModuleSymbol msym = syms.enterModule(names.fromString(sourceName)); 1693 if (!allModules.contains(msym)) { 1694 if (lintOptions) { 1695 log.warning(Warnings.ModuleForOptionNotFound(Option.ADD_READS, msym)); 1696 } 1697 continue; 1698 } 1699 1700 if (!allowAccessIntoSystem && (msym.flags() & Flags.SYSTEM_MODULE) != 0) { 1701 log.error(Errors.AddReadsWithRelease(msym)); 1702 continue; 1703 } 1704 1705 for (String targetName : targetNames.split("[ ,]+", -1)) { 1706 ModuleSymbol targetModule; 1707 if (targetName.equals("ALL-UNNAMED")) { 1708 targetModule = syms.unnamedModule; 1709 } else { 1710 if (!isValidName(targetName)) 1711 continue; 1712 targetModule = syms.enterModule(names.fromString(targetName)); 1713 if (!allModules.contains(targetModule)) { 1714 if (lintOptions) { 1715 log.warning(LintCategory.OPTIONS, Warnings.ModuleForOptionNotFound(Option.ADD_READS, targetModule)); 1716 } 1717 continue; 1718 } 1719 } 1720 addReads.computeIfAbsent(msym, m -> new HashSet<>()) 1721 .add(new RequiresDirective(targetModule, EnumSet.of(RequiresFlag.EXTRA))); 1722 } 1723 } 1724 } 1725 1726 private void checkCyclicDependencies(JCModuleDecl mod) { 1727 for (JCDirective d : mod.directives) { 1728 JCRequires rd; 1729 if (!d.hasTag(Tag.REQUIRES) || (rd = (JCRequires) d).directive == null) 1730 continue; 1731 Set<ModuleSymbol> nonSyntheticDeps = new HashSet<>(); 1732 List<ModuleSymbol> queue = List.of(rd.directive.module); 1733 while (queue.nonEmpty()) { 1734 ModuleSymbol current = queue.head; 1735 queue = queue.tail; 1736 if (!nonSyntheticDeps.add(current)) 1737 continue; 1738 current.complete(); 1739 if ((current.flags() & Flags.ACYCLIC) != 0) 1740 continue; 1741 Assert.checkNonNull(current.requires, current::toString); 1742 for (RequiresDirective dep : current.requires) { 1743 if (!dep.flags.contains(RequiresFlag.EXTRA)) 1744 queue = queue.prepend(dep.module); 1745 } 1746 } 1747 if (nonSyntheticDeps.contains(mod.sym)) { 1748 log.error(rd.moduleName.pos(), Errors.CyclicRequires(rd.directive.module)); 1749 } 1750 mod.sym.flags_field |= Flags.ACYCLIC; 1751 } 1752 } 1753 1754 private boolean isValidName(CharSequence name) { 1755 return SourceVersion.isName(name, Source.toSourceVersion(source)); 1756 } 1757 1758 // DEBUG 1759 private String toString(ModuleSymbol msym) { 1760 return msym.name + "[" 1761 + "kind:" + msym.kind + ";" 1762 + "locn:" + toString(msym.sourceLocation) + "," + toString(msym.classLocation) + ";" 1763 + "info:" + toString(msym.module_info.sourcefile) + "," 1764 + toString(msym.module_info.classfile) + "," 1765 + msym.module_info.completer 1766 + "]"; 1767 } 1768 1769 // DEBUG 1770 String toString(Location locn) { 1771 return (locn == null) ? "--" : locn.getName(); 1772 } 1773 1774 // DEBUG 1775 String toString(JavaFileObject fo) { 1776 return (fo == null) ? "--" : fo.getName(); 1777 } 1778 1779 public void newRound() { 1780 allModules = null; 1781 rootModules = null; 1782 warnedMissing.clear(); 1783 } 1784 1785 public interface PackageNameFinder { 1786 public Name findPackageNameOf(JavaFileObject jfo); 1787 } 1788} 1789