Skip to content

Commit

Permalink
GROOVY-7937: CLONE - same linkedlist code different behavior between …
Browse files Browse the repository at this point in the history
…groovy and java (fix priority of DGM methods vs actual methods on an object) (closes #418)
  • Loading branch information
paulk-asert committed Sep 16, 2016
1 parent 14266ad commit f5a161f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/main/groovy/lang/MetaClassImpl.java
Expand Up @@ -94,6 +94,7 @@

import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
import static org.codehaus.groovy.ast.tools.GeneralUtils.isDefaultVisibility;
import static org.codehaus.groovy.reflection.ReflectionCache.isAssignableFrom;

/**
* Allows methods to be dynamically added to existing classes at runtime
Expand Down Expand Up @@ -625,10 +626,26 @@ private void inheritInterfaceNewMetaMethods(Set<CachedClass> interfaces) {
for (CachedClass cls : interfaces) {
MetaMethod methods[] = getNewMetaMethods(cls);
for (MetaMethod method : methods) {
if (!newGroovyMethodsSet.contains(method)) {
newGroovyMethodsSet.add(method);
boolean skip = false;
// skip DGM methods on an interface if the class already has the method
// but don't skip for GroovyObject-related methods as it breaks things :-(
if (method instanceof GeneratedMetaMethod && !isAssignableFrom(GroovyObject.class, method.getDeclaringClass().getTheClass())) {
for (Method m : theClass.getMethods()) {
if (method.getName().equals(m.getName())
// below not true for DGM#push and also co-variant return scenarios
//&& method.getReturnType().equals(m.getReturnType())
&& MetaMethod.equal(method.getParameterTypes(), m.getParameterTypes())) {
skip = true;
break;
}
}
}
if (!skip) {
if (!newGroovyMethodsSet.contains(method)) {
newGroovyMethodsSet.add(method);
}
addMetaMethodToIndex(method, mainClassMethodHeader);
}
addMetaMethodToIndex(method, mainClassMethodHeader);
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions src/test/groovy/bugs/Groovy7937Bug.groovy
@@ -0,0 +1,36 @@
/*
* 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 Groovy7937Bug extends GroovyTestCase {
void testMethodsWithinAnInstanceShouldBeChosenAheadOfDGMMethodsOnAnInterface() {
assertScript """
class MyList extends LinkedList<String> {
MyList(Collection c) { super(c) }
String pop() {
'foo'
}
}
MyList stack1 = new MyList(1..3)
assert stack1.pop() == 'foo'
def stack2 = 1..3 as LinkedList
assert stack2.pop() == 1
"""
}
}

0 comments on commit f5a161f

Please sign in to comment.