You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/05/31 15:29:19 UTC

[groovy] 01/01: GROOVY-9580: declaring class of getter/setter should be same as property

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

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

commit c52c6275e77713ef47a582eaff1f0871f48a3e76
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun May 31 10:21:16 2020 -0500

    GROOVY-9580: declaring class of getter/setter should be same as property
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  20 +--
 src/test/groovy/bugs/Groovy7691Bug.groovy          |  99 ------------
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 169 +++++++++++++++++----
 3 files changed, 145 insertions(+), 143 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 67e1d99..a0b10eb 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4636,14 +4636,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         curNode = curNode.getSuperClass();
                     }
                     if (property != null) {
-                        MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
-                        if (property.isStatic()) {
-                            node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
-                        }
-                        node.setDeclaringClass(receiver);
-                        return Collections.singletonList(
-                                node);
-
+                        int mods = Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0);
+                        MethodNode node = new MethodNode(name, mods, property.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
+                        node.setDeclaringClass(property.getDeclaringClass());
+                        return Collections.singletonList(node);
                     }
                 }
             } else if (methods.isEmpty() && args != null && args.length == 1) {
@@ -4659,11 +4655,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     if (property != null) {
                         ClassNode type = property.getOriginType();
                         if (implementsInterfaceOrIsSubclassOf(wrapTypeIfNecessary(args[0]), wrapTypeIfNecessary(type))) {
-                            MethodNode node = new MethodNode(name, Opcodes.ACC_PUBLIC, VOID_TYPE, new Parameter[]{new Parameter(type, "arg")}, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
-                            if (property.isStatic()) {
-                                node.setModifiers(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC);
-                            }
-                            node.setDeclaringClass(receiver);
+                            int mods = Opcodes.ACC_PUBLIC | (property.isStatic() ? Opcodes.ACC_STATIC : 0);
+                            MethodNode node = new MethodNode(name, mods, VOID_TYPE, new Parameter[]{new Parameter(type, name)}, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
+                            node.setDeclaringClass(property.getDeclaringClass());
                             return Collections.singletonList(node);
                         }
                     }
diff --git a/src/test/groovy/bugs/Groovy7691Bug.groovy b/src/test/groovy/bugs/Groovy7691Bug.groovy
deleted file mode 100644
index 5ffe0ee..0000000
--- a/src/test/groovy/bugs/Groovy7691Bug.groovy
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- *  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
-
-import groovy.test.GroovyTestCase
-
-class Groovy7691Bug extends GroovyTestCase {
-//    @NotYetImplemented
-    void testCovariantGenericField() {
-        assertScript '''
-            @groovy.transform.CompileStatic
-            abstract class AbstractNumberWrapper<S extends Number> {
-                protected final S number;
-
-                AbstractNumberWrapper(S number) {
-                    this.number = number
-                }
-            }
-            @groovy.transform.CompileStatic
-            class LongWrapper<S extends Long> extends AbstractNumberWrapper<S> {
-                LongWrapper(S longNumber) {
-                    super(longNumber)
-                }
-
-                S getValue() {
-                    return number;
-                }
-            }
-            assert new LongWrapper<Long>(42L).value == 42L
-        '''
-    }
-
-    void testCovariantGenericProperty() {
-        assertScript '''
-            @groovy.transform.CompileStatic
-            abstract class AbstractNumberWrapper<S extends Number> {
-                def S number;
-
-                AbstractNumberWrapper(S number) {
-                    this.number = number
-                }
-            }
-            @groovy.transform.CompileStatic
-            class LongWrapper<S extends Long> extends AbstractNumberWrapper<S> {
-                LongWrapper(S longNumber) {
-                    super(longNumber)
-                }
-
-                S getValue() {
-                    return number;
-                }
-            }
-            assert new LongWrapper<Long>(42L).value == 42L
-        '''
-    }
-
-    // this test can pass even if GROOVY-7691 is not resolved, just for ensuring the common case will pass test all the time!
-    void testCovariantGenericMethod() {
-        assertScript '''
-            @groovy.transform.CompileStatic
-            abstract class AbstractNumberWrapper<S extends Number> {
-                protected final S number;
-
-                AbstractNumberWrapper(S number) {
-                    this.number = number
-                }
-                
-                protected S getNumber() { return number; }
-            }
-            @groovy.transform.CompileStatic
-            class LongWrapper<S extends Long> extends AbstractNumberWrapper<S> {
-                LongWrapper(S longNumber) {
-                    super(longNumber)
-                }
-
-                S getValue() {
-                    return getNumber();
-                }
-            }
-            assert new LongWrapper<Long>(42L).value == 42L
-        '''
-    }
-}
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 90c62ee..a924ab8 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1697,42 +1697,45 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
 
     // GROOVY-6731
     void testContravariantMethodResolution() {
-        assertScript '''interface Function<T, R> {
-
-    R apply(T t)
+        assertScript '''
+            interface Function<T, R> {
+                R apply(T t)
+            }
 
-}
-public <I, O> void transform(Function<? super I, ? extends O> function) { function.apply('')}
+            public <I, O> void transform(Function<? super I, ? extends O> function) {
+                function.apply('')
+            }
 
-String result = null
-transform(new Function<String, String>() {
+            String result = null
+            transform(new Function<String, String>() {
+                String apply(String input) {
+                    result = "ok"
+                }
+            })
 
-    String apply(String input) {
-        result = "ok"
+            assert result == 'ok'
+        '''
     }
-})
 
-assert result == 'ok\''''
-    }
     void testContravariantMethodResolutionWithImplicitCoercion() {
-        assertScript '''interface Function<T, R> {
-
-    R apply(T t)
-
-}
-public <I, O> void transform(Function<? super I, ? extends O> function) { function.apply('')}
-
-String result = null
-transform {
-        result = "ok"
-}
+        assertScript '''
+            interface Function<T, R> {
+                R apply(T t)
+            }
 
+            public <I, O> void transform(Function<? super I, ? extends O> function) {
+                function.apply('')
+            }
 
-assert result == 'ok'
-'''
+            String result = null
+            transform {
+                result = 'ok'
+            }
+            assert result == 'ok'
+        '''
     }
 
-    void testGROOVY5981(){
+    void testGROOVY5981() {
         assertScript '''
             import javax.swing.*
             import java.awt.*
@@ -1772,6 +1775,113 @@ assert result == 'ok'
         '''
     }
 
+    // GROOVY-7691
+    void testCovariantReturnTypeInferredFromField() {
+        assertScript '''
+            import groovy.transform.*
+
+            @CompileStatic
+            @TupleConstructor(includeFields=true)
+            abstract class A<N extends Number> {
+                protected final N number
+            }
+
+            @CompileStatic
+            class C<L extends Long> extends A<L> { // further restriction of type parameter
+                C(L longNumber) {
+                    super(longNumber)
+                }
+
+                L getValue() {
+                    return number
+                }
+            }
+
+            assert new C<Long>(42L).value == 42L
+        '''
+    }
+
+    // GROOVY-7691
+    void testCovariantReturnTypeInferredFromProperty() {
+        assertScript '''
+            import groovy.transform.*
+
+            @CompileStatic
+            @TupleConstructor
+            abstract class A<N extends Number> {
+                final N number
+            }
+
+            @CompileStatic
+            class C<L extends Long> extends A<L> {
+                C(L longNumber) {
+                    super(longNumber)
+                }
+
+                L getValue() {
+                    return number
+                }
+            }
+
+            assert new C<Long>(42L).value == 42L
+        '''
+    }
+
+    void testCovariantReturnTypeInferredFromMethod1() {
+        assertScript '''
+            import groovy.transform.*
+
+            @CompileStatic
+            @TupleConstructor(includeFields=true)
+            abstract class A<N extends Number> {
+                protected final N number
+
+                protected N getNumber() {
+                    return number
+                }
+            }
+
+            @CompileStatic
+            class C<L extends Long> extends A<L> {
+                C(L longNumber) {
+                    super(longNumber)
+                }
+
+                L getValue() {
+                    return getNumber()
+                }
+            }
+
+            assert new C<Long>(42L).value == 42L
+        '''
+    }
+
+    // GROOVY-9580
+    void testCovariantReturnTypeInferredFromMethod2() {
+        assertScript '''
+            import groovy.transform.*
+
+            @CompileStatic
+            @TupleConstructor(includeFields=true)
+            abstract class A<N extends Number> {
+                final N number
+            }
+
+            @CompileStatic
+            class C<L extends Long> extends A<L> {
+                C(L longNumber) {
+                    super(longNumber)
+                }
+
+                L getValue() {
+                    return getNumber() // property method stubbed by StaticTypeCheckingVisitor
+                }
+            }
+
+            assert new C<Long>(42L).value == 42L
+        '''
+    }
+
     void testReturnTypeChecking() {
         shouldFailWithMessages '''
             class Foo {
@@ -1793,8 +1903,7 @@ assert result == 'ok'
         '''
     }
 
-
-    //GROOVY-7804
+    // GROOVY-7804
     void testParameterlessClosureToGenericSAMTypeArgumentCoercion() {
         assertScript '''
             interface Supplier<T> {
@@ -1807,7 +1916,7 @@ assert result == 'ok'
         '''
     }
 
-    //GROOVY-7713
+    // GROOVY-7713
     void testClosureReturnNull() {
         assertScript '''
             Closure<String> cl = {
@@ -1841,6 +1950,4 @@ assert result == 'ok'
         public static <T> List<T> unwrap(Collection<? extends Container<T>> list) {
         }
     }
-
 }
-