You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2018/05/24 11:43:20 UTC

groovy git commit: GROOVY-8586: Support Java 9 ARM blocks

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_6_X 3f5b9fd38 -> 5f540e893


GROOVY-8586: Support Java 9 ARM blocks


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/5f540e89
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/5f540e89
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/5f540e89

Branch: refs/heads/GROOVY_2_6_X
Commit: 5f540e8933ed3412d3acaede1483d09dfdb8c5dc
Parents: 3f5b9fd
Author: danielsun1106 <re...@hotmail.com>
Authored: Thu May 24 19:43:11 2018 +0800
Committer: danielsun1106 <re...@hotmail.com>
Committed: Thu May 24 19:43:28 2018 +0800

----------------------------------------------------------------------
 .../groovy/ast/stmt/TryCatchStatement.java      |   5 +-
 .../apache/groovy/parser/antlr4/AstBuilder.java |  43 ++-
 .../parser/antlr4/GroovyParserTest.groovy       |   1 +
 .../resources/core/TryWithResources_02x.groovy  | 311 +++++++++++++++++++
 4 files changed, 352 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/5f540e89/src/main/java/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/ast/stmt/TryCatchStatement.java b/src/main/java/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
index f05460f..aee7176 100644
--- a/src/main/java/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
+++ b/src/main/java/org/codehaus/groovy/ast/stmt/TryCatchStatement.java
@@ -20,6 +20,7 @@ package org.codehaus.groovy.ast.stmt;
 
 import org.codehaus.groovy.ast.GroovyCodeVisitor;
 import org.codehaus.groovy.ast.expr.DeclarationExpression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -63,8 +64,8 @@ public class TryCatchStatement extends Statement {
     }
 
     public void addResource(ExpressionStatement resourceStatement) {
-        if (!(resourceStatement.getExpression() instanceof DeclarationExpression)) {
-            throw new IllegalArgumentException("resourceStatement should be a variable declaration statement");
+        if (!(resourceStatement.getExpression() instanceof DeclarationExpression || resourceStatement.getExpression() instanceof VariableExpression)) {
+            throw new IllegalArgumentException("resourceStatement should be a variable declaration statement or a variable");
         }
 
         resourceStatements.add(resourceStatement);

http://git-wip-us.apache.org/repos/asf/groovy/blob/5f540e89/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 2942439..fb3895e 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -801,7 +801,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
                 new TryCatchStatement((Statement) this.visit(ctx.block()),
                         this.visitFinallyBlock(ctx.finallyBlock()));
 
-        if (asBoolean(ctx.resources())) {
+        if (resourcesExists) {
             for (ExpressionStatement e : this.visitResources(ctx.resources())) {
                 tryCatchStatement.addResource(e);
             }
@@ -847,14 +847,40 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
             return declarationStatements.get(0);
         } else if (asBoolean(ctx.expression())) {
             Expression expression = (Expression) this.visit(ctx.expression());
-            if (!(expression instanceof BinaryExpression
+            boolean isVariableDeclaration = expression instanceof BinaryExpression
                     && Types.ASSIGN == ((BinaryExpression) expression).getOperation().getType()
-                    && ((BinaryExpression) expression).getLeftExpression() instanceof VariableExpression)) {
+                    && ((BinaryExpression) expression).getLeftExpression() instanceof VariableExpression;
+            boolean isVariableAccess = expression instanceof VariableExpression;
 
-                throw createParsingFailedException("Only variable declarations are allowed to declare resource", ctx);
+            if (!(isVariableDeclaration || isVariableAccess)) {
+                throw createParsingFailedException("Only variable declarations or variable access are allowed to declare resource", ctx);
+            }
+            BinaryExpression assignmentExpression;
+
+            if (isVariableDeclaration) {
+                assignmentExpression = (BinaryExpression) expression;
+            } else if (isVariableAccess) {
+                /* See https://docs.oracle.com/javase/specs/jls/se9/html/jls-14.html
+                 * 14.20.3.1. Basic try-with-resources
+                 *
+                 * If a basic try-with-resource statement is of the form:
+                 * try (VariableAccess ...)
+                 *      Block
+                 *
+                 * then the resource is first converted to a local variable declaration by the following translation:
+                 * try (T #r = VariableAccess ...) {
+                 *      Block
+                 * }
+                 */
+                assignmentExpression =
+                        new BinaryExpression(
+                                new VariableExpression(genResourceName()),
+                                org.codehaus.groovy.syntax.Token.newSymbol(Types.ASSIGN, -1, -1),
+                                expression
+                        );
+            } else {
+                throw createParsingFailedException("Unsupported resource declaration", ctx);
             }
-
-            BinaryExpression assignmentExpression = (BinaryExpression) expression;
 
             return configureAST(
                     new ExpressionStatement(
@@ -873,6 +899,11 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         throw createParsingFailedException("Unsupported resource declaration: " + ctx.getText(), ctx);
     }
 
+    private int resourceCnt = 0;
+    private String genResourceName() {
+        return "__$$resource" + resourceCnt++;
+    }
+
     /**
      * Multi-catch(1..*) clause will be unpacked to several normal catch clauses, so the return type is List
      *

http://git-wip-us.apache.org/repos/asf/groovy/blob/5f540e89/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
index 6535b69..0d55a39 100644
--- a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
+++ b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/GroovyParserTest.groovy
@@ -273,6 +273,7 @@ class GroovyParserTest extends GroovyTestCase {
 
     void "test groovy core - TryWithResources"() {
         doRunAndTestAntlr4('core/TryWithResources_01x.groovy')
+        doRunAndTestAntlr4('core/TryWithResources_02x.groovy')
     }
 
     void "test groovy core - SafeIndex"() {

http://git-wip-us.apache.org/repos/asf/groovy/blob/5f540e89/subprojects/parser-antlr4/src/test/resources/core/TryWithResources_02x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/core/TryWithResources_02x.groovy b/subprojects/parser-antlr4/src/test/resources/core/TryWithResources_02x.groovy
new file mode 100644
index 0000000..95d0767
--- /dev/null
+++ b/subprojects/parser-antlr4/src/test/resources/core/TryWithResources_02x.groovy
@@ -0,0 +1,311 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+import groovy.transform.CompileStatic
+
+import java.io.*
+
+
+class Resource implements Closeable {
+    int resourceId;
+    static closedResourceIds = [];
+    static exMsg = "failed to close";
+
+    public Resource(int resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public void close() {
+        if (3 == resourceId) throw new IOException(exMsg);
+
+        closedResourceIds << resourceId
+    }
+}
+
+// test case 1
+def a = 1;
+Resource resource1 = new Resource(1)
+try (resource1) {
+    a = 2;
+}
+assert Resource.closedResourceIds == [1]
+assert 2 == a
+
+// test case 2
+Resource.closedResourceIds = []
+final exMsg = "resource not found";
+try {
+    // try { ... } should throw the IOException, while the resource should be closed
+    Resource r1 = new Resource(2)
+    try (r1) {
+        throw new FileNotFoundException(exMsg)
+    }
+} catch(FileNotFoundException e) {
+    assert exMsg == e.getMessage()
+}
+assert Resource.closedResourceIds == [2]
+
+// test case 3
+Resource.closedResourceIds = []
+a = 1;
+try {
+    Resource r1 = new Resource(3)
+    try (r1) {
+        a = 2;
+    }
+} catch (IOException e) {
+    assert Resource.exMsg == e.getMessage()
+}
+assert 2 == a;
+assert Resource.closedResourceIds == []
+
+// test case 4
+Resource.closedResourceIds = []
+try {
+    // try { ... } should throw the IOException, while the resource should be closed
+    Resource r1 = new Resource(3)
+    try (r1) {
+        throw new FileNotFoundException(exMsg)
+    }
+} catch(FileNotFoundException e) {
+    assert exMsg == e.getMessage()
+
+    def suppressedExceptions = e.getSuppressed();
+    assert suppressedExceptions.length == 1
+    assert suppressedExceptions[0] instanceof IOException
+    assert suppressedExceptions[0].getMessage() == Resource.exMsg
+}
+assert Resource.closedResourceIds == []
+
+
+// test case 5
+Resource.closedResourceIds = []
+a = 1;
+Resource rr1 = new Resource(5)
+try (rr1;
+Resource r2 = new Resource(6);) {
+    a = 2;
+}
+assert Resource.closedResourceIds == [6, 5]
+assert 2 == a
+
+// test case 6
+Resource.closedResourceIds = []
+a = 1;
+Resource rr2 = new Resource(6)
+try (Resource r1 = new Resource(5);
+rr2;
+Resource r3 = new Resource(7);) {
+    a = 2;
+}
+assert Resource.closedResourceIds == [7, 6, 5]
+assert 2 == a
+
+
+// test case 7
+Resource.closedResourceIds = []
+Resource rrr1 = new Resource(7)
+try (rrr1) {
+    throw new FileNotFoundException(exMsg)
+} catch(FileNotFoundException e) {
+    assert exMsg == e.getMessage()
+}
+assert Resource.closedResourceIds == [7]
+
+// test case 8
+Resource rrr2 = new Resource(8)
+Resource.closedResourceIds = []
+try (Resource r1 = new Resource(7);
+rrr2) {
+    throw new FileNotFoundException(exMsg)
+} catch(FileNotFoundException e) {
+    assert exMsg == e.getMessage()
+}
+assert Resource.closedResourceIds == [8, 7]
+
+
+// test case 9
+Resource.closedResourceIds = []
+a = 1;
+Resource rrrr1 = new Resource(3)
+try (rrrr1) {
+    a = 2;
+} catch (IOException e) {
+    assert Resource.exMsg == e.getMessage()
+}
+assert 2 == a;
+assert Resource.closedResourceIds == []
+
+
+// test case 10
+Resource.closedResourceIds = []
+a = 1;
+Resource rrrrr1 = new Resource(3);
+Resource rrrrr2 = new Resource(4);
+try (rrrrr1; rrrrr2) {
+    a = 2;
+} catch (IOException e) {
+    assert Resource.exMsg == e.getMessage()
+}
+assert 2 == a;
+assert Resource.closedResourceIds == [4]
+
+// test case 11
+Resource.closedResourceIds = []
+a = 1;
+Resource rrrrrr0 = new Resource(2);
+Resource rrrrrr2 = new Resource(4)
+try (rrrrrr0;
+Resource rrrrrr1 = new Resource(3); rrrrrr2) {
+    a = 2;
+} catch (IOException e) {
+    assert Resource.exMsg == e.getMessage()
+}
+assert 2 == a;
+assert Resource.closedResourceIds == [4, 2]
+
+
+// test case 12
+Resource.closedResourceIds = []
+Resource rrrrrrr1 = new Resource(3);
+Resource rrrrrrr2 = new Resource(4)
+try (rrrrrrr1;
+rrrrrrr2) {
+    throw new FileNotFoundException(exMsg)
+} catch(FileNotFoundException e) {
+    assert exMsg == e.getMessage()
+
+    def suppressedExceptions = e.getSuppressed();
+    assert suppressedExceptions.length == 1
+    assert suppressedExceptions[0] instanceof IOException
+    assert suppressedExceptions[0].getMessage() == Resource.exMsg
+}
+assert Resource.closedResourceIds == [4]
+
+// test case 13
+Resource.closedResourceIds = []
+Resource rrrrrrrr2 = new Resource(4)
+try (Resource r0 = new Resource(2);
+Resource r1 = new Resource(3);
+rrrrrrrr2) {
+    throw new FileNotFoundException(exMsg)
+} catch(FileNotFoundException e) {
+    assert exMsg == e.getMessage()
+
+    def suppressedExceptions = e.getSuppressed();
+    assert suppressedExceptions.length == 1
+    assert suppressedExceptions[0] instanceof IOException
+    assert suppressedExceptions[0].getMessage() == Resource.exMsg
+}
+assert Resource.closedResourceIds == [4, 2]
+
+// test case 14
+Resource.closedResourceIds = []
+a = 1;
+Resource rrrrrrrrr1 = new Resource(1)
+try (rrrrrrrrr1) {
+    a += 2;
+    Resource rrrrrrrrr2 = new Resource(2);
+    Resource rrrrrrrrr4 = new Resource(4)
+    try (rrrrrrrrr2; rrrrrrrrr4) {
+        a += 3;
+        Resource rrrrrrrrr6 = new Resource(6)
+        try (Resource r5 = new Resource(5); rrrrrrrrr6; Resource r7 = new Resource(7)) {
+            a += 4;
+            try {
+                Resource rrrrrrrrr3 = new Resource(3)
+                try (rrrrrrrrr3) {
+                    a += 5;
+                }
+            } catch (IOException e) {
+                assert Resource.exMsg == e.getMessage()
+            }
+        }
+    } catch(Exception e) {
+        // ignored
+    } finally {
+        a += 10
+    }
+}
+assert Resource.closedResourceIds == [7, 6, 5, 4, 2, 1]
+assert 25 == a
+
+// test case 15
+@CompileStatic
+void tryWithResources() {
+    Resource.closedResourceIds = []
+    int cs = 1;
+    Resource r1 = new Resource(1)
+    try (r1) {
+        cs += 2;
+        Resource r2 = new Resource(2);
+        Resource r4 = new Resource(4)
+        try (r2; r4) {
+            cs += 3;
+            Resource r6 = new Resource(6);
+            try (Resource r5 = new Resource(5); r6; Resource r7 = new Resource(7)) {
+                cs += 4;
+                try {
+                    Resource r3 = new Resource(3)
+                    try (r3) {
+                        cs += 5;
+                    }
+                } catch (IOException e) {
+                    assert Resource.exMsg == e.getMessage()
+                }
+            }
+        } catch(Exception e) {
+            // ignored
+        } finally {
+            cs += 10
+        }
+    }
+    assert Resource.closedResourceIds == [7, 6, 5, 4, 2, 1]
+    assert 25 == cs
+}
+
+tryWithResources()
+
+
+// test case 16
+Resource.closedResourceIds = []
+a = 1;
+Resource rrrrrrrrrr1 = new Resource(
+        1
+)
+try (
+        rrrrrrrrrr1
+        Resource r2 = new Resource(2)
+) {
+    a = 2;
+}
+assert Resource.closedResourceIds == [2, 1]
+assert 2 == a
+
+// test case 17
+Resource.closedResourceIds = []
+a = 1;
+rrrrrrrrrrr2 = new Resource(2)
+try (r1 = new Resource(1)
+rrrrrrrrrrr2) {
+    a = 2;
+}
+assert Resource.closedResourceIds == [2, 1]
+assert 2 == a
+