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

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


The following commit(s) were added to refs/heads/GROOVY_5_0_X by this push:
     new 28b19fbdc9 GROOVY-11813: check category method declaring class against 
`theClass`
28b19fbdc9 is described below

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

    GROOVY-11813: check category method declaring class against `theClass`
    
    5_0_X backport
---
 src/main/java/groovy/lang/MetaClassImpl.java      |  24 +-
 src/spec/test/metaprogramming/CategoryTest.groovy |  32 +-
 src/test/groovy/groovy/CategoryTest.groovy        | 557 +++++++++++++---------
 src/test/groovy/groovy/MetaClassCreator.java      |  34 ++
 4 files changed, 386 insertions(+), 261 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java 
b/src/main/java/groovy/lang/MetaClassImpl.java
index 36a43be020..1f90450e74 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) {
+                    array = ((FastArray) answer).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/spec/test/metaprogramming/CategoryTest.groovy 
b/src/spec/test/metaprogramming/CategoryTest.groovy
index 1d528c6bbc..6a19dd106a 100644
--- a/src/spec/test/metaprogramming/CategoryTest.groovy
+++ b/src/spec/test/metaprogramming/CategoryTest.groovy
@@ -18,14 +18,17 @@
  */
 package metaprogramming
 
-import groovy.test.GroovyTestCase
 import groovy.time.TimeCategory
+import org.junit.jupiter.api.Test
 
-class CategoryTest extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
 
+final class CategoryTest {
+
+    @Test
     void testApplyTimeCategory() {
         // tag::time_category[]
-        use(TimeCategory)  {
+        use(TimeCategory) {
             println 1.minute.from.now       // <1>
             println 10.hours.ago
 
@@ -35,6 +38,7 @@ class CategoryTest extends GroovyTestCase {
         // end::time_category[]
     }
 
+    @Test
     void testCategoryAnnotation() {
         assertScript '''
             // tag::time_category_anno[]
@@ -50,30 +54,10 @@ class CategoryTest extends GroovyTestCase {
                 }
             }
 
-            use (NumberCategory)  {
+            use(NumberCategory) {
                 assert 42.meters.toString() == '42m'
             }
             // end::time_category_anno[]
         '''
     }
-
-    // GROOVY-8433
-    void testCategoryAnnotationAndAIC() {
-        assertScript '''
-            @Category(Number)
-            class NumberCategory {
-                def m() {
-                    String variable = 'works'
-                    new Object() { // "Cannot cast object '1' with class 
'java.lang.Integer' to class 'NumberCategory'" due to implicit "this"
-                        String toString() { variable }
-                    }
-                }
-            }
-
-            use (NumberCategory) {
-                String result = 1.m()
-                assert result == 'works'
-            }
-        '''
-    }
 }
diff --git a/src/test/groovy/groovy/CategoryTest.groovy 
b/src/test/groovy/groovy/CategoryTest.groovy
index 0723180c13..45dc573c11 100644
--- a/src/test/groovy/groovy/CategoryTest.groovy
+++ b/src/test/groovy/groovy/CategoryTest.groovy
@@ -18,71 +18,95 @@
  */
 package groovy
 
-import groovy.test.GroovyTestCase
+import org.junit.jupiter.api.Test
 
-final class CategoryTest extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+import static org.junit.jupiter.api.Assertions.assertThrows
 
-    @Override
-    protected void setUp() {
-        def dummy = null
-        CategoryTestPropertyCategory.setSomething(dummy, 'hello')
-        CategoryTestHelperPropertyReplacer.setaProperty(dummy, 'anotherValue')
+final class CategoryTest {
+
+    static class StringCategory {
+        static String lower(String s) {
+            s.toLowerCase()
+        }
     }
 
-    void testCategories() {
-        use (StringCategory) {
-            assert "Sam".lower() == "sam";
-            use (IntegerCategory.class) {
-                assert "Sam".lower() == "sam";
-                assert 1.inc() == 2;
+    static class IntegerCategory {
+        static Integer inc(Integer i) {
+            i + 1
+        }
+    }
+
+    @Test
+    void testNestingOfCategories() {
+        use(StringCategory) {
+            assert 'Sam'.lower() == 'sam'
+            use(IntegerCategory) {
+                assert 9.inc() == 10
+                assert 'Sam'.lower() == 'sam'
             }
-            shouldFail(MissingMethodException, { 1.inc() });
+            assertThrows(MissingMethodException) { 1.inc() }
         }
-        shouldFail(MissingMethodException, { "Sam".lower() });
+        assertThrows(MissingMethodException) { 'Sam'.lower() }
     }
 
+    @Test
     void testReturnValueWithUseClass() {
         def returnValue = use(StringCategory) {
-            "Green Eggs And Ham".lower()
+            'Green Eggs And Ham'.lower()
         }
-        assert "green eggs and ham" == returnValue
+        assert returnValue == 'green eggs and ham'
     }
 
-    void testReturnValueWithUseList() {
+    @Test
+    void testReturnValueWithUseClassList() {
         def returnValue = use([StringCategory, IntegerCategory]) {
-            "Green Eggs And Ham".lower() + 5.inc()
+            'Green Eggs And Ham'.lower() + 5.inc()
         }
-        assert "green eggs and ham6" == returnValue
+        assert returnValue == 'green eggs and ham6'
     }
 
+    
//--------------------------------------------------------------------------
+
+    @Test
     void testCategoryDefinedProperties() {
-        use(CategoryTestPropertyCategory) {
-            assert getSomething() == "hello"
-            assert something == "hello"
-            something = "nihao"
-            assert something == "nihao"
-        }
+        assertScript '''
+            class CategoryTestPropertyCategory {
+                private static aVal = 'hello'
+                static getSomething(Object self) { return aVal }
+                static void setSomething(Object self, newValue) { aVal = 
newValue }
+            }
 
-        // test the new value again in a new block
-        use(CategoryTestPropertyCategory) {
-            assert something == "nihao"
-        }
+            use(CategoryTestPropertyCategory) {
+                assert getSomething() == 'hello'
+                assert something == 'hello'
+                something = 'nihao'
+                assert something == 'nihao'
+            }
+            // test the new value again in a new block
+            use(CategoryTestPropertyCategory) {
+                assert something == 'nihao'
+            }
+        '''
     }
 
     // GROOVY-10133
+    @Test
     void testCategoryDefinedProperties2() {
         assertScript '''
             class Cat {
                 static boolean isAbc(self) { true }
                 static boolean getAbc(self) { false }
             }
-            use (Cat) {
-                assert abc // should select "isAbc()"
+
+            use(Cat) {
+                assert abc // should select isAbc()
             }
         '''
     }
 
     // GROOVY-5245
+    @Test
     void testCategoryDefinedProperties3() {
         assertScript '''
             class Isser {
@@ -92,7 +116,8 @@ final class CategoryTest extends GroovyTestCase {
                 static boolean getWorking2(Isser b) { true }
                 static boolean isNotWorking(Isser b) { true }
             }
-            use (IsserCat) {
+
+            use(IsserCat) {
                 assert new Isser().working
                 assert new Isser().working2
                 assert new Isser().notWorking // MissingPropertyException
@@ -100,161 +125,225 @@ final class CategoryTest extends GroovyTestCase {
         '''
     }
 
-    void testCategoryReplacedPropertyAccessMethod() {
-        def cth = new CategoryTestHelper()
-        cth.aProperty = "aValue"
-        assert cth.aProperty == "aValue"
-        use (CategoryTestHelperPropertyReplacer) {
-            assert cth.aProperty == "anotherValue"
-            cth.aProperty = "this is boring"
-            assert cth.aProperty == "this is boring"
-        }
-        assert cth.aProperty == "aValue"
+    @Test
+    void testCategoryMethodReplacesPropertyAccessMethod() {
+        assertScript '''
+            class CategoryTestHelper {
+                def aProperty = 'aValue'
+            }
+            class CategoryTestHelperPropertyReplacer {
+                private static aVal = 'anotherValue'
+                static getaProperty(CategoryTestHelper self) { return aVal }
+                static void setaProperty(CategoryTestHelper self, newValue) { 
aVal = newValue }
+            }
+
+            def cth = new CategoryTestHelper()
+            cth.aProperty = 'aValue'
+            assert cth.aProperty == 'aValue'
+            use(CategoryTestHelperPropertyReplacer) {
+                assert cth.aProperty == 'anotherValue'
+                cth.aProperty = 'this is boring'
+                assert cth.aProperty == 'this is boring'
+            }
+            assert cth.aProperty == 'aValue'
+        '''
     }
 
+    // GROOVY-11820
+    @Test
+    void testCategoryMethodHiddenByPropertyAccessMethod() {
+        assertScript '''import java.lang.reflect.Field
+            class Pogo {
+                public float field
+            }
+
+            Field field = Pogo.fields.first()
+            assert field.getType() == float
+            assert field.type == float
+
+            @Category(Field)
+            class FieldCat {
+                def getType() { 'override' }
+            }
+
+            use(FieldCat) {
+                assert field.getType() == 'override'
+                assert field.type == 'override'
+            }
+
+            @Category(Object)
+            class ObjectCat {
+                def getType() { 'override' }
+            }
+
+            use(ObjectCat) { // class method is closer than category method
+                assert field.getType() == float
+              //assert field.type == float TODO
+            }
+        '''
+    }
+
+    @Test
     void testCategoryHiddenByClassMethod() {
-      assertScript """
-         class A{}
-         class B extends A{def m(){1}}
-         class Category{ static m(A a) {2}}
-         def b = new B()
-         use (Category) {
-           assert b.m() == 1
-         }
-      """
+        assertScript '''
+            class A {
+            }
+            class B extends A {
+                def m() { 1 }
+            }
+            class C {
+                static m(A a) { 2 }
+            }
+
+            def b = new B()
+            use(C) {
+                assert b.m() == 1
+            }
+        '''
     }
 
+    @Test
     void testCategoryOverridingClassMethod() {
-      assertScript """
-         class A {def m(){1}}
-         class Category{ static m(A a) {2}}
-         def a = new A()
-         use (Category) {
-           assert a.m() == 2
-         }
-      """
-      assertScript """
-         class A {def m(){1}}
-         class B extends A{}
-         class Category{ static m(A a) {2}}
-         def a = new B()
-         use (Category) {
-           assert a.m() == 2
-         }
-      """
+        assertScript '''
+            class A {
+                def m() { 1 }
+            }
+            class C {
+                static m(A a) { 2 }
+            }
+
+            def a = new A()
+            use(C) {
+                assert a.m() == 2
+            }
+        '''
+    }
+
+    @Test
+    void testCategoryOverridingClassMethod2() {
+        assertScript '''
+            class A {
+                def m() { 1 }
+            }
+            class B extends A {
+            }
+            class C {
+                static m(A a) { 2 }
+            }
+
+            def a = new B()
+            use(C) {
+                assert a.m() == 2
+            }
+        '''
     }
 
+    @Test
     void testCategoryWithMixedOverriding() {
-      assertScript """
-         class A{def m(){0}}
-         class B extends A{def m(){1}}
-         class Category{ static m(A a) {2}}
-         def b = new B()
-         use (Category) {
-           assert b.m() == 1
-         }
-      """
+        assertScript '''
+            class A {
+                def m() { 0 }
+            }
+            class B extends A {
+                def m() { 1 }
+            }
+            class C {
+                static m(A a) { 2 }
+            }
+
+            def b = new B()
+            use(C) {
+                assert b.m() == 1
+            }
+        '''
     }
 
+    @Test
     void testCategoryInheritance() {
-      assertScript """
-        public class Foo {
-          static Object foo(Object obj) {
-            "Foo.foo()"
-          }
-        }
-
-        public class Bar extends Foo{
-          static Object bar(Object obj) {
-            "Bar.bar()"
-          }
-        }
+        assertScript '''
+            class Foo {
+                static Object foo(Object obj) {
+                    'Foo.foo()'
+                }
+            }
+            class Bar extends Foo {
+                static Object bar(Object obj) {
+                    'Bar.bar()'
+                }
+            }
 
-        def obj = new Object()
+            def obj = new Object()
+            use(Foo) {
+                assert obj.foo() == 'Foo.foo()'
+            }
+            use(Bar) {
+                assert obj.bar() == 'Bar.bar()'
+                assert obj.foo() == 'Foo.foo()'
+            }
+        '''
+    }
 
-        use(Foo){
-          assert obj.foo() == "Foo.foo()"
-        }
+    // GROOVY-8433
+    @Test
+    void testCategoryAnnotationAndAIC() {
+        assertScript '''
+            @Category(Number)
+            class NumberCategory {
+                def m() {
+                    String variable = 'works'
+                    new Object() { // "Cannot cast object '1' with class 
'java.lang.Integer' to class 'NumberCategory'" due to implicit "this"
+                        String toString() { variable }
+                    }
+                }
+            }
 
-        use(Bar){
-          assert obj.bar() == "Bar.bar()"
-          assert obj.foo() == "Foo.foo()"
-        }
-      """
+            use(NumberCategory) {
+                String result = 1.m()
+                assert result == 'works'
+            }
+        '''
     }
 
+    // GROOVY-5248
+    @Test
     void testNullReceiverChangeForPOJO() {
-        // GROOVY-5248
         // this test will call a method using a POJO while a category is active
         // in call site caching this triggers the usage of POJOMetaClassSite,
         // which was missing a null check for the receiver. The last foo call
         // uses null to exactly check that path. I use multiple calls with 
foo(1)
         // before to ensure for example indy will do the right things as well,
         // since indy may need more than one call here.
-        assertScript """
-            class Cat {
-              public static findAll(Integer x, Closure cl) {1}
-            }
-
-             def foo(x) {
-                 x.findAll {}
-             }
-
-             use (Cat) {
-                 assert foo(1) == 1
-                 assert foo(1) == 1
-                 assert foo(1) == 1
-                 assert foo(null) == []
-                 assert foo(1) == 1
-                 assert foo(1) == 1
-                 assert foo(1) == 1
-             }
-        """
-    }
-
-    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) == 1
-        def t = Thread.start {use (XCat2){assert foo(x)==3}}
-        t.join()
-        assert foo(x) == 1
-    }
+        assertScript '''
+            class C {
+                static findAll(Integer x, Closure c) { 1 }
+            }
+            def foo(x) {
+                x.findAll { -> }
+            }
 
-    void testMethodHiding2() {
-        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) == 1
-        def t = Thread.start {use (XCat2){assert foo(x)==3}}
-        t.join()
-        assert foo(x) == 1
+            use(C) {
+                assert foo(1) == 1
+                assert foo(1) == 1
+                assert foo(1) == 1
+                assert foo() == []
+                assert foo(1) == 1
+                assert foo(1) == 1
+                assert foo(1) == 1
+            }
+        '''
     }
 
+    @Test
     void testCallToPrivateMethod1() {
         assertScript '''
             class A {
                 private foo() { 1 }
                 def baz() { foo() }
             }
-
-            class B extends A {}
-
-            class C {}
+            class B extends A {
+            }
+            class C {
+            }
 
             use(C) {
                 assert new B().baz() == 1
@@ -263,16 +352,17 @@ final class CategoryTest extends GroovyTestCase {
     }
 
     // GROOVY-6263
+    @Test
     void testCallToPrivateMethod2() {
         assertScript '''
             class A {
                 private foo(a) { 1 }
                 def baz() { foo() }
             }
-
-            class B extends A {}
-
-            class C {}
+            class B extends A {
+            }
+            class C {
+            }
 
             use(C) {
                 assert new B().baz() == 1
@@ -281,13 +371,15 @@ final class CategoryTest extends GroovyTestCase {
     }
 
     // GROOVY-5453
+    @Test
     void testOverloadedGetterMethod1() {
         assertScript '''
-            class Cat {
-                static getFoo(String s) {'String'}
-                static getFoo(CharSequence s) {'CharSequence'}
+            class C {
+                static getFoo(String s) { 'String' }
+                static getFoo(CharSequence s) { 'CharSequence' }
             }
-            use (Cat) {
+
+            use(C) {
                 assert 'abc'.getFoo() == 'String'
                 assert 'abc'.foo      == 'String'
             }
@@ -295,9 +387,10 @@ final class CategoryTest extends GroovyTestCase {
     }
 
     // GROOVY-10214
+    @Test
     void testOverloadedGetterMethod2() {
         assertScript '''
-            class Cat {
+            class C {
                 static String getFoo(Boolean self) {
                     'Boolean'
                 }
@@ -320,7 +413,8 @@ final class CategoryTest extends GroovyTestCase {
                     'Double'
                 }
             }
-            use (Cat) {
+
+            use(C) {
                 assert 123.foo == 'Integer'
                 assert 4.5d.foo == 'Double'
             }
@@ -328,6 +422,7 @@ final class CategoryTest extends GroovyTestCase {
     }
 
     // GROOVY-10743
+    @Test
     void testStaticMethodOnInterface() {
         assertScript '''
             use(java.util.stream.Stream) {
@@ -337,96 +432,108 @@ final class CategoryTest extends GroovyTestCase {
         '''
     }
 
-    // GROOVY-3867
-    void testPropertyMissing() {
-        def x = new X()
-
-        shouldFail(MissingPropertyException) {
-            assert x.baz != "works" // accessing x.baz should throw MPE
-        }
+    // GROOVY-11813
+    @Test
+    void testCategoryOperatorMethodAndCustomMetaClass() {
+        assertScript '''
+            import groovy.MetaClassCreator
+            import groovy.time.TimeCategory
 
-        use(XCat4) {
-            assert x.baz == "works"
-        }
+            GroovySystem.metaClassRegistry.metaClassCreationHandle = new 
MetaClassCreator()
 
-        shouldFail(MissingPropertyException) {
-            assert x.baz != "works" // accessing x.baz should throw MPE
-        }
+            use(TimeCategory) {
+                def date = new Date()
+                def duration = 7.months
+                return (date - duration)
+            }
+        '''
     }
 
-    // GROOVY-10783
-    void testPropertyMissing2() {
-        assertScript '''\
-            class X{ def bar(){1}}
-            class XCat4{ static propertyMissing(X x, String name) {"works"}}
+    
//--------------------------------------------------------------------------
 
-            def x = new X()
+    static class X     { def bar() {1} }
+    static class XCat  { static bar(X x) {2} }
+    static class XCat2 { static bar(X x) {3} }
+    static class XCat3 { static methodMissing(X x, String name, args) {4} }
+    static class XCat4 { static propertyMissing(X x, String name) {'works'} }
 
-            use(XCat4) {
-                assert x.baz == "works"
-            }
-        '''
+    def foo(x) { x.bar() }
+
+    @Test
+    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) == 1
+        def t = Thread.start {use(XCat2){assert foo(x)==3}}
+        t.join()
+        assert foo(x) == 1
+    }
+
+    @Test
+    void testMethodHiding2() {
+        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) == 1
+        def t = Thread.start {use(XCat2){assert foo(x)==3}}
+        t.join()
+        assert foo(x) == 1
     }
 
     // GROOVY-3867
+    @Test
     void testMethodMissing() {
         def x = new X()
         assert foo(x) == 1
-        use (XCat3) {
+        use(XCat3) {
             assert foo(x) == 1 // regular foo() is not affected by 
methodMissing in category
             assert x.baz() == 4 // XCat3.methodMissing is called
         }
         assert foo(x) == 1
-        def t = Thread.start {use (XCat3){assert x.baz()==4}}
+        def t = Thread.start {use(XCat3){assert x.baz()==4}}
         t.join()
         assert foo(x) == 1
-        shouldFail(MissingMethodException) {
+        assertThrows(MissingMethodException) {
             x.baz()
         }
     }
 
     // GROOVY-3867
+    @Test
     void testMethodMissingNoStatic() {
         def x = new X()
-        use (XCat3) {
+        use(XCat3) {
             assert x.baz() == 4 // XCat3.methodMissing is called for instance
-            shouldFail(MissingMethodException) {
+            assertThrows(MissingMethodException) {
                 assert X.baz() != 4 // XCat3.methodMissing should not be 
called for static method of X
             }
         }
     }
-}
-
-class X{ def bar(){1}}
-class XCat{ static bar(X x){2}}
-class XCat2{ static bar(X x){3}}
-class XCat3{ static methodMissing(X x, String name, args) {4}}
-class XCat4{ static propertyMissing(X x, String name) {"works"}}
-
-class StringCategory {
-    static String lower(String string) {
-        return string.toLowerCase();
-    }
-}
 
-class IntegerCategory {
-    static Integer inc(Integer i) {
-        return i + 1;
+    // GROOVY-3867, GROOVY-10783
+    @Test
+    void testPropertyMissing() {
+        def x = new X()
+        assertThrows(MissingPropertyException) {
+            assert x.baz != 'works' // accessing x.baz should throw MPE
+        }
+        use(XCat4) {
+            assert x.baz == 'works'
+        }
+        assertThrows(MissingPropertyException) {
+            assert x.baz != 'works' // accessing x.baz should throw MPE
+        }
     }
 }
-
-class CategoryTestPropertyCategory {
-    private static aVal = "hello"
-    static getSomething(Object self) { return aVal }
-    static void setSomething(Object self, newValue) { aVal = newValue }
-}
-
-class CategoryTestHelper {
-    def aProperty = "aValue"
-}
-
-class CategoryTestHelperPropertyReplacer {
-    private static aVal = "anotherValue"
-    static getaProperty(CategoryTestHelper self) { return aVal }
-    static void setaProperty(CategoryTestHelper self, newValue) { aVal = 
newValue }
-}
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