8020437: Wrong handling of line numbers with multiline string literals
authorsundar
Fri, 12 Jul 2013 15:01:33 +0530
changeset 18870 aa4fceda2fba
parent 18869 b8ddb7296bae
child 18871 a27c6a5b999c
8020437: Wrong handling of line numbers with multiline string literals Reviewed-by: attila, lagergren
nashorn/src/jdk/nashorn/internal/parser/Lexer.java
nashorn/src/jdk/nashorn/internal/parser/Parser.java
nashorn/test/script/basic/JDK-8020437.js
nashorn/test/script/basic/JDK-8020437.js.EXPECTED
nashorn/test/script/error/JDK-8020437-2.js
nashorn/test/script/error/JDK-8020437-2.js.EXPECTED
nashorn/test/script/error/JDK-8020437.js
nashorn/test/script/error/JDK-8020437.js.EXPECTED
--- a/nashorn/src/jdk/nashorn/internal/parser/Lexer.java	Thu Jul 11 22:01:55 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/parser/Lexer.java	Fri Jul 12 15:01:33 2013 +0530
@@ -546,14 +546,27 @@
     }
 
     /**
+     * interface to receive line information for multi-line literals.
+     */
+    protected interface LineInfoReceiver {
+        /**
+         * Receives line information
+         * @param line last line number
+         * @param linePosition position of last line
+         */
+        public void lineInfo(int line, int linePosition);
+    }
+
+    /**
      * Check whether the given token represents the beginning of a literal. If so scan
      * the literal and return <tt>true</tt>, otherwise return false.
      *
      * @param token the token.
      * @param startTokenType the token type.
+     * @parasm lir LineInfoReceiver that receives line info for multi-line string literals.
      * @return True if a literal beginning with startToken was found and scanned.
      */
-    protected boolean scanLiteral(final long token, final TokenType startTokenType) {
+    protected boolean scanLiteral(final long token, final TokenType startTokenType, final LineInfoReceiver lir) {
         // Check if it can be a literal.
         if (!canStartLiteral(startTokenType)) {
             return false;
@@ -569,7 +582,7 @@
             return scanRegEx();
         } else if (ch0 == '<') {
             if (ch1 == '<') {
-                return scanHereString();
+                return scanHereString(lir);
             } else if (Character.isJavaIdentifierStart(ch1)) {
                 return scanXMLLiteral();
             }
@@ -1417,7 +1430,7 @@
      *
      * @return TRUE if is a here string.
      */
-    private boolean scanHereString() {
+    private boolean scanHereString(final LineInfoReceiver lir) {
         assert ch0 == '<' && ch1 == '<';
         if (scripting) {
             // Record beginning of here string.
@@ -1446,7 +1459,13 @@
 
             // Record rest of line.
             final State restState = saveState();
+            // keep line number updated
+            int lastLine = line;
+            int lastLinePosition = linePosition;
+
             skipLine(false);
+            lastLine++;
+            lastLinePosition = position;
             restState.setLimit(position);
 
             // Record beginning of string.
@@ -1463,9 +1482,14 @@
                 }
 
                 skipLine(false);
+                lastLine++;
+                lastLinePosition = position;
                 stringEnd = position;
             }
 
+            // notify last line information
+            lir.lineInfo(lastLine, lastLinePosition);
+
             // Record end of string.
             stringState.setLimit(stringEnd);
 
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Thu Jul 11 22:01:55 2013 +0200
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java	Fri Jul 12 15:01:33 2013 +0530
@@ -130,6 +130,9 @@
 
     private static final DebugLogger LOG = new DebugLogger("parser");
 
+    /** to receive line information from Lexer when scanning multine literals. */
+    protected final Lexer.LineInfoReceiver lineInfoReceiver;
+
     /**
      * Constructor
      *
@@ -154,6 +157,19 @@
         this.env       = env;
         this.namespace = new Namespace(env.getNamespace());
         this.scripting = env._scripting;
+        if (this.scripting) {
+            this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
+                @Override
+                public void lineInfo(final int line, final int linePosition) {
+                    // update the parser maintained line information
+                    Parser.this.line = line;
+                    Parser.this.linePosition = linePosition;
+                }
+            };
+        } else {
+            // non-scripting mode script can't have multi-line literals
+            this.lineInfoReceiver = null;
+        }
     }
 
     /**
@@ -1802,7 +1818,7 @@
 
         default:
             // In this context some operator tokens mark the start of a literal.
-            if (lexer.scanLiteral(primaryToken, type)) {
+            if (lexer.scanLiteral(primaryToken, type, lineInfoReceiver)) {
                 next();
                 return getLiteral();
             }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8020437.js	Fri Jul 12 15:01:33 2013 +0530
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8020437: Wrong handling of line numbers with multiline string literals
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+print({
+   text: <<EOF
+This is a multiple line
+text inside a sting literal.
+Run this with -scripting option.
+EOF}); f();
+
+function f() {
+   try {
+       func();
+   } catch (e) {
+       print(e.stack.replace(/\\/g, '/'));
+   }
+}
+
+function func() {
+    throw new Error();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/basic/JDK-8020437.js.EXPECTED	Fri Jul 12 15:01:33 2013 +0530
@@ -0,0 +1,5 @@
+[object Object]
+Error
+	at func (test/script/basic/JDK-8020437.js:48)
+	at f (test/script/basic/JDK-8020437.js:41)
+	at <program> (test/script/basic/JDK-8020437.js:37)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8020437-2.js	Fri Jul 12 15:01:33 2013 +0530
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8020437: Wrong handling of line numbers with multiline string literals
+ *
+ * @test/compile-error
+ * @option -scripting
+ */
+
+print({
+   text: <<EOF
+This is a multiple line
+text inside a sting literal.
+Run this with -scripting option.
+EOF}); var x++; // syntax error in same line
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8020437-2.js.EXPECTED	Fri Jul 12 15:01:33 2013 +0530
@@ -0,0 +1,3 @@
+test/script/error/JDK-8020437-2.js:36:12 Expected ; but found ++
+EOF}); var x++; // syntax error in same line
+            ^
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8020437.js	Fri Jul 12 15:01:33 2013 +0530
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8020437: Wrong handling of line numbers with multiline string literals
+ *
+ * @test/compile-error
+ * @option -scripting
+ */
+
+print({
+   text: <<EOF
+This is a multiple line
+text inside a sting literal.
+Run this with -scripting option.
+EOF);  // missing "}" to end object literal
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/error/JDK-8020437.js.EXPECTED	Fri Jul 12 15:01:33 2013 +0530
@@ -0,0 +1,3 @@
+test/script/error/JDK-8020437.js:36:3 Expected comma but found )
+EOF);  // missing "}" to end object literal
+   ^