1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.ir;
  27 
  28 import java.util.List;
  29 
  30 /**
  31  * ES6 Module information.
  32  */
  33 public final class Module {
  34 
  35     /** The synthetic binding name assigned to export default declarations with unnamed expressions. */
  36     public static final String DEFAULT_EXPORT_BINDING_NAME = "*default*";
  37 
  38     /** The {@code export default} name. */
  39     public static final String DEFAULT_NAME = "default";
  40 
  41     /** The {@code export *} name. */
  42     public static final String STAR_NAME = "*";
  43 
  44     /**
  45      * A module ExportEntry record.
  46      *
  47      * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
  48      */
  49     public static final class ExportEntry {
  50         private final String exportName;
  51         private final String moduleRequest;
  52         private final String importName;
  53         private final String localName;
  54 
  55         private ExportEntry(final String exportName, final String moduleRequest, final String importName, final String localName) {
  56             this.exportName = exportName;
  57             this.moduleRequest = moduleRequest;
  58             this.importName = importName;
  59             this.localName = localName;
  60         }
  61 
  62         /**
  63          * Creates a {@code export *} export entry.
  64          *
  65          * @param moduleRequest the module request
  66          * @return the export entry
  67          */
  68         public static ExportEntry exportStarFrom(final String moduleRequest) {
  69             return new ExportEntry(null, moduleRequest, STAR_NAME, null);
  70         }
  71 
  72         /**
  73          * Creates a {@code export default} export entry.
  74          *
  75          * @return the export entry
  76          */
  77         public static ExportEntry exportDefault() {
  78             return exportDefault(DEFAULT_EXPORT_BINDING_NAME);
  79         }
  80 
  81         /**
  82          * Creates a {@code export default} export entry with a local name.
  83          *
  84          * @param localName the local name
  85          * @return the export entry
  86          */
  87         public static ExportEntry exportDefault(final String localName) {
  88             return new ExportEntry(DEFAULT_NAME, null, null, localName);
  89         }
  90 
  91         /**
  92          * Creates a export entry with a local name and export name.
  93          *
  94          * @param exportName the export name
  95          * @param localName the local name
  96          * @return the export entry
  97          */
  98         public static ExportEntry exportSpecifier(final String exportName, final String localName) {
  99             return new ExportEntry(exportName, null, null, localName);
 100         }
 101 
 102         /**
 103          * Creates a export entry with an export name.
 104          *
 105          * @param exportName the export name
 106          * @return the export entry
 107          */
 108         public static ExportEntry exportSpecifier(final String exportName) {
 109             return exportSpecifier(exportName, exportName);
 110         }
 111 
 112         /**
 113          * Create a copy of this entry with the specified {@code module request} string.
 114          *
 115          * @param moduleRequest the module request
 116          * @return the new export entry
 117          */
 118         public ExportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
 119             return new ExportEntry(exportName, moduleRequest, localName, null);
 120         }
 121 
 122         /**
 123          * Returns the entry's export name.
 124          *
 125          * @return the export name
 126          */
 127         public String getExportName() {
 128             return exportName;
 129         }
 130 
 131         /**
 132          * Returns the entry's module request.
 133          *
 134          * @return the module request
 135          */
 136         public String getModuleRequest() {
 137             return moduleRequest;
 138         }
 139 
 140         /**
 141          * Returns the entry's import name.
 142          *
 143          * @return the import name
 144          */
 145         public String getImportName() {
 146             return importName;
 147         }
 148 
 149         /**
 150          * Returns the entry's local name.
 151          *
 152          * @return the local name
 153          */
 154         public String getLocalName() {
 155             return localName;
 156         }
 157 
 158         @Override
 159         public String toString() {
 160             return "ExportEntry [exportName=" + exportName + ", moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
 161         }
 162     }
 163 
 164     /**
 165      * An ImportEntry record.
 166      *
 167      * @link http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
 168      */
 169     public static final class ImportEntry {
 170         private final String moduleRequest;
 171         private final String importName;
 172         private final String localName;
 173 
 174         private ImportEntry(final String moduleRequest, final String importName, final String localName) {
 175             this.moduleRequest = moduleRequest;
 176             this.importName = importName;
 177             this.localName = localName;
 178         }
 179 
 180         /**
 181          * Creates an import entry with default name.
 182          *
 183          * @param localName the local name
 184          * @return the import entry
 185          */
 186         public static ImportEntry importDefault(final String localName) {
 187             return new ImportEntry(null, DEFAULT_NAME, localName);
 188         }
 189 
 190         /**
 191          * Creates an import entry with {@code *} import name.
 192          *
 193          * @param localName the local name
 194          * @return the import entry
 195          */
 196         public static ImportEntry importStarAsNameSpaceFrom(final String localName) {
 197             return new ImportEntry(null, STAR_NAME, localName);
 198         }
 199 
 200         /**
 201          * Creates an import entry with the given import and local names.
 202          *
 203          * @param importName the import name
 204          * @param localName the local name
 205          * @return the import entry
 206          */
 207         public static ImportEntry importSpecifier(final String importName, final String localName) {
 208             return new ImportEntry(null, importName, localName);
 209         }
 210 
 211         /**
 212          * Creates a new import entry with the given import name.
 213          *
 214          * @param importName the import name
 215          * @return the import entry
 216          */
 217         public static ImportEntry importSpecifier(final String importName) {
 218             return importSpecifier(importName, importName);
 219         }
 220 
 221         /**
 222          * Returns a copy of this import entry with the given module request.
 223          *
 224          * @param moduleRequest the module request
 225          * @return the new import entry
 226          */
 227         public ImportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
 228             return new ImportEntry(moduleRequest, importName, localName);
 229         }
 230 
 231         /**
 232          * Returns the entry's module request.
 233          *
 234          * @return the module request
 235          */
 236         public String getModuleRequest() {
 237             return moduleRequest;
 238         }
 239 
 240         /**
 241          * Returns the entry's import name.
 242          *
 243          * @return the import name
 244          */
 245         public String getImportName() {
 246             return importName;
 247         }
 248 
 249         /**
 250          * Returns the entry's local name.
 251          *
 252          * @return the local name
 253          */
 254         public String getLocalName() {
 255             return localName;
 256         }
 257 
 258         @Override
 259         public String toString() {
 260             return "ImportEntry [moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
 261         }
 262     }
 263 
 264     private final List<String> requestedModules;
 265     private final List<ImportEntry> importEntries;
 266     private final List<ExportEntry> localExportEntries;
 267     private final List<ExportEntry> indirectExportEntries;
 268     private final List<ExportEntry> starExportEntries;
 269 
 270     /**
 271      * Creates a module with the specified requested modules and import and export entries.
 272      *
 273      * @param requestedModules the requested modules
 274      * @param importEntries the import entries
 275      * @param localExportEntries local export entries
 276      * @param indirectExportEntries indirect export entries
 277      * @param starExportEntries star export entries
 278      */
 279     public Module(final List<String> requestedModules, final List<ImportEntry> importEntries, final List<ExportEntry> localExportEntries,
 280                   final List<ExportEntry> indirectExportEntries, final List<ExportEntry> starExportEntries) {
 281         this.requestedModules = requestedModules;
 282         this.importEntries = importEntries;
 283         this.localExportEntries = localExportEntries;
 284         this.indirectExportEntries = indirectExportEntries;
 285         this.starExportEntries = starExportEntries;
 286     }
 287 
 288     /**
 289      * Returns the list of requested modules.
 290      *
 291      * @return the requested modules
 292      */
 293     public List<String> getRequestedModules() {
 294         return requestedModules;
 295     }
 296 
 297     /**
 298      * Returns the list of import entries.
 299      *
 300      * @return the import entries
 301      */
 302     public List<ImportEntry> getImportEntries() {
 303         return importEntries;
 304     }
 305 
 306     /**
 307      * Returns the list of local export entries.
 308      *
 309      * @return the local export entries
 310      */
 311     public List<ExportEntry> getLocalExportEntries() {
 312         return localExportEntries;
 313     }
 314 
 315     /**
 316      * Returns the list of indirect export entries.
 317      *
 318      * @return the indirect export entries
 319      */
 320     public List<ExportEntry> getIndirectExportEntries() {
 321         return indirectExportEntries;
 322     }
 323 
 324     /**
 325      * Returns the list of star export entries.
 326      *
 327      * @return the star export entries
 328      */
 329     public List<ExportEntry> getStarExportEntries() {
 330         return starExportEntries;
 331     }
 332 
 333     @Override
 334     public String toString() {
 335         return "Module [requestedModules=" + requestedModules + ", importEntries=" + importEntries + ", localExportEntries=" + localExportEntries + ", indirectExportEntries=" +
 336                 indirectExportEntries + ", starExportEntries=" + starExportEntries + "]";
 337     }
 338 }