This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 8ca3424ebada3b8beb3586f61cb1328e061b9556
Author: Eric Milles <[email protected]>
AuthorDate: Tue Dec 30 15:03:25 2025 -0600

    GROOVY-11813: check category method declaring class against `theClass`
---
 src/main/java/groovy/lang/MetaClassImpl.java | 24 ++++++++++----------
 src/test/groovy/groovy/CategoryTest.groovy   | 21 +++++++++++++++--
 src/test/groovy/groovy/MetaClassCreator.java | 34 ++++++++++++++++++++++++++++
 3 files changed, 65 insertions(+), 14 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java 
b/src/main/java/groovy/lang/MetaClassImpl.java
index 767ad24801..98a25a1c9c 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -694,21 +694,21 @@ public class MetaClassImpl implements MetaClass, 
MutableMetaClass {
         if (answer == null) answer = FastArray.EMPTY_LIST;
 
         if (!isCallToSuper) {
-            List<CategoryMethod> used = 
GroovyCategorySupport.getCategoryMethods(name);
-            if (used != null) {
-                FastArray arr;
-                if (answer instanceof MetaMethod) {
-                    arr = new FastArray();
-                    arr.add(answer);
+            List<CategoryMethod> methods = 
GroovyCategorySupport.getCategoryMethods(name);
+            if (methods != null) {
+                FastArray array;
+                if (answer instanceof FastArray fastArray) {
+                    array = fastArray.copy();
                 } else {
-                    arr = ((FastArray) answer).copy();
+                    array = new FastArray();
+                    array.add(answer);
                 }
-                for (CategoryMethod cm : used) {
-                    if 
(!cm.getDeclaringClass().getTheClass().isAssignableFrom(sender))
-                        continue;
-                    filterMatchingMethodForCategory(arr, cm);
+                for (CategoryMethod cm : methods) {
+                    Class<?> cmdc = cm.getDeclaringClass().getTheClass();
+                    if (cmdc.isAssignableFrom(theClass)) // GROOVY-11813: not 
sender
+                        filterMatchingMethodForCategory(array, cm);
                 }
-                answer = arr;
+                answer = array;
             }
         }
         return answer;
diff --git a/src/test/groovy/groovy/CategoryTest.groovy 
b/src/test/groovy/groovy/CategoryTest.groovy
index 9584918242..848410404e 100644
--- a/src/test/groovy/groovy/CategoryTest.groovy
+++ b/src/test/groovy/groovy/CategoryTest.groovy
@@ -390,7 +390,7 @@ final class CategoryTest {
     @Test
     void testOverloadedGetterMethod2() {
         assertScript '''
-            class Cat {
+            class C {
                 static String getFoo(Boolean self) {
                     'Boolean'
                 }
@@ -414,7 +414,7 @@ final class CategoryTest {
                 }
             }
 
-            use(Cat) {
+            use(C) {
                 assert 123.foo == 'Integer'
                 assert 4.5d.foo == 'Double'
             }
@@ -432,6 +432,23 @@ final class CategoryTest {
         '''
     }
 
+    // GROOVY-11813
+    @Test
+    void testCategoryOperatorMethodAndCustomMetaClass() {
+        assertScript '''
+            import groovy.MetaClassCreator
+            import groovy.time.TimeCategory
+
+            GroovySystem.metaClassRegistry.metaClassCreationHandle = new 
MetaClassCreator()
+
+            use(TimeCategory) {
+                def date = new Date()
+                def duration = 7.months
+                return (date - duration)
+            }
+        '''
+    }
+
     
//--------------------------------------------------------------------------
 
     static class X     { def bar() {1} }
diff --git a/src/test/groovy/groovy/MetaClassCreator.java 
b/src/test/groovy/groovy/MetaClassCreator.java
new file mode 100644
index 0000000000..8d1ff93ab1
--- /dev/null
+++ b/src/test/groovy/groovy/MetaClassCreator.java
@@ -0,0 +1,34 @@
+/*
+ *  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;
+
+import groovy.lang.MetaClass;
+import groovy.lang.MetaClassImpl;
+import groovy.lang.MetaClassRegistry;
+import org.codehaus.groovy.runtime.GeneratedClosure;
+
+public class MetaClassCreator extends 
MetaClassRegistry.MetaClassCreationHandle {
+    @Override
+    protected MetaClass createNormalMetaClass(Class theClass, 
MetaClassRegistry registry) {
+        if (!theClass.isAnonymousClass() && 
!GeneratedClosure.class.isAssignableFrom(theClass)) {
+            return new MetaClassImpl(registry, theClass) { }; // GROOVY-11813
+        }
+        return super.createNormalMetaClass(theClass, registry);
+    }
+}

Reply via email to