8057652: Request to improve error messages for labeled declarations
authorjlahoda
Thu, 09 Oct 2014 10:08:52 +0200
changeset 26993 513b2cae81c3
parent 26992 92e69fa21956
child 26994 906669fe9f2d
8057652: Request to improve error messages for labeled declarations Summary: Parse labeled statements as block statements to improve error recovery for labeled declarations; related cleanup. Reviewed-by: jjg
langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
langtools/test/tools/javac/LabeledDeclaration.java
langtools/test/tools/javac/LabeledDeclaration.out
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Tue Oct 07 21:21:42 2014 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Oct 09 10:08:52 2014 +0200
@@ -2271,9 +2271,11 @@
     }
 
     /*
-     * This method parses a statement treating it as a block, relaxing the
-     * JLS restrictions, allows us to parse more faulty code, doing so
-     * enables us to provide better and accurate diagnostics to the user.
+     * Parse a Statement (JLS 14.5). As an enhancement to improve error recovery,
+     * this method will also recognize variable and class declarations (which are
+     * not legal for a Statement) by delegating the parsing to BlockStatement (JLS 14.2).
+     * If any illegal declarations are found, they will be wrapped in an erroneous tree,
+     * and an error will be produced by this method.
      */
     JCStatement parseStatementAsBlock() {
         int pos = token.pos;
@@ -2302,6 +2304,8 @@
         }
     }
 
+    /**This method parses a statement appearing inside a block.
+     */
     List<JCStatement> blockStatement() {
         //todo: skip to anchor on error(?)
         int pos = token.pos;
@@ -2311,7 +2315,8 @@
         case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
         case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
         case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
-            return List.of(parseStatement());
+        case ASSERT:
+            return List.of(parseSimpleStatement());
         case MONKEYS_AT:
         case FINAL: {
             Comment dc = token.comment(CommentStyle.JAVADOC);
@@ -2343,14 +2348,12 @@
             error(token.pos, "local.enum");
             dc = token.comment(CommentStyle.JAVADOC);
             return List.of(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
-        case ASSERT:
-            return List.of(parseStatement());
         default:
             Token prevToken = token;
             JCExpression t = term(EXPR | TYPE);
             if (token.kind == COLON && t.hasTag(IDENT)) {
                 nextToken();
-                JCStatement stat = parseStatement();
+                JCStatement stat = parseStatementAsBlock();
                 return List.<JCStatement>of(F.at(pos).Labelled(prevToken.name(), stat));
             } else if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
                 pos = token.pos;
@@ -2389,10 +2392,8 @@
      *     | CONTINUE [Ident] ";"
      *     | ASSERT Expression [ ":" Expression ] ";"
      *     | ";"
-     *     | ExpressionStatement
-     *     | Ident ":" Statement
      */
-    public JCStatement parseStatement() {
+    JCStatement parseSimpleStatement() {
         int pos = token.pos;
         switch (token.kind) {
         case LBRACE:
@@ -2542,24 +2543,17 @@
             JCAssert t = toP(F.at(pos).Assert(assertion, message));
             return t;
         }
-        case ENUM:
         default:
-            Token prevToken = token;
-            JCExpression expr = parseExpression();
-            if (token.kind == COLON && expr.hasTag(IDENT)) {
-                nextToken();
-                JCStatement stat = parseStatement();
-                return F.at(pos).Labelled(prevToken.name(), stat);
-            } else {
-                // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
-                expr = checkExprStat(expr);
-                accept(SEMI);
-                JCExpressionStatement stat = toP(F.at(pos).Exec(expr));
-                return stat;
-            }
+            Assert.error();
+            return null;
         }
     }
 
+    @Override
+    public JCStatement parseStatement() {
+        return parseStatementAsBlock();
+    }
+
     private JCStatement doRecover(int startPos, ErrorRecoveryAction action, String key) {
         int errPos = S.errPos();
         JCTree stm = action.doRecover(this);
--- a/langtools/test/tools/javac/LabeledDeclaration.java	Tue Oct 07 21:21:42 2014 +0200
+++ b/langtools/test/tools/javac/LabeledDeclaration.java	Thu Oct 09 10:08:52 2014 +0200
@@ -1,6 +1,6 @@
 /*
  * @test  /nodynamiccopyright/
- * @bug 4039843
+ * @bug 4039843 8057652
  * @summary The compiler should not allow labeled declarations.
  * @author turnidge
  *
--- a/langtools/test/tools/javac/LabeledDeclaration.out	Tue Oct 07 21:21:42 2014 +0200
+++ b/langtools/test/tools/javac/LabeledDeclaration.out	Thu Oct 09 10:08:52 2014 +0200
@@ -1,3 +1,2 @@
-LabeledDeclaration.java:12:14: compiler.err.dot.class.expected
-LabeledDeclaration.java:12:10: compiler.err.not.stmt
-2 errors
+LabeledDeclaration.java:12:14: compiler.err.variable.not.allowed
+1 error