8159220: Preserve position info in module import and export entries
authorhannesw
Mon, 13 Jun 2016 12:39:28 +0200
changeset 38901 28e775c6e08e
parent 38900 35214991a264
child 38902 88485e91143a
8159220: Preserve position info in module import and export entries Reviewed-by: sundar, lagergren
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java
nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java	Thu Jun 09 19:07:12 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Module.java	Mon Jun 13 12:39:28 2016 +0200
@@ -47,45 +47,48 @@
      * @see <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records">es6 modules</a>
      */
     public static final class ExportEntry {
-        private final String exportName;
-        private final String moduleRequest;
-        private final String importName;
-        private final String localName;
+        private final IdentNode exportName;
+        private final IdentNode moduleRequest;
+        private final IdentNode importName;
+        private final IdentNode localName;
 
-        private ExportEntry(final String exportName, final String moduleRequest, final String importName, final String localName) {
+        private final int startPosition;
+        private final int endPosition;
+
+        private ExportEntry(final IdentNode exportName, final IdentNode moduleRequest, final IdentNode importName,
+                            final IdentNode localName, final int startPosition, final int endPosition) {
             this.exportName = exportName;
             this.moduleRequest = moduleRequest;
             this.importName = importName;
             this.localName = localName;
+            this.startPosition = startPosition;
+            this.endPosition = endPosition;
         }
 
         /**
          * Creates a {@code export *} export entry.
          *
+         * @param starName the star name
          * @param moduleRequest the module request
+         * @param startPosition the start position
+         * @param endPosition the end position
          * @return the export entry
          */
-        public static ExportEntry exportStarFrom(final String moduleRequest) {
-            return new ExportEntry(null, moduleRequest, STAR_NAME, null);
-        }
-
-        /**
-         * Creates a {@code export default} export entry.
-         *
-         * @return the export entry
-         */
-        public static ExportEntry exportDefault() {
-            return exportDefault(DEFAULT_EXPORT_BINDING_NAME);
+        public static ExportEntry exportStarFrom(final IdentNode starName, final IdentNode moduleRequest, final int startPosition, final int endPosition) {
+            return new ExportEntry(null, moduleRequest, starName, null, startPosition, endPosition);
         }
 
         /**
          * Creates a {@code export default} export entry with a local name.
          *
+         * @param defaultName the default name
          * @param localName the local name
+         * @param startPosition the start position
+         * @param endPosition the end position
          * @return the export entry
          */
-        public static ExportEntry exportDefault(final String localName) {
-            return new ExportEntry(DEFAULT_NAME, null, null, localName);
+        public static ExportEntry exportDefault(final IdentNode defaultName, final IdentNode localName, final int startPosition, final int endPosition) {
+            return new ExportEntry(defaultName, null, null, localName, startPosition, endPosition);
         }
 
         /**
@@ -93,30 +96,37 @@
          *
          * @param exportName the export name
          * @param localName the local name
+         * @param startPosition the start position
+         * @param endPosition the end position
          * @return the export entry
          */
-        public static ExportEntry exportSpecifier(final String exportName, final String localName) {
-            return new ExportEntry(exportName, null, null, localName);
+        public static ExportEntry exportSpecifier(final IdentNode exportName, final IdentNode localName, final int startPosition, final int endPosition) {
+            return new ExportEntry(exportName, null, null, localName, startPosition, endPosition);
         }
 
+
         /**
          * Creates a export entry with an export name.
          *
          * @param exportName the export name
+         * @param startPosition the start position
+         * @param endPosition the end position
          * @return the export entry
          */
-        public static ExportEntry exportSpecifier(final String exportName) {
-            return exportSpecifier(exportName, exportName);
+        public static ExportEntry exportSpecifier(final IdentNode exportName, final int startPosition, final int endPosition) {
+            return exportSpecifier(exportName, exportName, startPosition, endPosition);
         }
 
         /**
          * Create a copy of this entry with the specified {@code module request} string.
          *
          * @param moduleRequest the module request
+         * @param endPosition the new endPosition
          * @return the new export entry
          */
-        public ExportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
-            return new ExportEntry(exportName, moduleRequest, localName, null);
+        public ExportEntry withFrom(@SuppressWarnings("hiding") final IdentNode moduleRequest, final int endPosition) {
+            // Note that "from" moves localName to inputName, and localName becomes null
+            return new ExportEntry(exportName, moduleRequest, localName, null, startPosition, endPosition);
         }
 
         /**
@@ -124,7 +134,7 @@
          *
          * @return the export name
          */
-        public String getExportName() {
+        public IdentNode getExportName() {
             return exportName;
         }
 
@@ -133,7 +143,7 @@
          *
          * @return the module request
          */
-        public String getModuleRequest() {
+        public IdentNode getModuleRequest() {
             return moduleRequest;
         }
 
@@ -142,7 +152,7 @@
          *
          * @return the import name
          */
-        public String getImportName() {
+        public IdentNode getImportName() {
             return importName;
         }
 
@@ -151,10 +161,28 @@
          *
          * @return the local name
          */
-        public String getLocalName() {
+        public IdentNode getLocalName() {
             return localName;
         }
 
+        /**
+         * Returns the entry's start position.
+         *
+         * @return the start position
+         */
+        public int getStartPosition() {
+            return startPosition;
+        }
+
+        /**
+         * Returns the entry's end position.
+         *
+         * @return the end position
+         */
+        public int getEndPosition() {
+            return endPosition;
+        }
+
         @Override
         public String toString() {
             return "ExportEntry [exportName=" + exportName + ", moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
@@ -167,34 +195,20 @@
      * @see <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records">es6 modules</a>
      */
     public static final class ImportEntry {
-        private final String moduleRequest;
-        private final String importName;
-        private final String localName;
+        private final IdentNode moduleRequest;
+        private final IdentNode importName;
+        private final IdentNode localName;
 
-        private ImportEntry(final String moduleRequest, final String importName, final String localName) {
+        private final int startPosition;
+        private final int endPosition;
+
+        private ImportEntry(final IdentNode moduleRequest, final IdentNode importName, final IdentNode localName,
+                            final int startPosition, final int endPosition) {
             this.moduleRequest = moduleRequest;
             this.importName = importName;
             this.localName = localName;
-        }
-
-        /**
-         * Creates an import entry with default name.
-         *
-         * @param localName the local name
-         * @return the import entry
-         */
-        public static ImportEntry importDefault(final String localName) {
-            return new ImportEntry(null, DEFAULT_NAME, localName);
-        }
-
-        /**
-         * Creates an import entry with {@code *} import name.
-         *
-         * @param localName the local name
-         * @return the import entry
-         */
-        public static ImportEntry importStarAsNameSpaceFrom(final String localName) {
-            return new ImportEntry(null, STAR_NAME, localName);
+            this.startPosition = startPosition;
+            this.endPosition = endPosition;
         }
 
         /**
@@ -202,30 +216,35 @@
          *
          * @param importName the import name
          * @param localName the local name
+         * @param startPosition the start position
+         * @param endPosition the end position
          * @return the import entry
          */
-        public static ImportEntry importSpecifier(final String importName, final String localName) {
-            return new ImportEntry(null, importName, localName);
+        public static ImportEntry importSpecifier(final IdentNode importName, final IdentNode localName, final int startPosition, final int endPosition) {
+            return new ImportEntry(null, importName, localName, startPosition, endPosition);
         }
 
         /**
          * Creates a new import entry with the given import name.
          *
          * @param importName the import name
+         * @param startPosition the start position
+         * @param endPosition the end position
          * @return the import entry
          */
-        public static ImportEntry importSpecifier(final String importName) {
-            return importSpecifier(importName, importName);
+        public static ImportEntry importSpecifier(final IdentNode importName, final int startPosition, final int endPosition) {
+            return importSpecifier(importName, importName, startPosition, endPosition);
         }
 
         /**
-         * Returns a copy of this import entry with the given module request.
+         * Returns a copy of this import entry with the given module request and end position.
          *
          * @param moduleRequest the module request
+         * @param endPosition the new end position
          * @return the new import entry
          */
-        public ImportEntry withFrom(@SuppressWarnings("hiding") final String moduleRequest) {
-            return new ImportEntry(moduleRequest, importName, localName);
+        public ImportEntry withFrom(@SuppressWarnings("hiding") final IdentNode moduleRequest, final int endPosition) {
+            return new ImportEntry(moduleRequest, importName, localName, startPosition, endPosition);
         }
 
         /**
@@ -233,7 +252,7 @@
          *
          * @return the module request
          */
-        public String getModuleRequest() {
+        public IdentNode getModuleRequest() {
             return moduleRequest;
         }
 
@@ -242,7 +261,7 @@
          *
          * @return the import name
          */
-        public String getImportName() {
+        public IdentNode getImportName() {
             return importName;
         }
 
@@ -251,10 +270,28 @@
          *
          * @return the local name
          */
-        public String getLocalName() {
+        public IdentNode getLocalName() {
             return localName;
         }
 
+        /**
+         * Returns the entry's start position.
+         *
+         * @return the start position
+         */
+        public int getStartPosition() {
+            return startPosition;
+        }
+
+        /**
+         * Returns the entry's end position.
+         *
+         * @return the end position
+         */
+        public int getEndPosition() {
+            return endPosition;
+        }
+
         @Override
         public String toString() {
             return "ImportEntry [moduleRequest=" + moduleRequest + ", importName=" + importName + ", localName=" + localName + "]";
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Thu Jun 09 19:07:12 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Mon Jun 13 12:39:28 2016 +0200
@@ -5138,32 +5138,33 @@
      *     BindingIdentifier
      */
     private void importDeclaration() {
+        final int startPosition = start;
         expect(IMPORT);
         final ParserContextModuleNode module = lc.getCurrentModule();
         if (type == STRING || type == ESCSTRING) {
             // import ModuleSpecifier ;
-            final String moduleSpecifier = (String) getValue();
+            final IdentNode moduleSpecifier = createIdentNode(token, finish, (String) getValue());
             next();
             module.addModuleRequest(moduleSpecifier);
         } else {
             // import ImportClause FromClause ;
             List<Module.ImportEntry> importEntries;
             if (type == MUL) {
-                importEntries = Collections.singletonList(nameSpaceImport());
+                importEntries = Collections.singletonList(nameSpaceImport(startPosition));
             } else if (type == LBRACE) {
-                importEntries = namedImports();
+                importEntries = namedImports(startPosition);
             } else if (isBindingIdentifier()) {
                 // ImportedDefaultBinding
                 final IdentNode importedDefaultBinding = bindingIdentifier("ImportedBinding");
-                Module.ImportEntry defaultImport = Module.ImportEntry.importDefault(importedDefaultBinding.getName());
+                Module.ImportEntry defaultImport = Module.ImportEntry.importSpecifier(importedDefaultBinding, startPosition, finish);
 
                 if (type == COMMARIGHT) {
                     next();
                     importEntries = new ArrayList<>();
                     if (type == MUL) {
-                        importEntries.add(nameSpaceImport());
+                        importEntries.add(nameSpaceImport(startPosition));
                     } else if (type == LBRACE) {
-                        importEntries.addAll(namedImports());
+                        importEntries.addAll(namedImports(startPosition));
                     } else {
                         throw error(AbstractParser.message("expected.named.import"));
                     }
@@ -5174,10 +5175,10 @@
                 throw error(AbstractParser.message("expected.import"));
             }
 
-            final String moduleSpecifier = fromClause();
+            final IdentNode moduleSpecifier = fromClause();
             module.addModuleRequest(moduleSpecifier);
             for (int i = 0; i < importEntries.size(); i++) {
-                module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier));
+                module.addImportEntry(importEntries.get(i).withFrom(moduleSpecifier, finish));
             }
         }
         expect(SEMICOLON);
@@ -5187,10 +5188,12 @@
      * NameSpaceImport :
      *     * as ImportedBinding
      *
+     * @param startPosition the start of the import declaration
      * @return imported binding identifier
      */
-    private Module.ImportEntry nameSpaceImport() {
+    private Module.ImportEntry nameSpaceImport(final int startPosition) {
         assert type == MUL;
+        final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
         next();
         final long asToken = token;
         final String as = (String) expectValue(IDENT);
@@ -5198,7 +5201,7 @@
             throw error(AbstractParser.message("expected.as"), asToken);
         }
         final IdentNode localNameSpace = bindingIdentifier("ImportedBinding");
-        return Module.ImportEntry.importStarAsNameSpaceFrom(localNameSpace.getName());
+        return Module.ImportEntry.importSpecifier(starName, localNameSpace, startPosition, finish);
     }
 
     /**
@@ -5215,7 +5218,7 @@
      * ImportedBinding :
      *     BindingIdentifier
      */
-    private List<Module.ImportEntry> namedImports() {
+    private List<Module.ImportEntry> namedImports(final int startPosition) {
         assert type == LBRACE;
         next();
         List<Module.ImportEntry> importEntries = new ArrayList<>();
@@ -5226,11 +5229,11 @@
             if (type == IDENT && "as".equals(getValue())) {
                 next();
                 final IdentNode localName = bindingIdentifier("ImportedBinding");
-                importEntries.add(Module.ImportEntry.importSpecifier(importName.getName(), localName.getName()));
+                importEntries.add(Module.ImportEntry.importSpecifier(importName, localName, startPosition, finish));
             } else if (!bindingIdentifier) {
                 throw error(AbstractParser.message("expected.binding.identifier"), nameToken);
             } else {
-                importEntries.add(Module.ImportEntry.importSpecifier(importName.getName()));
+                importEntries.add(Module.ImportEntry.importSpecifier(importName, startPosition, finish));
             }
             if (type == COMMARIGHT) {
                 next();
@@ -5246,14 +5249,14 @@
      * FromClause :
      *     from ModuleSpecifier
      */
-    private String fromClause() {
+    private IdentNode fromClause() {
         final long fromToken = token;
         final String name = (String) expectValue(IDENT);
         if (!"from".equals(name)) {
             throw error(AbstractParser.message("expected.from"), fromToken);
         }
         if (type == STRING || type == ESCSTRING) {
-            final String moduleSpecifier = (String) getValue();
+            final IdentNode moduleSpecifier = createIdentNode(Token.recast(token, IDENT), finish, (String) getValue());
             next();
             return moduleSpecifier;
         } else {
@@ -5276,23 +5279,25 @@
      */
     private void exportDeclaration() {
         expect(EXPORT);
+        final int startPosition = start;
         final ParserContextModuleNode module = lc.getCurrentModule();
         switch (type) {
             case MUL: {
+                final IdentNode starName = createIdentNode(Token.recast(token, IDENT), finish, Module.STAR_NAME);
                 next();
-                final String moduleRequest = fromClause();
+                final IdentNode moduleRequest = fromClause();
                 expect(SEMICOLON);
                 module.addModuleRequest(moduleRequest);
-                module.addStarExportEntry(Module.ExportEntry.exportStarFrom(moduleRequest));
+                module.addStarExportEntry(Module.ExportEntry.exportStarFrom(starName, moduleRequest, startPosition, finish));
                 break;
             }
             case LBRACE: {
-                final List<Module.ExportEntry> exportEntries = exportClause();
+                final List<Module.ExportEntry> exportEntries = exportClause(startPosition);
                 if (type == IDENT && "from".equals(getValue())) {
-                    final String moduleRequest = fromClause();
+                    final IdentNode moduleRequest = fromClause();
                     module.addModuleRequest(moduleRequest);
                     for (Module.ExportEntry exportEntry : exportEntries) {
-                        module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest));
+                        module.addIndirectExportEntry(exportEntry.withFrom(moduleRequest, finish));
                     }
                 } else {
                     for (Module.ExportEntry exportEntry : exportEntries) {
@@ -5303,6 +5308,7 @@
                 break;
             }
             case DEFAULT:
+                final IdentNode defaultName = createIdentNode(Token.recast(token, IDENT), finish, Module.DEFAULT_NAME);
                 next();
                 final Expression assignmentExpression;
                 IdentNode ident;
@@ -5327,14 +5333,14 @@
                         break;
                 }
                 if (ident != null) {
-                    module.addLocalExportEntry(Module.ExportEntry.exportDefault(ident.getName()));
+                    module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
                 } else {
                     ident = createIdentNode(Token.recast(rhsToken, IDENT), finish, Module.DEFAULT_EXPORT_BINDING_NAME);
                     lc.appendStatementToCurrentNode(new VarNode(lineNumber, Token.recast(rhsToken, LET), finish, ident, assignmentExpression));
                     if (!declaration) {
                         expect(SEMICOLON);
                     }
-                    module.addLocalExportEntry(Module.ExportEntry.exportDefault());
+                    module.addLocalExportEntry(Module.ExportEntry.exportDefault(defaultName, ident, startPosition, finish));
                 }
                 break;
             case VAR:
@@ -5345,18 +5351,18 @@
                 variableStatement(type);
                 for (final Statement statement : statements.subList(previousEnd, statements.size())) {
                     if (statement instanceof VarNode) {
-                        module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName().getName()));
+                        module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(((VarNode) statement).getName(), startPosition, finish));
                     }
                 }
                 break;
             case CLASS: {
                 final ClassNode classDeclaration = classDeclaration(false);
-                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent().getName()));
+                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(classDeclaration.getIdent(), startPosition, finish));
                 break;
             }
             case FUNCTION: {
                 final FunctionNode functionDeclaration = (FunctionNode) functionExpression(true, true);
-                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent().getName()));
+                module.addLocalExportEntry(Module.ExportEntry.exportSpecifier(functionDeclaration.getIdent(), startPosition, finish));
                 break;
             }
             default:
@@ -5378,7 +5384,7 @@
      *
      * @return a list of ExportSpecifiers
      */
-    private List<Module.ExportEntry> exportClause() {
+    private List<Module.ExportEntry> exportClause(final int startPosition) {
         assert type == LBRACE;
         next();
         List<Module.ExportEntry> exports = new ArrayList<>();
@@ -5387,9 +5393,9 @@
             if (type == IDENT && "as".equals(getValue())) {
                 next();
                 final IdentNode exportName = getIdentifierName();
-                exports.add(Module.ExportEntry.exportSpecifier(exportName.getName(), localName.getName()));
+                exports.add(Module.ExportEntry.exportSpecifier(exportName, localName, startPosition, finish));
             } else {
-                exports.add(Module.ExportEntry.exportSpecifier(localName.getName()));
+                exports.add(Module.ExportEntry.exportSpecifier(localName, startPosition, finish));
             }
             if (type == COMMARIGHT) {
                 next();
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java	Thu Jun 09 19:07:12 2016 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextModuleNode.java	Mon Jun 13 12:39:28 2016 +0200
@@ -28,6 +28,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.Module;
 import jdk.nashorn.internal.ir.Module.ExportEntry;
 import jdk.nashorn.internal.ir.Module.ImportEntry;
@@ -64,8 +65,8 @@
         return name;
     }
 
-    public void addModuleRequest(final String moduleRequest) {
-        requestedModules.add(moduleRequest);
+    public void addModuleRequest(final IdentNode moduleRequest) {
+        requestedModules.add(moduleRequest.getName());
     }
 
     public void addImportEntry(final ImportEntry importEntry) {