This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY_3_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 21b30bf690af3bf7558b140a0bf10f775e2d66f2 Author: Eric Milles <[email protected]> AuthorDate: Thu Jun 3 15:28:00 2021 -0500 GROOVY-5453: order category methods before taking first getter/setter Conflicts: src/main/java/org/codehaus/groovy/runtime/GroovyCategorySupport.java --- src/main/java/groovy/lang/MetaClassImpl.java | 69 ++++++---------------- .../groovy/runtime/GroovyCategorySupport.java | 25 +++----- src/test/groovy/CategoryTest.groovy | 34 +++++++---- 3 files changed, 51 insertions(+), 77 deletions(-) diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java index 1b71bc0..7742b8b 100644 --- a/src/main/java/groovy/lang/MetaClassImpl.java +++ b/src/main/java/groovy/lang/MetaClassImpl.java @@ -2158,61 +2158,30 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass { return tuple(method, mp); } - private static MetaMethod getCategoryMethodMissing(Class sender) { - List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(METHOD_MISSING); - if (possibleGenericMethods != null) { - for (Object possibleGenericMethod : possibleGenericMethods) { - MetaMethod mmethod = (MetaMethod) possibleGenericMethod; - if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender)) - continue; - - CachedClass[] paramTypes = mmethod.getParameterTypes(); - if (paramTypes.length == 2 && paramTypes[0].getTheClass() == String.class) { - return mmethod; - } - } - } - return null; + private static CategoryMethod getCategoryMethodMissing(final Class<?> sender) { + return findCategoryMethod(METHOD_MISSING, sender, params -> + params.length == 2 && params[0].getTheClass() == String.class + ); } - private static MetaMethod getCategoryMethodGetter(Class sender, String name, boolean useLongVersion) { - List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(name); - if (possibleGenericMethods != null) { - for (Object possibleGenericMethod : possibleGenericMethods) { - MetaMethod mmethod = (MetaMethod) possibleGenericMethod; - if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender)) - continue; - - CachedClass[] paramTypes = mmethod.getParameterTypes(); - if (useLongVersion) { - if (paramTypes.length == 1 && paramTypes[0].getTheClass() == String.class) { - return mmethod; - } - } else { - if (paramTypes.length == 0) return mmethod; - } - } - } - return null; + private static CategoryMethod getCategoryMethodGetter(final Class<?> sender, final String name, final boolean useLongVersion) { + return findCategoryMethod(name, sender, params -> + useLongVersion ? params.length == 1 && params[0].getTheClass() == String.class : params.length == 0 + ); } - private static MetaMethod getCategoryMethodSetter(Class sender, String name, boolean useLongVersion) { - List possibleGenericMethods = GroovyCategorySupport.getCategoryMethods(name); - if (possibleGenericMethods != null) { - for (Object possibleGenericMethod : possibleGenericMethods) { - MetaMethod mmethod = (MetaMethod) possibleGenericMethod; - if (!mmethod.getDeclaringClass().getTheClass().isAssignableFrom(sender)) - continue; + private static CategoryMethod getCategoryMethodSetter(final Class<?> sender, final String name, final boolean useLongVersion) { + return findCategoryMethod(name, sender, params -> + useLongVersion ? params.length == 2 && params[0].getTheClass() == String.class : params.length == 1 + ); + } - CachedClass[] paramTypes = mmethod.getParameterTypes(); - if (useLongVersion) { - if (paramTypes.length == 2 && paramTypes[0].getTheClass() == String.class) { - return mmethod; - } - } else { - if (paramTypes.length == 1) return mmethod; - } - } + private static CategoryMethod findCategoryMethod(final String name, final Class<?> sender, final java.util.function.Predicate<CachedClass[]> paramFilter) { + List<CategoryMethod> categoryMethods = GroovyCategorySupport.getCategoryMethods(name); + if (categoryMethods != null) { + return categoryMethods.stream().filter(categoryMethod -> + categoryMethod.getDeclaringClass().isAssignableFrom(sender) && paramFilter.test(categoryMethod.getParameterTypes()) + ).sorted().findFirst().orElse(null); } return null; } diff --git a/src/main/java/org/codehaus/groovy/runtime/GroovyCategorySupport.java b/src/main/java/org/codehaus/groovy/runtime/GroovyCategorySupport.java index c96780f..ff872fc 100644 --- a/src/main/java/org/codehaus/groovy/runtime/GroovyCategorySupport.java +++ b/src/main/java/org/codehaus/groovy/runtime/GroovyCategorySupport.java @@ -228,27 +228,18 @@ public class GroovyCategorySupport { /** * Sort by most specific to least specific. * - * @param o the object to compare against + * @param that the object to compare against */ - public int compareTo(Object o) { - CategoryMethod thatMethod = (CategoryMethod) o; + @Override + public int compareTo(final Object that) { Class thisClass = metaClass; - Class thatClass = thatMethod.metaClass; + Class thatClass = ((CategoryMethod) that).metaClass; + if (thisClass == thatClass) return 0; - if (isChildOfParent(thisClass, thatClass)) return -1; - if (isChildOfParent(thatClass, thisClass)) return 1; - return 0; - } + if (thisClass.isAssignableFrom(thatClass)) return 1; + if (thatClass.isAssignableFrom(thisClass)) return -1; - private boolean isChildOfParent(Class candidateChild, Class candidateParent) { - Class loop = candidateChild; - while(loop != null && loop != Object.class) { - loop = loop.getSuperclass(); - if (loop == candidateParent) { - return true; - } - } - return false; + return 0; } } diff --git a/src/test/groovy/CategoryTest.groovy b/src/test/groovy/CategoryTest.groovy index 1dbbb99..2a7f73f 100644 --- a/src/test/groovy/CategoryTest.groovy +++ b/src/test/groovy/CategoryTest.groovy @@ -180,15 +180,15 @@ final class CategoryTest extends GroovyTestCase { """ } - def foo(x){x.bar()} + void testMethodHiding1() { def x = new X() assert foo(x) == 1 use (XCat) { - assert foo(x) == 2 - def t = Thread.start {assert foo(x)==1} - t.join() + assert foo(x) == 2 + def t = Thread.start {assert foo(x)==1} + t.join() } assert foo(x) == 1 def t = Thread.start {use (XCat2){assert foo(x)==3}} @@ -200,12 +200,12 @@ final class CategoryTest extends GroovyTestCase { def x = new X() assert foo(x) == 1 use (XCat) { - assert foo(x) == 2 - def t = Thread.start {use (XCat2){assert foo(x)==3}} - t.join() - assert foo(x) == 2 - t = Thread.start {assert foo(x)==1} - t.join() + assert foo(x) == 2 + def t = Thread.start {use (XCat2){assert foo(x)==3}} + t.join() + assert foo(x) == 2 + t = Thread.start {assert foo(x)==1} + t.join() } assert foo(x) == 1 def t = Thread.start {use (XCat2){assert foo(x)==3}} @@ -248,6 +248,20 @@ final class CategoryTest extends GroovyTestCase { ''' } + // GROOVY-5453 + void testOverloadedGetterMethod() { + assertScript ''' + class Cat { + static getFoo(String s) {'String'} + static getFoo(CharSequence s) {'CharSequence'} + } + use (Cat) { + assert 'abc'.getFoo() == 'String' + assert 'abc'.foo == 'String' + } + ''' + } + // GROOVY-3867 void testPropertyMissing() { def x = new X()
