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 2022/03/26 15:18:40 UTC

[groovy] branch master updated: GROOVY-10548: SC: property access method without get/is prefix

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


The following commit(s) were added to refs/heads/master by this push:
     new badbcd2  GROOVY-10548: SC: property access method without get/is prefix
badbcd2 is described below

commit badbcd27f6f227af973fe7617ae216ee8078fb38
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Mar 26 10:08:41 2022 -0500

    GROOVY-10548: SC: property access method without get/is prefix
---
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |   7 +-
 .../org/codehaus/groovy/classgen/RecordTest.groovy | 167 ++++++++++++---------
 .../org/codehaus/groovy/classgen/SealedTest.groovy |   7 +-
 3 files changed, 99 insertions(+), 82 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index ce65d11..7ddcc14 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -476,14 +476,11 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter {
 
         // GROOVY-5561: if two files are compiled in the same source unit and
         // one references the other, the getters for properties have not been
-        // generated by the compiler yet (generated by the Verifier)
+        // generated by the compiler yet by Verifier
         PropertyNode propertyNode = receiverType.getProperty(propertyName);
         if (getterNode == null && propertyNode != null) {
-            // it is possible to use an accessor method
-            String prefix = isPrimitiveBoolean(propertyNode.getOriginType()) ? "is" : "get";
-            getterName = prefix + capitalize(propertyName);
             getterNode = new MethodNode(
-                    getterName,
+                    propertyNode.getGetterNameOrDefault(), // GROOVY-10548
                     ACC_PUBLIC | (propertyNode.isStatic() ? ACC_STATIC : 0),
                     propertyNode.getOriginType(),
                     Parameter.EMPTY_ARRAY,
diff --git a/src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy b/src/test/org/codehaus/groovy/classgen/RecordTest.groovy
similarity index 83%
rename from src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy
rename to src/test/org/codehaus/groovy/classgen/RecordTest.groovy
index b67602e..62fdb40 100644
--- a/src/test/groovy/org/codehaus/groovy/classgen/RecordTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/RecordTest.groovy
@@ -18,8 +18,6 @@
  */
 package org.codehaus.groovy.classgen
 
-import groovy.transform.CompileDynamic
-import groovy.transform.CompileStatic
 import org.codehaus.groovy.ast.AnnotationNode
 import org.codehaus.groovy.ast.ClassHelper
 import org.codehaus.groovy.ast.ClassNode
@@ -37,72 +35,73 @@ import static groovy.test.GroovyAssert.isAtLeastJdk
 import static groovy.test.GroovyAssert.shouldFail
 import static org.junit.Assume.assumeTrue
 
-@CompileStatic
-class RecordTest {
+final class RecordTest {
+
     @Test
     void testNativeRecordOnJDK16ByDefault() {
         assumeTrue(isAtLeastJdk('16.0'))
+
         assertScript '''
-            record RecordJDK16plus(String name) {}
-            assert java.lang.Record == RecordJDK16plus.class.getSuperclass()
+            record Person(String name) {}
+            assert Person.class.superclass == java.lang.Record
         '''
     }
 
     @Test
     void testRecordLikeOnJDK16withTargetBytecode15() {
         assumeTrue(isAtLeastJdk('16.0'))
-        def configuration = new CompilerConfiguration(targetBytecode: '15')
-        assertScript(new GroovyShell(configuration), '''
-            record RecordJDK16plus2(String name) {}
-            assert java.lang.Record != RecordJDK16plus2.class.getSuperclass()
-        ''')
+
+        def shell = new GroovyShell(new CompilerConfiguration(targetBytecode:'15'))
+        assertScript shell, '''
+            record Person(String name) {}
+            assert Person.class.superclass != java.lang.Record
+        '''
     }
 
     @Test
     void testAttemptedNativeRecordWithTargetBytecode15ShouldFail() {
         assumeTrue(isAtLeastJdk('16.0'))
-        def configuration = new CompilerConfiguration(targetBytecode: '15')
-        def ex = shouldFail(new GroovyShell(configuration), '''
-            import groovy.transform.*
+
+        def shell = new GroovyShell(new CompilerConfiguration(targetBytecode:'15'))
+        def err = shouldFail shell, '''import groovy.transform.*
             @RecordType(mode=RecordTypeMode.NATIVE)
-            class RecordJDK16plus2 {
+            class Person {
                 String name
             }
-            assert java.lang.Record != RecordJDK16plus2.class.getSuperclass()
-        ''')
-        assert ex.message.contains('Expecting JDK16+ but found 15 when attempting to create a native record')
+        '''
+        assert err.message.contains('Expecting JDK16+ but found 15 when attempting to create a native record')
     }
 
     @Test
     void testNativeRecordWithSuperClassShouldFail() {
         assumeTrue(isAtLeastJdk('16.0'))
-        def ex = shouldFail('''
-            import groovy.transform.*
+
+        def err = shouldFail '''import groovy.transform.*
             @RecordType
-            class RecordJDK16plus2 extends ArrayList {
+            class Person extends ArrayList {
                 String name
             }
-            assert java.lang.Record != RecordJDK16plus2.class.getSuperclass()
-        ''')
-        assert ex.message.contains('Invalid superclass for native record found: java.util.ArrayList')
+        '''
+        assert err.message.contains('Invalid superclass for native record found: java.util.ArrayList')
     }
 
     @Test
     void testNoNativeRecordOnJDK16WhenEmulating() {
         assumeTrue(isAtLeastJdk('16.0'))
-        assertScript '''
-            import groovy.transform.*
+
+        assertScript '''import groovy.transform.*
             @RecordOptions(mode=RecordTypeMode.EMULATE)
-            record RecordJDK16plus2(String name) {}
-            assert java.lang.Record != RecordJDK16plus2.class.getSuperclass()
+            record Person(String name) {
+            }
+            assert Person.class.superclass != java.lang.Record
         '''
     }
 
     @Test
     void testRecordsDefaultParams() {
         assertScript '''
-            record Bar (String a = 'a', long b, Integer c = 24, short d, String e = 'e') { }
-
+            record Bar (String a = 'a', long b, Integer c = 24, short d, String e = 'e') {
+            }
             short one = 1
             assert new Bar(3L, one).toString() == 'Bar[a=a, b=3, c=24, d=1, e=e]'
             assert new Bar('A', 3L, one).toString() == 'Bar[a=A, b=3, c=24, d=1, e=e]'
@@ -115,7 +114,8 @@ class RecordTest {
     void testInnerRecordIsImplicitlyStatic() {
         assertScript '''
             class Test {
-                record Point(int i, int j) {}
+                record Point(int i, int j) {
+                }
             }
             assert java.lang.reflect.Modifier.isStatic(Test$Point.modifiers)
         '''
@@ -124,7 +124,8 @@ class RecordTest {
     @Test
     void testRecordWithDefaultParams() {
         assertScript '''
-            record Point(int i = 5, int j = 10) {}
+            record Point(int i = 5, int j = 10) {
+            }
             assert new Point().toString() == 'Point[i=5, j=10]'
             assert new Point(50).toString() == 'Point[i=50, j=10]'
             assert new Point(50, 100).toString() == 'Point[i=50, j=100]'
@@ -137,12 +138,12 @@ class RecordTest {
 
     @Test
     void testRecordWithDefaultParamsAndMissingRequiredParam() {
-        assertScript '''
-            import static groovy.test.GroovyAssert.shouldFail
-            record Point(int i = 5, int j, int k = 10) {}
+        assertScript '''import static groovy.test.GroovyAssert.shouldFail
+            record Point(int i = 5, int j, int k = 10) {
+            }
             assert new Point(j: 100).toString() == 'Point[i=5, j=100, k=10]'
-            def err = shouldFail(AssertionError) {
-                assert new Point(i: 50).toString() == 'Point[i=50, j=10]'
+            def err = shouldFail {
+                new Point(i: 50)
             }
             assert err.message.contains("Missing required named argument 'j'")
         '''
@@ -151,6 +152,7 @@ class RecordTest {
     @Test
     void testNativeRecordOnJDK16plus() {
         assumeTrue(isAtLeastJdk('16.0'))
+
         assertScript '''
             import java.lang.annotation.*
             import java.lang.reflect.RecordComponent
@@ -162,7 +164,7 @@ class RecordTest {
             @Retention(RetentionPolicy.RUNTIME)
             @Target([ElementType.RECORD_COMPONENT, ElementType.TYPE_USE])
             @interface NotNull2 {}
-            
+
             @Retention(RetentionPolicy.RUNTIME)
             @Target([ElementType.TYPE_USE])
             @interface NotNull3 {}
@@ -199,18 +201,17 @@ class RecordTest {
     }
 
     @Test
-    @CompileDynamic
     void testNativeRecordOnJDK16plus_java() {
         assumeTrue(isAtLeastJdk('16.0'))
 
+        def sourceDir = File.createTempDir()
         def config = new CompilerConfiguration(
-                targetDirectory: File.createTempDir(),
-                jointCompilationOptions: [memStub: true]
+            targetDirectory: File.createTempDir(),
+            jointCompilationOptions: [memStub: true]
         )
-        def parentDir = File.createTempDir()
         try {
-            def b = new File(parentDir, 'Person.java')
-            b.write '''
+            def a = new File(sourceDir, 'Person.java')
+            a.write '''
                 import java.lang.annotation.*;
                 import java.util.*;
 
@@ -223,7 +224,7 @@ class RecordTest {
                 @Retention(RetentionPolicy.RUNTIME)
                 @Target({ElementType.RECORD_COMPONENT, ElementType.TYPE_USE})
                 @interface NotNull2 {}
-                
+
                 @Retention(RetentionPolicy.RUNTIME)
                 @Target({ElementType.TYPE_USE})
                 @interface NotNull3 {}
@@ -231,7 +232,7 @@ class RecordTest {
 
             def loader = new GroovyClassLoader(this.class.classLoader)
             def cu = new JavaAwareCompilationUnit(config, loader)
-            cu.addSources(b)
+            cu.addSources(a)
             cu.compile()
 
             Class personClazz = loader.loadClass("Person")
@@ -270,20 +271,20 @@ class RecordTest {
             ClassNode notNullClassNode = ClassHelper.make(notNullClazz)
             ClassNode notNull2ClassNode = ClassHelper.make(notNull2Clazz)
             ClassNode notNull3ClassNode = ClassHelper.make(notNull3Clazz)
-            doTestNativeRecordClassNode(personClassNode, notNullClassNode, notNull2ClassNode, notNull3ClassNode)
+            checkNativeRecordClassNode(personClassNode, notNullClassNode, notNull2ClassNode, notNull3ClassNode)
 
             def resource = loader.getResource(personClazz.getName().replace('.', '/') + '.class')
             def stub = AsmDecompiler.parseClass(resource)
             def unit = new CompilationUnit(loader)
             def personDecompiledClassNode = new DecompiledClassNode(stub, new AsmReferenceResolver(new ClassNodeResolver(), unit))
-            doTestNativeRecordClassNode(personDecompiledClassNode, notNullClassNode, notNull2ClassNode, notNull3ClassNode)
+            checkNativeRecordClassNode(personDecompiledClassNode, notNullClassNode, notNull2ClassNode, notNull3ClassNode)
         } finally {
-            parentDir.deleteDir()
+            sourceDir.deleteDir()
             config.targetDirectory.deleteDir()
         }
     }
 
-    private static void doTestNativeRecordClassNode(ClassNode personClassNode, ClassNode notNullClassNode, ClassNode notNull2ClassNode, ClassNode notNull3ClassNode) {
+    private static void checkNativeRecordClassNode(ClassNode personClassNode, ClassNode notNullClassNode, ClassNode notNull2ClassNode, ClassNode notNull3ClassNode) {
         assert personClassNode.isRecord()
         def rcns = personClassNode.getRecordComponents()
         assert 4 == rcns.size()
@@ -316,6 +317,7 @@ class RecordTest {
     @Test
     void testNativeRecordOnJDK16plus2_java() {
         assumeTrue(isAtLeastJdk('16.0'))
+
         assertScript '''
             import org.codehaus.groovy.ast.*
 
@@ -331,6 +333,7 @@ class RecordTest {
     @Test
     void testNativeRecordOnJDK16plus2() {
         assumeTrue(isAtLeastJdk('16.0'))
+
         assertScript '''
             @groovy.transform.CompileStatic
             record Record(String name, int x0, int x1, int x2, int x3, int x4,
@@ -345,6 +348,7 @@ class RecordTest {
             def expected = 'Record[name=someRecord, x0=0, x1=-1, x2=2, x3=3, x4=4, x5=5, x6=6, x7=7, x8=8, x9=9, x10=10, x11=11, x12=12, x13=13, x14=14, x15=15, x16=16, x17=17, x18=18, x19=19, x20=20]'
             assert expected == r.toString()
         '''
+
         assertScript '''
             import groovy.transform.*
             @CompileStatic
@@ -446,28 +450,29 @@ class RecordTest {
     @Test
     void testNativeRecordSerialization() {
         assumeTrue(isAtLeastJdk('16.0'))
+
         assertScript '''
-        import static groovy.test.GroovyAssert.shouldFail
+            import static groovy.test.GroovyAssert.shouldFail
 
-        record RangeRecord(int lo, int hi) implements Serializable {
-            public RangeRecord {
-                if (lo > hi) throw new IllegalArgumentException("$lo should not be greater than $hi")
-            }
-            // backdoor to emulate hacking of datastream
-            RangeRecord(int[] pair) {
-                this.lo = pair[0]
-                this.hi = pair[1]
+            record RangeRecord(int lo, int hi) implements Serializable {
+                public RangeRecord {
+                    if (lo > hi) throw new IllegalArgumentException("$lo should not be greater than $hi")
+                }
+                // backdoor to emulate hacking of datastream
+                RangeRecord(int[] pair) {
+                    this.lo = pair[0]
+                    this.hi = pair[1]
+                }
             }
-        }
 
-        var data = File.createTempFile("serial", ".data")
-        var rr = [new RangeRecord([5, 10] as int[]), new RangeRecord([10, 5] as int[])]
-        data.withObjectOutputStream { out -> rr.each{ out << it } }
-        data.withObjectInputStream(getClass().classLoader) { in ->
-            assert in.readObject().toString() == 'RangeRecord[lo=5, hi=10]'
-            def ex = shouldFail(InvalidObjectException) { in.readObject() }
-            assert ex.message == '10 should not be greater than 5'
-        }
+            var data = File.createTempFile("serial", ".data")
+            var rr = [new RangeRecord([5, 10] as int[]), new RangeRecord([10, 5] as int[])]
+            data.withObjectOutputStream { out -> rr.each{ out << it } }
+            data.withObjectInputStream(getClass().classLoader) { in ->
+                assert in.readObject().toString() == 'RangeRecord[lo=5, hi=10]'
+                def ex = shouldFail(InvalidObjectException) { in.readObject() }
+                assert ex.message == '10 should not be greater than 5'
+            }
         '''
     }
 
@@ -479,7 +484,7 @@ class RecordTest {
                     return "name: $name"
                 }
             }
-            
+
             assert 'name: Daniel' == new Person('Daniel').name()
         '''
     }
@@ -496,30 +501,44 @@ class RecordTest {
                     if (age < 0) throw new IllegalArgumentException("Invalid age: $age")
                 }
             }
-            
+
             @CompileStatic
             def test() {
                 def p = new Person<String>('Daniel', 37)
                 assert 'daniel' == p.name().toLowerCase()
                 assert 'Person[name=Daniel, age=37]' == p.toString()
-                
+
                 def p2 = new Person<>('Daniel', 37)
                 assert 'daniel' == p2.name().toLowerCase()
                 assert 'Person[name=Daniel, age=37]' == p2.toString()
-                
+
                 try {
                     new Person<String>('', 1)
                 } catch (IllegalArgumentException e) {
                     assert 'name can not be empty' == e.message
                 }
-                
+
                 try {
                     new Person<String>('Unknown', -1)
                 } catch (IllegalArgumentException e) {
                     assert 'Invalid age: -1' == e.message
                 }
             }
-            
+
+            test()
+        '''
+    }
+
+    @Test // GROOVY-10548
+    void testProperty() {
+        assertScript '''
+            record Person(String name) {
+            }
+            @groovy.transform.CompileStatic
+            void test() {
+                def person = new Person('Frank Grimes')
+                assert person.name == 'Frank Grimes'
+            }
             test()
         '''
     }
diff --git a/src/test/groovy/org/codehaus/groovy/classgen/SealedTest.groovy b/src/test/org/codehaus/groovy/classgen/SealedTest.groovy
similarity index 96%
rename from src/test/groovy/org/codehaus/groovy/classgen/SealedTest.groovy
rename to src/test/org/codehaus/groovy/classgen/SealedTest.groovy
index 8fae661..c1c8669 100644
--- a/src/test/groovy/org/codehaus/groovy/classgen/SealedTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/SealedTest.groovy
@@ -18,18 +18,18 @@
  */
 package org.codehaus.groovy.classgen
 
-import groovy.transform.CompileStatic
 import org.junit.Test
 
 import static groovy.test.GroovyAssert.assertScript
 import static groovy.test.GroovyAssert.isAtLeastJdk
 import static org.junit.Assume.assumeTrue
 
-@CompileStatic
-class SealedTest {
+final class SealedTest {
+
     @Test
     void testInferredPermittedNestedClasses() {
         assumeTrue(isAtLeastJdk('17.0'))
+
         assertScript '''
             sealed class Shape {
                 final class Triangle extends Shape { }
@@ -43,6 +43,7 @@ class SealedTest {
     @Test
     void testInferredPermittedNestedClassesWithNativeDisabled() {
         assumeTrue(isAtLeastJdk('17.0'))
+
         assertScript '''
             import groovy.transform.*
             @SealedOptions(mode=SealedMode.EMULATE)