langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 27844 8b5d79870a2f
parent 26993 513b2cae81c3
child 27989 0da3e8ddfdd5
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Nov 17 23:11:05 2014 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Wed Nov 19 13:46:04 2014 +0100
@@ -145,6 +145,8 @@
         this.names = fac.names;
         this.source = fac.source;
         this.allowTWR = source.allowTryWithResources();
+        this.allowEffectivelyFinalVariablesInTWR =
+                source.allowEffectivelyFinalVariablesInTryWithResources();
         this.allowDiamond = source.allowDiamond();
         this.allowMulticatch = source.allowMulticatch();
         this.allowStringFolding = fac.options.getBoolean("allowStringFolding", true);
@@ -184,6 +186,10 @@
      */
     boolean allowTWR;
 
+    /** Switch: should we allow (effectively) final variables as resources in try-with-resources?
+     */
+    boolean allowEffectivelyFinalVariablesInTWR;
+
     /** Switch: should we fold strings?
      */
     boolean allowStringFolding;
@@ -3003,14 +3009,28 @@
         return defs.toList();
     }
 
-    /** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
+    /** Resource = VariableModifiersOpt Type VariableDeclaratorId "=" Expression
+     *           | Expression
      */
     protected JCTree resource() {
-        JCModifiers optFinal = optFinal(Flags.FINAL);
-        JCExpression type = parseType();
-        int pos = token.pos;
-        Name ident = ident();
-        return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
+        int startPos = token.pos;
+        if (token.kind == FINAL || token.kind == MONKEYS_AT) {
+            JCModifiers mods = optFinal(Flags.FINAL);
+            JCExpression t = parseType();
+            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
+        }
+        JCExpression t = term(EXPR | TYPE);
+        if ((lastmode & TYPE) != 0 && LAX_IDENTIFIER.accepts(token.kind)) {
+            JCModifiers mods = toP(F.at(startPos).Modifiers(Flags.FINAL));
+            return variableDeclaratorRest(token.pos, mods, t, ident(), true, null);
+        } else {
+            checkVariableInTryWithResources(startPos);
+            if (!t.hasTag(IDENT) && !t.hasTag(SELECT)) {
+                log.error(t.pos(), "try.with.resources.expr.needs.var");
+            }
+
+            return t;
+        }
     }
 
     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
@@ -3933,6 +3953,12 @@
             allowTWR = true;
         }
     }
+    void checkVariableInTryWithResources(int startPos) {
+        if (!allowEffectivelyFinalVariablesInTWR) {
+            error(startPos, "var.in.try.with.resources.not.supported.in.source", source.name);
+            allowEffectivelyFinalVariablesInTWR = true;
+        }
+    }
     void checkLambda() {
         if (!allowLambda) {
             log.error(token.pos, "lambda.not.supported.in.source", source.name);