8159220: Preserve position info in module import and export entries
Reviewed-by: sundar, lagergren
--- 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) {