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 2017/07/14 18:52:51 UTC

groovy git commit: Support property and field with same name

Repository: groovy
Updated Branches:
  refs/heads/master 2817e7e64 -> 72a7f35e2


Support property and field with same name


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

Branch: refs/heads/master
Commit: 72a7f35e2715ab962adb5ef114f0b33dc956cece
Parents: 2817e7e
Author: sunlan <su...@apache.org>
Authored: Sat Jul 15 02:52:16 2017 +0800
Committer: sunlan <su...@apache.org>
Committed: Sat Jul 15 02:52:45 2017 +0800

----------------------------------------------------------------------
 .../apache/groovy/parser/antlr4/AstBuilder.java | 118 ++++++++++++-------
 .../groovy/parser/antlr4/SyntaxErrorTest.groovy |   3 +
 .../resources/core/ClassDeclaration_01.groovy   |   7 +-
 .../resources/core/FieldDeclaration_01x.groovy  |  10 +-
 .../resources/fail/FieldDeclaration_01x.groovy  |   1 +
 .../resources/fail/FieldDeclaration_02x.groovy  |  24 ++++
 .../resources/fail/FieldDeclaration_03x.groovy  |  25 ++++
 .../resources/fail/FieldDeclaration_04x.groovy  |  25 ++++
 8 files changed, 167 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/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 649f080..369ecae 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
@@ -1538,7 +1538,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
             VariableExpression variableExpression = (VariableExpression) declarationExpression.getLeftExpression();
 
             String fieldName = variableExpression.getName();
-            validateDuplicatedField(ctx, classNode, fieldName);
 
             int modifiers = modifierManager.getClassMemberModifiersOpValue();
 
@@ -1553,60 +1552,93 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
                 modifiers |= Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
             }
 
-            if (classNode.isInterface() || modifierManager.containsVisibilityModifier()) {
-                FieldNode fieldNode =
-                        classNode.addField(
-                                fieldName,
-                                modifiers,
-                                variableType,
-                                initialValue);
-                modifierManager.attachAnnotations(fieldNode);
+            if (isFieldDeclaration(modifierManager, classNode)) {
+                declareField(ctx, modifierManager, variableType, classNode, i, variableExpression, fieldName, modifiers, initialValue);
+            } else {
+                declareProperty(ctx, modifierManager, variableType, classNode, i, variableExpression, fieldName, modifiers, initialValue);
+            }
+        }
 
-                groovydocManager.handle(fieldNode, ctx);
+        return null;
+    }
 
-                if (0 == i) {
-                    this.configureAST(fieldNode, ctx, initialValue);
-                } else {
-                    this.configureAST(fieldNode, variableExpression, initialValue);
-                }
+    private void declareProperty(VariableDeclarationContext ctx, ModifierManager modifierManager, ClassNode variableType, ClassNode classNode, int i, VariableExpression variableExpression, String fieldName, int modifiers, Expression initialValue) {
+        if (classNode.hasProperty(fieldName)) {
+            throw createParsingFailedException("The property '" + fieldName + "' is declared multiple times", ctx);
+        }
 
-            } else {
-                PropertyNode propertyNode =
-                        classNode.addProperty(
-                                fieldName,
-                                modifiers | Opcodes.ACC_PUBLIC,
-                                variableType,
-                                initialValue,
-                                null,
-                                null);
+        PropertyNode propertyNode;
+        FieldNode fieldNode = classNode.getDeclaredField(fieldName);
 
-                FieldNode fieldNode = propertyNode.getField();
-                fieldNode.setModifiers(modifiers & ~Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE);
-                fieldNode.setSynthetic(!classNode.isInterface());
-                modifierManager.attachAnnotations(fieldNode);
+        if (fieldNode != null && !classNode.hasProperty(fieldName)) {
+            classNode.getFields().remove(fieldNode);
 
-                groovydocManager.handle(fieldNode, ctx);
-                groovydocManager.handle(propertyNode, ctx);
+            propertyNode = new PropertyNode(fieldNode, modifiers | Opcodes.ACC_PUBLIC, null, null);
+            classNode.addProperty(propertyNode);
+        } else {
+            propertyNode =
+                    classNode.addProperty(
+                            fieldName,
+                            modifiers | Opcodes.ACC_PUBLIC,
+                            variableType,
+                            initialValue,
+                            null,
+                            null);
 
-                if (0 == i) {
-                    this.configureAST(fieldNode, ctx, initialValue);
-                    this.configureAST(propertyNode, ctx, initialValue);
-                } else {
-                    this.configureAST(fieldNode, variableExpression, initialValue);
-                    this.configureAST(propertyNode, variableExpression, initialValue);
-                }
-            }
+            fieldNode = propertyNode.getField();
         }
 
-        return null;
+        fieldNode.setModifiers(modifiers & ~Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE);
+        fieldNode.setSynthetic(!classNode.isInterface());
+        modifierManager.attachAnnotations(fieldNode);
+
+        groovydocManager.handle(fieldNode, ctx);
+        groovydocManager.handle(propertyNode, ctx);
+
+        if (0 == i) {
+            this.configureAST(fieldNode, ctx, initialValue);
+            this.configureAST(propertyNode, ctx, initialValue);
+        } else {
+            this.configureAST(fieldNode, variableExpression, initialValue);
+            this.configureAST(propertyNode, variableExpression, initialValue);
+        }
     }
 
-    private void validateDuplicatedField(VariableDeclarationContext ctx, ClassNode classNode, String fieldName) {
-        if (null == classNode.getDeclaredField(fieldName)) {
-            return;
+    private void declareField(VariableDeclarationContext ctx, ModifierManager modifierManager, ClassNode variableType, ClassNode classNode, int i, VariableExpression variableExpression, String fieldName, int modifiers, Expression initialValue) {
+        FieldNode existingFieldNode = classNode.getDeclaredField(fieldName);
+        if (null != existingFieldNode && !existingFieldNode.isSynthetic()) {
+            throw createParsingFailedException("The field '" + fieldName + "' is declared multiple times", ctx);
         }
 
-        throw createParsingFailedException("The field '" + fieldName + "' is declared multiple times", ctx);
+        FieldNode fieldNode;
+        PropertyNode propertyNode = classNode.getProperty(fieldName);
+
+        if (null != propertyNode && propertyNode.getField().isSynthetic()) {
+            classNode.getFields().remove(propertyNode.getField());
+            fieldNode = new FieldNode(fieldName, modifiers, variableType, classNode.redirect(), initialValue);
+            propertyNode.setField(fieldNode);
+            classNode.addField(fieldNode);
+        } else {
+            fieldNode =
+                    classNode.addField(
+                            fieldName,
+                            modifiers,
+                            variableType,
+                            initialValue);
+        }
+
+        modifierManager.attachAnnotations(fieldNode);
+        groovydocManager.handle(fieldNode, ctx);
+
+        if (0 == i) {
+            this.configureAST(fieldNode, ctx, initialValue);
+        } else {
+            this.configureAST(fieldNode, variableExpression, initialValue);
+        }
+    }
+
+    private boolean isFieldDeclaration(ModifierManager modifierManager, ClassNode classNode) {
+        return classNode.isInterface() || modifierManager.containsVisibilityModifier();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
index 672edfa..432be7b 100644
--- a/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
+++ b/subprojects/parser-antlr4/src/test/groovy/org/apache/groovy/parser/antlr4/SyntaxErrorTest.groovy
@@ -173,6 +173,9 @@ class SyntaxErrorTest extends GroovyTestCase {
 
     void "test groovy core - FieldDeclaration"() {
         TestUtils.doRunAndShouldFail('fail/FieldDeclaration_01x.groovy');
+        TestUtils.doRunAndShouldFail('fail/FieldDeclaration_02x.groovy');
+        TestUtils.doRunAndShouldFail('fail/FieldDeclaration_03x.groovy');
+        TestUtils.doRunAndShouldFail('fail/FieldDeclaration_04x.groovy');
     }
 
     /**************************************/

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy b/subprojects/parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
index 05c8bc3..875006f 100644
--- a/subprojects/parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
+++ b/subprojects/parser-antlr4/src/test/resources/core/ClassDeclaration_01.groovy
@@ -70,4 +70,9 @@ class OutputTransforms {
 
 class OutputTransforms2 {
         @Lazy  static localTransforms = loadOutputTransforms()
-}
\ No newline at end of file
+}
+
+class XX {
+        def x
+        private x = 1
+}

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/resources/core/FieldDeclaration_01x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/core/FieldDeclaration_01x.groovy b/subprojects/parser-antlr4/src/test/resources/core/FieldDeclaration_01x.groovy
index 658f98d..4a83e9f 100644
--- a/subprojects/parser-antlr4/src/test/resources/core/FieldDeclaration_01x.groovy
+++ b/subprojects/parser-antlr4/src/test/resources/core/FieldDeclaration_01x.groovy
@@ -22,7 +22,13 @@ class Base {
 }
 
 class FieldHolder extends Base {
-    def num = 1
+    def num
+    private num = 1
 }
 
-assert 1 == new FieldHolder().num
+class FieldHolder2 extends FieldHolder {
+    private num = 2
+    def num
+}
+
+assert 2 == new FieldHolder2().num

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_01x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_01x.groovy b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_01x.groovy
index 4546576..0a6d064 100644
--- a/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_01x.groovy
+++ b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_01x.groovy
@@ -21,3 +21,4 @@ class FieldHolder {
     def num = 1
     def num = 1
 }
+FieldHolder.class
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_02x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_02x.groovy b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_02x.groovy
new file mode 100644
index 0000000..e765dc0
--- /dev/null
+++ b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_02x.groovy
@@ -0,0 +1,24 @@
+/*
+ *  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.
+ */
+
+class FieldHolder {
+    private num = 1
+    private num = 1
+}
+FieldHolder.class
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_03x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_03x.groovy b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_03x.groovy
new file mode 100644
index 0000000..4e4d21c
--- /dev/null
+++ b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_03x.groovy
@@ -0,0 +1,25 @@
+/*
+ *  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.
+ */
+
+class FieldHolder {
+    def num
+    private num = 1
+    private num = 1
+}
+FieldHolder.class
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/groovy/blob/72a7f35e/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_04x.groovy
----------------------------------------------------------------------
diff --git a/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_04x.groovy b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_04x.groovy
new file mode 100644
index 0000000..0302a9a
--- /dev/null
+++ b/subprojects/parser-antlr4/src/test/resources/fail/FieldDeclaration_04x.groovy
@@ -0,0 +1,25 @@
+/*
+ *  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.
+ */
+
+class FieldHolder {
+    private num = 1
+    private num = 1
+    def num
+}
+FieldHolder.class
\ No newline at end of file