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/01/30 15:40:29 UTC

[groovy] branch GROOVY_3_0_X updated (a2856d9 -> 8ce67b1)

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

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


    from a2856d9  GROOVY-8974: STC: missesGenericsTypes(ClassNode) true for unresolved <>
     new 9cfbe18  GROOVY-9006: STC: compare to null for types that overload equals
     new 8ce67b1  GROOVY-9784: `GroovyRowResult` implements `Map<String,Object>`

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../transform/stc/StaticTypeCheckingVisitor.java   |   9 +-
 .../bugs/{Groovy7989.groovy => Groovy5041.groovy}  |  21 ++--
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |  15 +++
 .../src/main/java/groovy/sql/GroovyRowResult.java  |  39 ++++---
 .../test/groovy/groovy/bugs/ForAndSqlBug.groovy    |  53 ----------
 .../test/groovy/groovy/bugs/Groovy5041Bug.groovy   |  71 -------------
 .../groovy/groovy/sql/GroovyRowResultTest.groovy   | 116 ++++++++++++---------
 .../src/test/groovy/groovy/sql/SqlTest.groovy      | 101 ++++++++++++++----
 8 files changed, 203 insertions(+), 222 deletions(-)
 copy src/test/groovy/bugs/{Groovy7989.groovy => Groovy5041.groovy} (75%)
 delete mode 100644 subprojects/groovy-sql/src/test/groovy/groovy/bugs/ForAndSqlBug.groovy
 delete mode 100644 subprojects/groovy-sql/src/test/groovy/groovy/bugs/Groovy5041Bug.groovy

[groovy] 02/02: GROOVY-9784: `GroovyRowResult` implements `Map`

Posted by em...@apache.org.
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 8ce67b197a906569067f2049df84acf7b646a819
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Oct 29 10:46:07 2020 -0500

    GROOVY-9784: `GroovyRowResult` implements `Map<String,Object>`
---
 .../test/groovy/bugs/Groovy5041.groovy             |  40 +++----
 .../src/main/java/groovy/sql/GroovyRowResult.java  |  39 ++++---
 .../test/groovy/groovy/bugs/Groovy5041Bug.groovy   |  71 -------------
 .../groovy/groovy/sql/GroovyRowResultTest.groovy   | 116 ++++++++++++---------
 .../src/test/groovy/groovy/sql/SqlTest.groovy      | 101 ++++++++++++++----
 5 files changed, 183 insertions(+), 184 deletions(-)

diff --git a/subprojects/groovy-sql/src/test/groovy/groovy/bugs/ForAndSqlBug.groovy b/src/test/groovy/bugs/Groovy5041.groovy
similarity index 54%
rename from subprojects/groovy-sql/src/test/groovy/groovy/bugs/ForAndSqlBug.groovy
rename to src/test/groovy/bugs/Groovy5041.groovy
index 8aa87bd..ec60115 100644
--- a/subprojects/groovy-sql/src/test/groovy/groovy/bugs/ForAndSqlBug.groovy
+++ b/src/test/groovy/bugs/Groovy5041.groovy
@@ -18,36 +18,26 @@
  */
 package groovy.bugs
 
-import groovy.sql.SqlHelperTestCase
-import groovy.test.GroovyTestCase
+import org.junit.Test
 
-class ForAndSqlBug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
 
-    void testBugInNormalMethod() {
-        def sql = SqlHelperTestCase.makeSql()
-        def li = ["a", "b"]
-        for (x in li) {
-            sql.eachRow("SELECT count(*) FROM FOOD") { e ->
-                println " ${x}"
-                assert x != null
+final class Groovy5041 {
+    @Test
+    void testAICParameter() {
+        assertScript '''
+            abstract class C {
+                C(x) {}
+                abstract call()
             }
-        }
-        sql.close()
-    }
 
-    void testBugInsideScript() {
-        assertScript '''
-            import groovy.sql.SqlHelperTestCase
-            def sql = SqlHelperTestCase.makeSql()
-            def li = ["a", "b"]
-            for (x in li) {
-                sql.eachRow("SELECT count(*) FROM FOOD") { e ->
-                    println " ${x}"
-                    assert x != null
-                }
+            def x = 1
+            def c = new C(x) {
+                def call() { x }
             }
-            sql.close()
+            assert c.call() == 1
+            x = 2
+            assert c.call() == 2
         '''
     }
-
 }
diff --git a/subprojects/groovy-sql/src/main/java/groovy/sql/GroovyRowResult.java b/subprojects/groovy-sql/src/main/java/groovy/sql/GroovyRowResult.java
index 4202749..1a2f21c 100644
--- a/subprojects/groovy-sql/src/main/java/groovy/sql/GroovyRowResult.java
+++ b/subprojects/groovy-sql/src/main/java/groovy/sql/GroovyRowResult.java
@@ -31,11 +31,11 @@ import java.util.Set;
  * It's primarily used by methods of Groovy's {@link groovy.sql.Sql} class to return {@code ResultSet} data in map
  * form; allowing access to the result of a SQL query by the name of the column, or by the column number.
  */
-public class GroovyRowResult extends GroovyObjectSupport implements Map {
+public class GroovyRowResult extends GroovyObjectSupport implements Map<String, Object> {
 
-    private final Map result;
+    private final Map<String, Object> result;
 
-    public GroovyRowResult(Map result) {
+    public GroovyRowResult(Map<String, Object> result) {
         this.result = result;
     }
 
@@ -45,6 +45,7 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
      * @param property is the name of the property to look at
      * @return the value of the property
      */
+    @Override
     public Object getProperty(String property) {
         try {
             Object key = lookupKeyIgnoringCase(property);
@@ -86,7 +87,7 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
             // a negative index will count backwards from the last column.
             if (index < 0)
                 index += result.size();
-            Iterator it = result.values().iterator();
+            Iterator<Object> it = result.values().iterator();
             int i = 0;
             Object obj = null;
             while ((obj == null) && (it.hasNext())) {
@@ -103,6 +104,7 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
         }
     }
 
+    @Override
     public String toString() {
         return result.toString();
     }
@@ -111,7 +113,7 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
      * The following methods are needed for implementing the Map interface.
      * They are mostly delegating the request to the provided Map.
      */
-     
+    @Override
     public void clear() {
         result.clear();
     }
@@ -122,18 +124,22 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
      * @param key the property name to look for
      * @return true if the result contains this property name
      */
+    @Override
     public boolean containsKey(Object key) {
         return lookupKeyIgnoringCase(key) != null;
     }
 
+    @Override
     public boolean containsValue(Object value) {
         return result.containsValue(value);
     }
 
-    public Set<Map.Entry> entrySet() {
+    @Override
+    public Set<Map.Entry<String, Object>> entrySet() {
         return result.entrySet();
     }
 
+    @Override
     public boolean equals(Object o) {
         return result.equals(o);
     }
@@ -144,21 +150,25 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
      * @param property the name of the property to get
      * @return the property value
      */
+    @Override
     public Object get(Object property) {
         if (property instanceof String)
             return getProperty((String)property);
         return null;
     }
 
+    @Override
     public int hashCode() {
         return result.hashCode();
     }
 
+    @Override
     public boolean isEmpty() {
         return result.isEmpty();
     }
 
-    public Set keySet() {
+    @Override
+    public Set<String> keySet() {
         return result.keySet();
     }
 
@@ -172,8 +182,8 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
      *         (A <tt>null</tt> return can also indicate that the map
      *         previously associated <tt>null</tt> with <tt>key</tt>.)
      */
-    @SuppressWarnings("unchecked")
-    public Object put(Object key, Object value) {
+    @Override
+    public Object put(String key, Object value) {
         // avoid different case keys being added by explicit remove
         Object orig = remove(key);
         result.put(key, value);
@@ -188,23 +198,26 @@ public class GroovyRowResult extends GroovyObjectSupport implements Map {
      *
      * @param t the mappings to store in this result
      */
-    @SuppressWarnings("unchecked")
-    public void putAll(Map t) {
+    @Override
+    public void putAll(Map<? extends String, ?> t) {
         // don't delegate to putAll since we want case handling from put
-        for (Entry next : (Set<Entry>) t.entrySet()) {
+        for (Entry<? extends String, ?> next : t.entrySet()) {
             put(next.getKey(), next.getValue());
         }
     }
 
+    @Override
     public Object remove(Object rawKey) {
         return result.remove(lookupKeyIgnoringCase(rawKey));
     }
 
+    @Override
     public int size() {
         return result.size();
     }
 
-    public Collection values() {
+    @Override
+    public Collection<Object> values() {
         return result.values();
     }
 }
diff --git a/subprojects/groovy-sql/src/test/groovy/groovy/bugs/Groovy5041Bug.groovy b/subprojects/groovy-sql/src/test/groovy/groovy/bugs/Groovy5041Bug.groovy
deleted file mode 100644
index c66f7dc..0000000
--- a/subprojects/groovy-sql/src/test/groovy/groovy/bugs/Groovy5041Bug.groovy
+++ /dev/null
@@ -1,71 +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 Groovy5041Bug extends GroovyTestCase {
-    void testAICParameter() {
-        // GROOVY-5041
-        assertScript """
-            import java.sql.Connection
-            import groovy.sql.Sql
-
-            class GrailsPrecondition {
-
-                Connection getConnection() { database?.connection?.wrappedConnection }
-
-                Sql getSql() {
-                    if (!connection) return null
-
-                    if (!sql) {
-                        sql = new Sql(connection) {
-                            protected void closeResources(Connection c) {
-                                // do nothing, let Liquibase close the connection
-                            }
-                        }
-                    }
-
-                    sql
-                }
-            }
-            def x = new GrailsPrecondition()
-            try {
-                x.sql
-                assert false
-            } catch (MissingPropertyException mpe) {
-                assert true
-            }
-        """
-        assertScript """
-            class Foo {
-              def call(){}
-              def Foo(x){}
-            }
-
-            def x = 1
-            def caller = new Foo(x) {
-               def call(){x}
-            }
-            assert caller.call() == 1
-            x = 2
-            assert caller.call() == 2
-        """
-    }
-}
diff --git a/subprojects/groovy-sql/src/test/groovy/groovy/sql/GroovyRowResultTest.groovy b/subprojects/groovy-sql/src/test/groovy/groovy/sql/GroovyRowResultTest.groovy
index effffc4..6e4d56a 100644
--- a/subprojects/groovy-sql/src/test/groovy/groovy/sql/GroovyRowResultTest.groovy
+++ b/subprojects/groovy-sql/src/test/groovy/groovy/sql/GroovyRowResultTest.groovy
@@ -18,72 +18,93 @@
  */
 package groovy.sql
 
-import groovy.test.GroovyTestCase
+import groovy.transform.CompileStatic
+import org.junit.Test
 
-class GroovyRowResultTest extends GroovyTestCase {
+import static groovy.test.GroovyAssert.shouldFail
 
-    void testMap() {
-        def row = createRow();
-        def row2 = createRow();
+final class GroovyRowResultTest {
 
-        /**
-         * Test for implementing Map
-         */
-        assert row instanceof Map, "BUG! GroovyRowResult doesn't implement Map!"
+    protected GroovyRowResult createRow() {
+        def map = [:]
+        map.put('miXed', 'quick')
+        map.put('nullMixed', null)
+        map.put('lower', 'brown')
+        map.put('nulllower', null)
+        map.put('UPPER', 'fox')
+        map.put('NULLUPPER', null)
+        def row = new GroovyRowResult(map)
+        assert row != null, 'failed to load GroovyRowResult class'
+        return row
+    }
+
+    @CompileStatic @Test
+    void testMapType() {
+        Map<String, Object> row = createRow() // GROOVY-9784
+    }
+
+    @Test
+    void testMapMethods() {
+        def row = createRow()
+        def row2 = createRow()
 
         /**
          * Test for put and accessing the new property
          */
-        row.put("john", "Doe")
-        assert row.john == "Doe"
-        assert row["john"] == "Doe"
+        row.put('john', 'Doe')
+        assert row.john == 'Doe'
         assert row['john'] == 'Doe'
-        assert row.containsKey("john")
-        assert row.containsKey("JOHN")
-        assert row.containsKey("John")
-        assert !row2.containsKey("john")
-        assert row.containsValue("Doe")
-        assert !row2.containsKey("Doe")
+        assert row['john'] == 'Doe'
+        assert row.containsKey('john')
+        assert row.containsKey('JOHN')
+        assert row.containsKey('John')
+        assert !row2.containsKey('john')
+        assert row.containsValue('Doe')
+        assert !row2.containsKey('Doe')
 
         /**
          * Test for equality (1) and size
          */
-        assert row != row2, "rows unexpectedly equal"
+        assert row != row2, 'rows unexpectedly equal'
         assert row.size() == 7
         assert row2.size() == 6
 
         /**
          * Test for remove, equality (2) and isEmpty (1)
          */
-        row.remove("john")
-        assert row == row2, "rows different after remove"
-        assert !row.isEmpty(), "row empty after remove"
+        row.remove('john')
+        assert row == row2, 'rows different after remove'
+        assert !row.isEmpty(), 'row empty after remove'
 
         /**
          * Test for clear, equality (3) and isEmpty (2)
          */
         row.clear()
         row2.clear()
-        assert row == row2, "rows different after clear"
-        assert row.isEmpty(), "row not empty after clear"
+        assert row == row2, 'rows different after clear'
+        assert row.isEmpty(), 'row not empty after clear'
     }
 
+    @Test
     void testProperties() {
         def row = createRow()
-        assert row.miXed == "quick"
-        assert row.mixed == "quick"
-        assert row.lower == "brown"
-        assert row.LOWER == "brown"
-        assert row.upper == "fox"
-        assert row.UPPER == "fox"
+
+        assert row.miXed == 'quick'
+        assert row.mixed == 'quick'
+        assert row.lower == 'brown'
+        assert row.LOWER == 'brown'
+        assert row.upper == 'fox'
+        assert row.UPPER == 'fox'
 
         shouldFail(MissingPropertyException) {
             row.foo
         }
+    }
+
+    @Test // GROOVY-1296
+    void testNullProperties() {
+        def row = createRow()
 
-        /**
-         * This is for GROOVY-1296
-         */
         assert row.nullMixed == null
         assert row[1] == null
         assert row.nulllower == null
@@ -98,36 +119,27 @@ class GroovyRowResultTest extends GroovyTestCase {
         assert !row.containsKey('UPPER')
     }
 
+    @Test
     void testOrder() {
         def row = createRow()
-        assert row[0] == "quick"
+
+        assert row[0] == 'quick'
         assert row[1] == null
-        assert row[2] == "brown"
+        assert row[2] == 'brown'
         assert row[3] == null
-        assert row[4] == "fox"
+        assert row[4] == 'fox'
         assert row[5] == null
         assert row[27] == null
         assert row[-1] == null
-        assert row[-2] == "fox"
-    }
-
-    protected def createRow() {
-        def map = new LinkedHashMap()
-        map.put("miXed", "quick")
-        map.put("nullMixed", null)
-        map.put("lower", "brown")
-        map.put("nulllower", null)
-        map.put("UPPER", "fox")
-        map.put("NULLUPPER", null)
-        def row = new GroovyRowResult(map)
-        assert row != null, "failed to load GroovyRowResult class"
-        return row
+        assert row[-2] == 'fox'
     }
 
+    @Test
     void testCaseInsensitivePut() {
-        def row = new GroovyRowResult(SOMEKEY: "v1")
+        def row = new GroovyRowResult(SOMEKEY: 'v1')
+
         assert row.someKEY == 'v1'
-        row.somekey = "v2"
+        row.somekey = 'v2'
         assert row.someKEY == 'v2'
         assert row.put('sOmEkEy', 'v3') == 'v2'
         assert row.someKEY == 'v3'
diff --git a/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlTest.groovy b/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlTest.groovy
index 300cfd3..c5d9dba 100644
--- a/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlTest.groovy
+++ b/subprojects/groovy-sql/src/test/groovy/groovy/sql/SqlTest.groovy
@@ -18,9 +18,11 @@
  */
 package groovy.sql
 
-import groovy.test.GroovyTestCase
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TestName
 
-import javax.sql.DataSource
 import java.sql.Connection
 
 import static groovy.sql.SqlTestConstants.DB_DATASOURCE
@@ -28,23 +30,27 @@ import static groovy.sql.SqlTestConstants.DB_DS_KEY
 import static groovy.sql.SqlTestConstants.DB_PASSWORD
 import static groovy.sql.SqlTestConstants.DB_URL_PREFIX
 import static groovy.sql.SqlTestConstants.DB_USER
+import static groovy.test.GroovyAssert.assertScript
 
 /**
  * This is more of a sample program than a unit test and is here as an easy
  * to read demo of GDO. The actual full unit test case is in SqlCompleteTest
  */
-class SqlTest extends GroovyTestCase {
+final class SqlTest {
 
-    private sql
+    private Sql sql
 
+    @Before
     void setUp() {
         sql = createSql()
     }
 
+    @Test
     void testSqlQuery() {
         sql.eachRow("select * from PERSON") { println("Hello ${it.firstname} ${it.lastname}") }
     }
 
+    @Test
     void testQueryUsingColumnIndex() {
         def answer = null
         sql.eachRow("select count(*) from PERSON") { answer = it[0] }
@@ -52,6 +58,7 @@ class SqlTest extends GroovyTestCase {
         assert answer == 3
     }
 
+    @Test
     void testQueryUsingNegativeColumnIndex() {
         def first = null
         def last = null
@@ -64,17 +71,20 @@ class SqlTest extends GroovyTestCase {
         assert last == "Strachan"
     }
 
+    @Test
     void testSqlQueryWithWhereClause() {
         def foo = "drink"
         sql.eachRow("select * from FOOD where type=${foo}") { println("Drink ${it.name}") }
     }
 
+    @Test
     void testEachRowWithWhereClauseWith2Arguments() {
         def foo = "cheese"
         def bar = "edam"
         sql.eachRow("select * from FOOD where type=${foo} and name != ${bar}") { println("Found cheese ${it.name}") }
     }
 
+    @Test
     void testFirstRowWithWhereClauseWith2Arguments() {
         def foo = "cheese"
         def bar = "edam"
@@ -82,22 +92,26 @@ class SqlTest extends GroovyTestCase {
         assert result.name == 'brie'
     }
 
+    @Test
     void testSqlQueryWithIncorrectlyQuotedDynamicExpressions() {
         def foo = "cheese"
         def bar = "edam"
         sql.eachRow("select * from FOOD where type='${foo}' and name != '${bar}'") { println("Found cheese ${it.name}") }
     }
 
+    @Test
     void testDataSet() {
         def people = sql.dataSet("PERSON")
         people.each { println("Hey ${it.firstname}") }
     }
 
+    @Test
     void testDataSetWithClosurePredicate() {
         def food = sql.dataSet("FOOD")
         food.findAll { it.type == "cheese" }.each { println("Cheese ${it.name}") }
     }
 
+    @Test
     void testExecuteUpdate() {
         def foo = 'food-drink'
         def bar = 'guinness'
@@ -107,6 +121,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testExecuteInsert() {
         def value = 'log entry'
         if (sql.dataSource.connection.metaData.supportsGetGeneratedKeys()) {
@@ -118,6 +133,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testExecuteInsertWithColumnNamesListParams() {
         def value = 'log entry'
         if (sql.dataSource.connection.metaData.supportsGetGeneratedKeys()) {
@@ -126,6 +142,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testExecuteInsertWithColumnNamesVarargParams() {
         def value = 'log entry'
         if (sql.dataSource.connection.metaData.supportsGetGeneratedKeys()) {
@@ -134,6 +151,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testExecuteInsertWithColumnNamesNoVarargs() {
         if (sql.dataSource.connection.metaData.supportsGetGeneratedKeys()) {
             def keys = sql.executeInsert("insert into LOG (value) values 'log entry'", ['ID'] as String[])
@@ -141,6 +159,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testExecuteInsertWithColumnNamesGString() {
         def value = 'log entry'
         if (sql.dataSource.connection.metaData.supportsGetGeneratedKeys()) {
@@ -152,6 +171,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testExecuteWithProcessResultsClosure() {
         sql.execute("insert into LOG (value) values ('log entry')") {
             isResultSet, result ->
@@ -159,6 +179,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testMetaData() {
         sql.eachRow('select * from PERSON') {
             assert it[0] != null
@@ -166,6 +187,7 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testSubClass() {
         def sub = new SqlSubclass(sql)
         def res = null
@@ -192,6 +214,7 @@ class SqlTest extends GroovyTestCase {
         assert data.size() == 2 && !(data - ['firstname', 'lastname'])
     }
 
+    @Test
     void testCallMethodFromObjectOnGroovyResultSet() {
         sql.eachRow('select * from PERSON') {
             println it.toString()
@@ -199,30 +222,62 @@ class SqlTest extends GroovyTestCase {
         }
     }
 
-    private createSql() {
-        DataSource ds = DB_DATASOURCE.newInstance(
-                (DB_DS_KEY): DB_URL_PREFIX + getMethodName(),
-                user: DB_USER,
-                password: DB_PASSWORD)
+    @Test // GROOVY-168
+    void testBugInNormalMethod() {
+        def li = ['a', 'b']
+        for (x in li) {
+            sql.eachRow('SELECT count(*) FROM FOOD') { e ->
+                println " ${x}"
+                assert x != null
+            }
+        }
+        sql.close()
+    }
+
+    @Test // GROOVY-168
+    void testBugInsideScript() {
+        assertScript '''
+            import groovy.sql.SqlHelperTestCase
+            def sql = SqlHelperTestCase.makeSql()
+            def li = ["a", "b"]
+            for (x in li) {
+                sql.eachRow("SELECT count(*) FROM FOOD") { e ->
+                    println " ${x}"
+                    assert x != null
+                }
+            }
+            sql.close()
+        '''
+    }
+
+    //--------------------------------------------------------------------------
+
+    @Rule
+    public final TestName test = new TestName()
+
+    private Sql createSql() {
+        javax.sql.DataSource ds = DB_DATASOURCE.newInstance(
+                (DB_DS_KEY): DB_URL_PREFIX + test.methodName,
+                user: DB_USER, password: DB_PASSWORD)
         sql = new Sql(ds.connection)
         def sql = new Sql(ds)
 
-        sql.execute("create table PERSON ( firstname VARCHAR(10), lastname VARCHAR(10) )")
-        sql.execute("create table FOOD ( type VARCHAR(10), name VARCHAR(10))")
-        sql.execute("create table LOG ( value VARCHAR(20), ID INTEGER IDENTITY)")
+        sql.execute('create table PERSON ( firstname VARCHAR(10), lastname VARCHAR(10) )')
+        sql.execute('create table FOOD ( type VARCHAR(10), name VARCHAR(10))')
+        sql.execute('create table LOG ( value VARCHAR(20), ID INTEGER IDENTITY)')
 
         // now let's populate the datasets
-        def people = sql.dataSet("PERSON")
-        people.add(firstname: "James", lastname: "Strachan")
-        people.add(firstname: "Bob", lastname: "Mcwhirter")
-        people.add(firstname: "Sam", lastname: "Pullara")
-
-        def food = sql.dataSet("FOOD")
-        food.add(type: "cheese", name: "edam")
-        food.add(type: "cheese", name: "brie")
-        food.add(type: "cheese", name: "cheddar")
-        food.add(type: "drink", name: "beer")
-        food.add(type: "drink", name: "coffee")
+        def people = sql.dataSet('PERSON')
+        people.add(firstname: 'James', lastname: 'Strachan')
+        people.add(firstname: 'Bob', lastname: 'Mcwhirter')
+        people.add(firstname: 'Sam', lastname: 'Pullara')
+
+        def food = sql.dataSet('FOOD')
+        food.add(type: 'cheese', name: 'edam')
+        food.add(type: 'cheese', name: 'brie')
+        food.add(type: 'cheese', name: 'cheddar')
+        food.add(type: 'drink', name: 'beer')
+        food.add(type: 'drink', name: 'coffee')
 
         return sql
     }

[groovy] 01/02: GROOVY-9006: STC: compare to null for types that overload equals

Posted by em...@apache.org.
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 9cfbe18b85e3ee1c3768b87266481b77d09b2f23
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Oct 19 19:42:22 2021 -0500

    GROOVY-9006: STC: compare to null for types that overload equals
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../groovy/transform/stc/StaticTypeCheckingVisitor.java   |  9 +++++++--
 src/test/groovy/transform/stc/BugsSTCTest.groovy          | 15 +++++++++++++++
 2 files changed, 22 insertions(+), 2 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 69feed6..206b6bc 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4421,8 +4421,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             return mathResultType;
         }
 
-        // GROOVY-5890
-        // do not mix Class<Foo> with Foo
+        // GROOVY-9006: compare to null for types that overload equals
+        if ("equals".equals(operationName) && (left == UNKNOWN_PARAMETER_TYPE
+                                            || right == UNKNOWN_PARAMETER_TYPE)) {
+            return boolean_TYPE;
+        }
+
+        // GROOVY-5890: do not mix Class<Type> with Type
         if (leftExpression instanceof ClassExpression) {
             left = CLASS_Type.getPlainNodeReference();
         }
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index e4e899d..cfa8c19 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -788,6 +788,21 @@ Printer
         '''
     }
 
+    // GROOVY-9006
+    void testAmbiguousMethodResolutionTimestampComparedToNull() {
+        assertScript '''
+            import java.sql.Timestamp
+
+            def test(Timestamp timestamp) {
+                if (timestamp != null) { // Reference to method is ambiguous
+                    return 'not null'
+                }
+            }
+            def result = test(new Timestamp(new Date().getTime()))
+            assert result == 'not null'
+        '''
+    }
+
     // GROOVY-6911
     void testShouldNotThrowArrayIndexOfOutBoundsException() {
         assertScript '''