You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2016/08/29 12:59:47 UTC

groovy git commit: GROOVY-7920: Simple getAt example produces a BUG exception (closes #399)

Repository: groovy
Updated Branches:
  refs/heads/master 680bd4428 -> e0b36ebc9


GROOVY-7920: Simple getAt example produces a BUG exception (closes #399)


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

Branch: refs/heads/master
Commit: e0b36ebc910cd01a05a5c9ecf5e569b26e891874
Parents: 680bd44
Author: paulk <pa...@asert.com.au>
Authored: Sat Aug 27 14:37:35 2016 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Mon Aug 29 22:59:07 2016 +1000

----------------------------------------------------------------------
 .../asm/sc/StaticTypesCallSiteWriter.java       | 30 +++++++++-
 src/test/groovy/bugs/Groovy7920Bug.groovy       | 58 ++++++++++++++++++++
 2 files changed, 85 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/e0b36ebc/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index dd5a913..e955efc 100644
--- a/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -662,11 +662,20 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
                 ClassNode current = rType;
                 MethodNode getAtNode = null;
                 while (current!=null && getAtNode==null) {
-                    getAtNode = current.getMethod("getAt", new Parameter[]{new Parameter(aType, "index")});
+                    getAtNode = current.getDeclaredMethod("getAt", new Parameter[]{new Parameter(aType, "index")});
+                    if (getAtNode == null) {
+                        getAtNode = getCompatibleMethod(current, "getAt", aType);
+                    }
                     if (getAtNode==null && isPrimitiveType(aType)) {
-                        getAtNode = current.getMethod("getAt", new Parameter[]{new Parameter(getWrapper(aType), "index")});
+                        getAtNode = current.getDeclaredMethod("getAt", new Parameter[]{new Parameter(getWrapper(aType), "index")});
+                        if (getAtNode == null) {
+                            getAtNode = getCompatibleMethod(current, "getAt", getWrapper(aType));
+                        }
                     } else if (getAtNode==null && aType.isDerivedFrom(Number_TYPE)) {
-                        getAtNode = current.getMethod("getAt", new Parameter[]{new Parameter(getUnwrapper(aType), "index")});
+                        getAtNode = current.getDeclaredMethod("getAt", new Parameter[]{new Parameter(getUnwrapper(aType), "index")});
+                        if (getAtNode == null) {
+                            getAtNode = getCompatibleMethod(current, "getAt", getUnwrapper(aType));
+                        }
                     }
                     current = current.getSuperClass();
                 }
@@ -726,6 +735,21 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
         return false;
     }
 
+    private MethodNode getCompatibleMethod(ClassNode current, String getAt, ClassNode aType) {
+        // TODO this really should find "best" match or find all matches and complain about ambiguity if more than one
+        // TODO handle getAt with more than one parameter
+        // TODO handle default getAt methods on Java 8 interfaces
+        for (MethodNode methodNode : current.getDeclaredMethods("getAt")) {
+            if (methodNode.getParameters().length == 1) {
+                ClassNode paramType = methodNode.getParameters()[0].getType();
+                if (aType.isDerivedFrom(paramType) || aType.declaresInterface(paramType)) {
+                    return methodNode;
+                }
+            }
+        }
+        return null;
+    }
+
     private void writeArrayGet(final Expression receiver, final Expression arguments, final ClassNode rType, final ClassNode aType) {
         OperandStack operandStack = controller.getOperandStack();
         int m1 = operandStack.getStackLength();

http://git-wip-us.apache.org/repos/asf/groovy/blob/e0b36ebc/src/test/groovy/bugs/Groovy7920Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy7920Bug.groovy b/src/test/groovy/bugs/Groovy7920Bug.groovy
new file mode 100644
index 0000000..f59a63f
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7920Bug.groovy
@@ -0,0 +1,58 @@
+/*
+ *  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 Groovy7920Bug extends GroovyTestCase {
+    void testGetAtViaInterface() {
+        assertScript '''
+            interface Foo {}
+            class Bar implements Foo {}
+            @groovy.transform.CompileStatic
+            class TestGroovy {
+                static void test() { assert new TestGroovy()[new Bar()] == 42 }
+                def getAt(Foo x) { 42 }
+            }
+            TestGroovy.test()
+        '''
+    }
+
+    void testGetAtViaSuper() {
+        assertScript '''
+            class Foo {}
+            class Bar extends Foo {}
+            @groovy.transform.CompileStatic
+            class TestGroovy {
+                static void test() { assert new TestGroovy()[new Bar()] == 42 }
+                def getAt(Foo x) { 42 }
+            }
+            TestGroovy.test()
+        '''
+    }
+
+    void testGetAtNonNumeric() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class TestGroovy {
+                static void test() { assert new TestGroovy()[3] == 42 }
+                def getAt(def x) { 42 }
+            }
+            TestGroovy.test()
+        '''
+    }
+}