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/02/08 08:13:15 UTC
groovy git commit: GROOVY-8474: 'Unexpected super property set for:'
when accessing super class property via super.propertyName
Repository: groovy
Updated Branches:
refs/heads/master e5e8fe1af -> ca4ffaac1
GROOVY-8474: 'Unexpected super property set for:' when accessing super class property via super.propertyName
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/ca4ffaac
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/ca4ffaac
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/ca4ffaac
Branch: refs/heads/master
Commit: ca4ffaac1dfcaa8c38409a02b08392d0f8b2473f
Parents: e5e8fe1
Author: sunlan <su...@apache.org>
Authored: Thu Feb 8 16:12:48 2018 +0800
Committer: sunlan <su...@apache.org>
Committed: Thu Feb 8 16:13:06 2018 +0800
----------------------------------------------------------------------
.../groovy/classgen/AsmClassGenerator.java | 50 ++++-
src/test/groovy/bugs/Groovy8474Bug.groovy | 220 +++++++++++++++++++
2 files changed, 269 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/ca4ffaac/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index 4b7600f..1144b6e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -1010,7 +1010,10 @@ public class AsmClassGenerator extends ClassGenerator {
if (isSuperExpression(objectExpression)) {
String prefix;
if (controller.getCompileStack().isLHS()) {
- throw new GroovyBugError("Unexpected super property set for:" + expression.getText());
+ //throw new GroovyBugError("Unexpected super property set for:" + expression.getText());
+ setSuperProperty(classNode, expression, mv);
+
+ return;
} else {
prefix = "get";
}
@@ -1082,6 +1085,51 @@ public class AsmClassGenerator extends ClassGenerator {
}
}
+ private void setSuperProperty(ClassNode classNode, PropertyExpression expression, MethodVisitor mv) {
+ String fieldName = expression.getPropertyAsString();
+ FieldNode fieldNode = classNode.getSuperClass().getField(fieldName);
+
+ if (null == fieldNode) {
+ throw new RuntimeParserException("Failed to find field[" + fieldName + "] of " + classNode.getName() + "'s super class", expression);
+ }
+
+ if (fieldNode.isFinal()) {
+ throw new RuntimeParserException("Can not modify final field[" + fieldName + "] of " + classNode.getName() + "'s super class", expression);
+ }
+
+ MethodNode setter = findSetter(classNode, fieldNode);
+
+ if (fieldNode.isPrivate() && null == setter) {
+ throw new RuntimeParserException("Can not access private field[" + fieldName + "] of " + classNode.getName() + "'s super class", expression);
+ }
+
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(SWAP);
+
+ String owner = BytecodeHelper.getClassInternalName(classNode.getSuperClass().getName());
+ String desc = BytecodeHelper.getTypeDescription(fieldNode.getType());
+ if (fieldNode.isPublic() || fieldNode.isProtected()) {
+ mv.visitFieldInsn(PUTFIELD, owner, fieldName, desc);
+ } else {
+ mv.visitMethodInsn(INVOKESPECIAL, owner, setter.getName(), BytecodeHelper.getMethodDescriptor(setter), false);
+ }
+ }
+
+ private MethodNode findSetter(ClassNode classNode, FieldNode fieldNode) {
+ String setMethodName = "set" + MetaClassHelper.capitalize(fieldNode.getName());
+ MethodNode mn = classNode.getSuperClass().getMethod(setMethodName, new Parameter[] { new Parameter(fieldNode.getType(), "") });
+
+ if (null == mn) {
+ return null;
+ }
+
+ if (!ClassHelper.VOID_TYPE.equals(mn.getReturnType())) {
+ return null;
+ }
+
+ return mn;
+ }
+
private boolean isThisOrSuperInStaticContext(Expression objectExpression) {
if (controller.isInClosure()) return false;
return controller.isStaticContext() && isThisOrSuper(objectExpression);
http://git-wip-us.apache.org/repos/asf/groovy/blob/ca4ffaac/src/test/groovy/bugs/Groovy8474Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy8474Bug.groovy b/src/test/groovy/bugs/Groovy8474Bug.groovy
new file mode 100644
index 0000000..4438b24
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8474Bug.groovy
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+package groovy.bugs
+
+class Groovy8474Bug extends GroovyTestCase {
+ void testSettingSuperProperty() {
+ assertScript '''
+ class T {
+ String group
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ '''
+ }
+
+ void testSettingSuperProperty2() {
+ assertScript '''
+ class T {
+ String group
+ String group2
+ String group3
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ super.group2 = 'Hello2'
+ super.group3 = 'Hello3'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ assert 'Hello2' == new S().group2
+ assert 'Hello3' == new S().group3
+ '''
+ }
+
+ void testSettingSuperProperty3() {
+ assertScript '''
+ class K {
+ String group
+ }
+ class T extends K {
+
+ }
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ '''
+ }
+
+ void testSettingSuperProtectedField() {
+ assertScript '''
+ class T {
+ protected String group
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ '''
+ }
+
+ void testSettingSuperProtectedField2() {
+ assertScript '''
+ class T {
+ protected String group
+ protected String group2
+ protected String group3
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ super.group2 = 'Hello2'
+ super.group3 = 'Hello3'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ assert 'Hello2' == new S().group2
+ assert 'Hello3' == new S().group3
+ '''
+ }
+
+ void testSettingSuperProtectedField3() {
+ assertScript '''
+ class K {
+ protected String group
+ }
+ class T extends K {
+
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ '''
+ }
+
+ void testSettingSuperPublicField() {
+ assertScript '''
+ class T {
+ public String group
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ '''
+ }
+
+ void testSettingSuperPublicField2() {
+ assertScript '''
+ class T {
+ public String group
+ public String group2
+ public String group3
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ super.group2 = 'Hello2'
+ super.group3 = 'Hello3'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ assert 'Hello2' == new S().group2
+ assert 'Hello3' == new S().group3
+ '''
+ }
+
+ void testSettingSuperPublicField3() {
+ assertScript '''
+ class K {
+ public String group
+ }
+ class T extends K {
+
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+
+ assert 'Hello' == new S().group
+ '''
+ }
+
+ void testSettingSuperPrivateProperty() {
+ def errMsg = shouldFail '''
+ class T {
+ private String group
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+ '''
+ assert errMsg.contains('Can not access private field')
+ }
+
+ void testSettingSuperFinalProperty() {
+ shouldFail '''
+ class T {
+ protected final String group = 'Hi'
+ }
+
+ class S extends T {
+ S() {
+ super.group = 'Hello'
+ }
+ }
+ '''
+ }
+}