Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/main/java/groovy/lang/MetaClassImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -518,8 +518,7 @@ public void methodNameAction(final Class<?> c, final MetaMethodIndex.Cache e) {
int matchedMethod = mopArrayIndex(method, c);
if (matchedMethod >= 0) {
methods.set(i, mopMethods[matchedMethod]);
} else if (!useThis && !isDGM(method) && (isBridge(method)
|| c == method.getDeclaringClass().getTheClass())) {
} else if (!useThis && notSuperUseful(method, c)) {
methods.remove(i--); // not fit for super usage
}
}
Expand All @@ -534,8 +533,7 @@ public void methodNameAction(final Class<?> c, final MetaMethodIndex.Cache e) {
if (matchedMethod >= 0) {
if (useThis) e.methods = mopMethods[matchedMethod];
else e.methodsForSuper = mopMethods[matchedMethod];
} else if (!useThis && !isDGM(method) && (isBridge(method)
|| c == method.getDeclaringClass().getTheClass())) {
} else if (!useThis && notSuperUseful(method, c)) {
e.methodsForSuper = null; // not fit for super usage
}
}
Expand Down Expand Up @@ -576,6 +574,12 @@ private int mopArrayIndex(final MetaMethod method, final String mopName) {
return -1;
}

private boolean notSuperUseful(final MetaMethod method, final Class<?> c) {
return !isDGM(method) && (isBridge(method)
|| method.isAbstract() // GROOVY-11929
|| c == method.getDeclaringClass().getTheClass());
}

private boolean isBridge(final MetaMethod method) {
return (method.getModifiers() & Opcodes.ACC_BRIDGE) != 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,21 +207,23 @@ public Object addMethodToList(final Object o, final MetaMethod toIndex) {
* should be kept.
*/
private static boolean isOverridden(final MetaMethod inIndex, final MetaMethod toIndex) {
// do not overwrite private methods
if (inIndex.isPrivate()) return false;
// don't overwrite private method
if (inIndex.isPrivate()) {
return false;
}

CachedClass inIndexDC = inIndex.getDeclaringClass();
CachedClass toIndexDC = toIndex.getDeclaringClass();
if (inIndexDC == toIndexDC) {
return isNonRealMethod(toIndex) || inIndex.isSynthetic(); // GROOVY-10136, GROOVY-10594
return inIndex.isSynthetic() || isNonRealMethod(toIndex); // GROOVY-10136, GROOVY-10594
}

// interface vs instance method; be careful...
if (!inIndex.isStatic() && !toIndex.isStatic() // GROOVY-9815
&& inIndexDC.isInterface() != toIndexDC.isInterface()
&& !(toIndex instanceof ClosureMetaMethod || toIndex instanceof ClosureStaticMetaMethod)) { // GROOVY-3493
// this is the old logic created for GROOVY-2391 and GROOVY-7879, which was labeled as "do not overwrite interface methods with instance methods"
return (isNonRealMethod(inIndex) || !inIndexDC.isInterface() || toIndexDC.isInterface()) && !toIndexDC.isAssignableFrom(inIndexDC.getTheClass());
return (toIndexDC.isInterface() || !inIndexDC.isInterface() || isNonRealMethod(inIndex)) && !toIndexDC.isAssignableFrom(inIndexDC.getTheClass());
}

// prefer most-specific or most-recent for type disjunction
Expand Down
58 changes: 58 additions & 0 deletions src/test/groovy/bugs/Groovy11929.groovy
Original file line number Diff line number Diff line change
@@ -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 bugs

import org.junit.jupiter.api.Test

import static groovy.test.GroovyAssert.assertScript

final class Groovy11929 {

@Test
void testInvokeSpecial() {
assertScript '''
interface Dao<T> {
T save(T t)
}

abstract class AbstractDao<T> implements Dao<T> {
@Override
T save(T t) { t }
}

interface EntityDao extends Dao<Entity> {
@Override
Entity save(Entity entity) // not replaced by super$2$save(Object)
}

class EntityDaoImpl extends AbstractDao<Entity> implements EntityDao {
@Override
Entity save(Entity entity) { super.save(entity) }
}

class Entity {
long id
}

def entity = new Entity()
def dao = new EntityDaoImpl()
assert dao.save(entity) === entity
'''
}
}
Loading