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
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/TryWithResources/BadTwrSyntax.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/annotations/typeAnnotations/6967002/T6967002.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/annotations/typeAnnotations/failures/AnnotatedPackage2.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/annotations/typeAnnotations/failures/OldArray.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/diags/examples/ArrayAndReceiver.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/diags/examples/EmptyCharLiteral.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/diags/examples/IllegalDot.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/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/langtools/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/langtools/test/tools/javac/diags/examples/InvalidBinaryNumber.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/diags/examples/VarargsMustBeLast.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/enum/EnumMembersOrder.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/parser/7157165/T7157165.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/parser/ErroneousParameters.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/parser/ErroneousParameters.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/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/langtools/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/langtools/test/tools/javac/parser/SingleCommaAnnotationValueFail.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/parser/T4881269.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/processing/TestWarnErrorCount.java Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/processing/errors/TestParseErrors/TestParseErrors.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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/langtools/test/tools/javac/quid/T6999438.out Fri Feb 28 18:27:14 2014 +0000
+++ b/langtools/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