changeset 3228:d2d04222e191

8031383: Error recovery in JavacParser could be improved Summary: Improving error recovery in JavacParser by avoiding artificial nextToken in JavacParser.reportSyntaxError. Reviewed-by: jjg, jfranck Contributed-by: dusan.balek@oracle.com, jan.lahoda@oracle.com
author jlahoda
date Fri, 28 Feb 2014 20:25:24 +0100
parents 35789cbea856
children c96d2c7acfe6
files src/share/classes/com/sun/tools/javac/parser/JavacParser.java src/share/classes/com/sun/tools/javac/resources/compiler.properties test/tools/javac/TryWithResources/BadTwrSyntax.out test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out test/tools/javac/annotations/typeAnnotations/failures/OldArray.out test/tools/javac/diags/examples/ArrayAndReceiver.java test/tools/javac/diags/examples/EmptyCharLiteral.java test/tools/javac/diags/examples/IllegalDot.java test/tools/javac/diags/examples/IllegalStartOfType.java test/tools/javac/diags/examples/InitializerNotAllowed.java test/tools/javac/diags/examples/InvalidBinaryNumber.java test/tools/javac/diags/examples/VarargsMustBeLast.java test/tools/javac/enum/EnumMembersOrder.out test/tools/javac/parser/7157165/T7157165.out test/tools/javac/parser/ErroneousParameters.java test/tools/javac/parser/ErroneousParameters.out test/tools/javac/parser/MissingClosingBrace.java test/tools/javac/parser/MissingClosingBrace.out test/tools/javac/parser/SingleCommaAnnotationValueFail.out test/tools/javac/parser/T4881269.out test/tools/javac/processing/TestWarnErrorCount.java test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out test/tools/javac/quid/T6999438.out
diffstat 24 files changed, 111 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Feb 28 20:25:24 2014 +0100
@@ -431,7 +431,9 @@
         return toP(err);
     }
 
+    private static final int RECOVERY_THRESHOLD = 50;
     private int errorPos = Position.NOPOS;
+    private int count = 0;
 
     /**
      * Report a syntax using the given the position parameter and arguments,
@@ -456,9 +458,13 @@
             }
         }
         S.errPos(pos);
-        if (token.pos == errorPos)
-            nextToken(); // guarantee progress
-        errorPos = token.pos;
+        if (token.pos == errorPos) {
+            //check for a possible infinite loop in parsing:
+            Assert.check(count++ < RECOVERY_THRESHOLD);
+        } else {
+            count = 0;
+            errorPos = token.pos;
+        }
     }
 
 
@@ -2288,14 +2294,19 @@
     @SuppressWarnings("fallthrough")
     List<JCStatement> blockStatements() {
         //todo: skip to anchor on error(?)
+        int lastErrPos = -1;
         ListBuffer<JCStatement> stats = new ListBuffer<>();
         while (true) {
             List<JCStatement> stat = blockStatement();
             if (stat.isEmpty()) {
                 return stats.toList();
             } else {
+                // error recovery
+                if (token.pos == lastErrPos)
+                    return stats.toList();
                 if (token.pos <= endPosTable.errorEndPos) {
                     skip(false, true, true, true);
+                    lastErrPos = token.pos;
                 }
                 stats.addAll(stat);
             }
@@ -3424,9 +3435,12 @@
                 token.kind == INTERFACE ||
                 allowEnums && token.kind == ENUM) {
                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
-            } else if (token.kind == LBRACE && !isInterface &&
+            } else if (token.kind == LBRACE &&
                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
                        mods.annotations.isEmpty()) {
+                if (isInterface) {
+                    error(token.pos, "initializer.not.allowed");
+                }
                 return List.<JCTree>of(block(pos, mods.flags));
             } else {
                 pos = token.pos;
--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Feb 28 18:27:14 2014 +0000
+++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Feb 28 20:25:24 2014 +0100
@@ -1039,6 +1039,9 @@
 compiler.err.initializer.must.be.able.to.complete.normally=\
     initializer must be able to complete normally
 
+compiler.err.initializer.not.allowed=\
+    initializers not allowed in interfaces
+
 # 0: type
 compiler.err.unreported.exception.need.to.catch.or.throw=\
     unreported exception {0}; must be caught or declared to be thrown
--- a/test/tools/javac/TryWithResources/BadTwrSyntax.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/TryWithResources/BadTwrSyntax.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,7 +1,2 @@
 BadTwrSyntax.java:14:43: compiler.err.illegal.start.of.type
-BadTwrSyntax.java:14:44: compiler.err.expected: =
-BadTwrSyntax.java:14:45: compiler.err.expected: ')'
-BadTwrSyntax.java:14:47: compiler.err.expected: '{'
-BadTwrSyntax.java:15:19: compiler.err.illegal.start.of.expr
-BadTwrSyntax.java:15:23: compiler.err.expected: ';'
-6 errors
+1 error
--- a/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,8 +1,2 @@
 T6967002.java:33:22: compiler.err.expected: ')'
-T6967002.java:33:25: compiler.err.illegal.start.of.expr
-T6967002.java:33:28: compiler.err.illegal.start.of.expr
-T6967002.java:33:29: compiler.err.illegal.start.of.expr
-T6967002.java:33:27: compiler.err.not.stmt
-T6967002.java:33:30: compiler.err.expected: ';'
-T6967002.java:35:2: compiler.err.premature.eof
-7 errors
+1 error
--- a/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,3 +1,3 @@
 AnnotatedPackage2.java:9:8: compiler.err.expected: token.identifier
-AnnotatedPackage2.java:9:10: compiler.err.expected3: class, interface, enum
+AnnotatedPackage2.java:9:12: compiler.err.expected3: class, interface, enum
 2 errors
--- a/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,10 +1,4 @@
 OldArray.java:12:11: compiler.err.expected: ']'
 OldArray.java:12:13: compiler.err.expected: token.identifier
-OldArray.java:12:14: compiler.err.expected: ';'
-OldArray.java:12:17: compiler.err.illegal.start.of.type
-OldArray.java:12:18: compiler.err.expected: token.identifier
-OldArray.java:12:19: compiler.err.expected: ';'
-OldArray.java:12:22: compiler.err.illegal.start.of.type
-OldArray.java:12:28: compiler.err.expected: token.identifier
-OldArray.java:13:1: compiler.err.expected3: class, interface, enum
-9 errors
+OldArray.java:12:16: compiler.err.invalid.meth.decl.ret.type.req
+3 errors
--- a/test/tools/javac/diags/examples/ArrayAndReceiver.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/diags/examples/ArrayAndReceiver.java	Fri Feb 28 20:25:24 2014 +0100
@@ -22,9 +22,6 @@
  */
 
 // key: compiler.err.array.and.receiver
-// key: compiler.err.expected
-// key: compiler.err.expected3
-// key: compiler.err.illegal.start.of.type
 
 class ArrayAndReceiver {
     void m(ArrayAndReceiver this[]) { }
--- a/test/tools/javac/diags/examples/EmptyCharLiteral.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/diags/examples/EmptyCharLiteral.java	Fri Feb 28 20:25:24 2014 +0100
@@ -23,7 +23,6 @@
 
 // key: compiler.err.empty.char.lit
 // key: compiler.err.unclosed.char.lit
-// key: compiler.err.premature.eof
 
 class X {
     char c = '';
--- a/test/tools/javac/diags/examples/IllegalDot.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/diags/examples/IllegalDot.java	Fri Feb 28 20:25:24 2014 +0100
@@ -22,8 +22,6 @@
  */
 
 // key: compiler.err.illegal.dot
-// key: compiler.err.expected
-// key: compiler.err.illegal.start.of.type
 
 class X {
     void m(Object.. args) { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/IllegalStartOfType.java	Fri Feb 28 20:25:24 2014 +0100
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// key: compiler.err.illegal.start.of.type
+
+class IllegalStartOfType {
+    public void test(int i,) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/diags/examples/InitializerNotAllowed.java	Fri Feb 28 20:25:24 2014 +0100
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+// key: compiler.err.initializer.not.allowed
+
+interface InitializerNotAllowed {
+    {
+        System.out.println();
+    }
+}
--- a/test/tools/javac/diags/examples/InvalidBinaryNumber.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/diags/examples/InvalidBinaryNumber.java	Fri Feb 28 20:25:24 2014 +0100
@@ -22,9 +22,6 @@
  */
 
 // key: compiler.err.invalid.binary.number
-// key: compiler.err.illegal.start.of.type
-// key: compiler.err.expected
-// key: compiler.err.premature.eof
 
 class InvalidBinaryNumber {
     int i = 0b201000010;
--- a/test/tools/javac/diags/examples/VarargsMustBeLast.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/diags/examples/VarargsMustBeLast.java	Fri Feb 28 20:25:24 2014 +0100
@@ -23,6 +23,6 @@
 
 // key: compiler.err.varargs.must.be.last
 
-class VarargMustBeFinal {
+class VarargMustBeLast {
     public void invalidVarArg(String... invalidVarArg, String extra) { }
 }
--- a/test/tools/javac/enum/EnumMembersOrder.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/enum/EnumMembersOrder.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,6 +1,6 @@
 EnumMembersOrder.java:11:16: compiler.err.expected: ')'
 EnumMembersOrder.java:11:17: compiler.err.expected3: ',', '}', ';'
-EnumMembersOrder.java:11:19: compiler.err.expected: '}'
+EnumMembersOrder.java:11:18: compiler.err.expected: '}'
 EnumMembersOrder.java:11:31: compiler.err.expected3: class, interface, enum
 EnumMembersOrder.java:17:13: compiler.err.expected3: class, interface, enum
 EnumMembersOrder.java:19:1: compiler.err.expected3: class, interface, enum
--- a/test/tools/javac/parser/7157165/T7157165.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/parser/7157165/T7157165.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,4 +1,4 @@
 T7157165.java:11:20: compiler.err.expected: >
-T7157165.java:11:21: compiler.err.expected: ';'
-T7157165.java:11:22: compiler.err.illegal.start.of.type
+T7157165.java:11:22: compiler.err.expected: token.identifier
+T7157165.java:11:28: compiler.err.expected: token.identifier
 3 errors
--- a/test/tools/javac/parser/ErroneousParameters.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/parser/ErroneousParameters.java	Fri Feb 28 20:25:24 2014 +0100
@@ -1,6 +1,6 @@
 /*
  * @test /nodynamiccopyright/
- * @bug 8030091
+ * @bug 8030091 8031383
  * @summary Producing reasonable errors for unexpected tokens in method parameters
  * @compile/fail/ref=ErroneousParameters.out -XDrawDiagnostics ErroneousParameters.java
  */
--- a/test/tools/javac/parser/ErroneousParameters.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/parser/ErroneousParameters.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,14 +1,6 @@
 ErroneousParameters.java:10:36: compiler.err.varargs.must.be.last
 ErroneousParameters.java:11:39: compiler.err.expected3: ',', ')', '['
-ErroneousParameters.java:11:42: compiler.err.illegal.start.of.type
-ErroneousParameters.java:11:43: compiler.err.expected: token.identifier
-ErroneousParameters.java:11:45: compiler.err.expected: ';'
 ErroneousParameters.java:12:40: compiler.err.illegal.start.of.type
-ErroneousParameters.java:12:41: compiler.err.expected3: ',', ')', '['
-ErroneousParameters.java:12:43: compiler.err.expected: ';'
 ErroneousParameters.java:13:41: compiler.err.expected: ']'
 ErroneousParameters.java:14:38: compiler.err.expected3: ',', ')', '['
-ErroneousParameters.java:14:39: compiler.err.illegal.start.of.type
-ErroneousParameters.java:14:40: compiler.err.expected: token.identifier
-ErroneousParameters.java:14:42: compiler.err.expected: ';'
-13 errors
+5 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/parser/MissingClosingBrace.java	Fri Feb 28 20:25:24 2014 +0100
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8031383
+ * @summary Verify that the parser handles a missing closing brace of a block gracefully.
+ * @compile/fail/ref=MissingClosingBrace.out -XDrawDiagnostics MissingClosingBrace.java
+ */
+
+public class MissingClosingBrace {
+    private void test(int i) {
+        if (i > 0) {
+
+    private int i;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/parser/MissingClosingBrace.out	Fri Feb 28 20:25:24 2014 +0100
@@ -0,0 +1,2 @@
+MissingClosingBrace.java:12:5: compiler.err.illegal.start.of.expr
+1 error
--- a/test/tools/javac/parser/SingleCommaAnnotationValueFail.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/parser/SingleCommaAnnotationValueFail.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,6 +1,3 @@
 SingleCommaAnnotationValueFail.java:34:12: compiler.err.expected: '}'
-SingleCommaAnnotationValueFail.java:34:13: compiler.err.illegal.start.of.type
-SingleCommaAnnotationValueFail.java:34:14: compiler.err.expected: token.identifier
-SingleCommaAnnotationValueFail.java:34:15: compiler.err.expected: ';'
-SingleCommaAnnotationValueFail.java:34:21: compiler.err.invalid.meth.decl.ret.type.req
-5 errors
+SingleCommaAnnotationValueFail.java:34:14: compiler.err.expected3: class, interface, enum
+2 errors
--- a/test/tools/javac/parser/T4881269.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/parser/T4881269.out	Fri Feb 28 20:25:24 2014 +0100
@@ -2,8 +2,4 @@
 T4881269.java:33:27: compiler.err.illegal.dot
 T4881269.java:33:22: compiler.err.not.stmt
 T4881269.java:34:19: compiler.err.illegal.dot
-T4881269.java:34:20: compiler.err.expected: ';'
-T4881269.java:34:22: compiler.err.illegal.start.of.type
-T4881269.java:34:23: compiler.err.expected: token.identifier
-T4881269.java:34:25: compiler.err.expected: ';'
-8 errors
+4 errors
--- a/test/tools/javac/processing/TestWarnErrorCount.java	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/processing/TestWarnErrorCount.java	Fri Feb 28 20:25:24 2014 +0100
@@ -214,7 +214,7 @@
                 javaWarnsExpected = 0;
                 break;
             case JAVA:
-                errsExpected = 2;
+                errsExpected = 1;
                 msgrWarnsExpected = mwk.count(1, ERROR_ROUND + 1);
                 javaWarnsExpected = 0;
                 break;
--- a/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,8 +1,3 @@
 ParseErrors.java:37:37: compiler.err.expected: token.identifier
 ParseErrors.java:38:1: compiler.err.illegal.start.of.type
-ParseErrors.java:38:2: compiler.err.expected3: ',', ')', '['
-ParseErrors.java:40:6: compiler.err.expected: ';'
-ParseErrors.java:40:20: compiler.err.illegal.start.of.type
-ParseErrors.java:41:5: compiler.err.expected: '('
-ParseErrors.java:41:8: compiler.err.expected: token.identifier
-7 errors
+2 errors
--- a/test/tools/javac/quid/T6999438.out	Fri Feb 28 18:27:14 2014 +0000
+++ b/test/tools/javac/quid/T6999438.out	Fri Feb 28 20:25:24 2014 +0100
@@ -1,6 +1,2 @@
 T6999438.java:8:9: compiler.err.illegal.char: #
-T6999438.java:8:10: compiler.err.illegal.start.of.type
-T6999438.java:8:25: compiler.err.expected: token.identifier
-T6999438.java:8:26: compiler.err.expected: ';'
-T6999438.java:9:2: compiler.err.premature.eof
-5 errors
+1 error