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/31 18:55:30 UTC

[groovy] branch GROOVY_2_5_X updated (cdea1fc -> 491d3f2)

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

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


    from cdea1fc  GROOVY-8104: fix this$0 for closure with anon. inner class of inner type
     new 8bc4644  GROOVY-9336: integer target type for shift RHS in constant initializer
     new c06ae8a  GROOVY-9455: !(x instanceof T) shouldn't propagate T as inferred type
     new 56362bd  GROOVY-9460: fix matching for T<?>, T<? super LB> and T<? extends UB>
     new 56d06a8  GROOVY-9526: Failed to reload classes with generic parameters
     new 3bfd280  GROOVY-9570: collect context generics starting at innermost class/method
     new 491d3f2  GROOVY-9575: `ASTNode#hashCode` does not conform to the general contract

The 6 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:
 .../groovy/groovy/util/GroovyScriptEngine.java     |  3 +-
 .../apache/groovy/ast/tools/ExpressionUtils.java   | 35 +++-----
 src/main/java/org/codehaus/groovy/ast/ASTNode.java | 45 ++++------
 .../java/org/codehaus/groovy/ast/GenericsType.java | 16 ++--
 .../transform/stc/StaticTypeCheckingSupport.java   | 10 +++
 .../transform/stc/StaticTypeCheckingVisitor.java   | 14 +++-
 .../bugs/{Groovy9294.groovy => Groovy9336.groovy}  | 17 ++--
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 24 ++++++
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 16 ++++
 .../transform/stc/TypeInferenceSTCTest.groovy      | 96 ++++++++++++++++++++++
 .../codehaus/groovy/ast/ASTNodeTest.java}          | 23 ++----
 11 files changed, 213 insertions(+), 86 deletions(-)
 copy src/test/groovy/bugs/{Groovy9294.groovy => Groovy9336.groovy} (76%)
 copy src/test/{groovy/bugs/Groovy7989.groovy => org/codehaus/groovy/ast/ASTNodeTest.java} (68%)

[groovy] 03/06: GROOVY-9460: fix matching for T, T and T

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 56362bdae6c4c8c692549ae3d1dab10293cb9122
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Jan 31 12:27:35 2022 -0600

    GROOVY-9460: fix matching for T<?>, T<? super LB> and T<? extends UB>
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/ast/GenericsType.java
---
 src/main/java/org/codehaus/groovy/ast/GenericsType.java | 16 +++++++---------
 src/test/groovy/transform/stc/GenericsSTCTest.groovy    | 16 ++++++++++++++++
 2 files changed, 23 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/GenericsType.java b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
index e68dfe0..276bfd8 100644
--- a/src/main/java/org/codehaus/groovy/ast/GenericsType.java
+++ b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
@@ -384,18 +384,16 @@ public class GenericsType extends ASTNode {
                         match = name.equals(gtn);
                         if (!match) {
                             GenericsType genericsType = boundPlaceHolders.get(gtn);
-                            match = false;
-                            if (genericsType!=null) {
+                            if (genericsType != null) {
                                 if (genericsType.isPlaceholder()) {
                                     match = true;
                                 } else if (genericsType.isWildcard()) {
-                                    if (genericsType.getUpperBounds()!=null) {
-                                        for (ClassNode up : genericsType.getUpperBounds()) {
-                                            match |= redirectBoundType.isCompatibleWith(up);
-                                        }
-                                        if (genericsType.getLowerBound()!=null) {
-                                            match |= redirectBoundType.isCompatibleWith(genericsType.getLowerBound());
-                                        }
+                                    if (genericsType.getUpperBounds() != null) { // multiple bounds not allowed for ?
+                                        match = redirectBoundType.isCompatibleWith(genericsType.getUpperBounds()[0]);
+                                    } else if (genericsType.getLowerBound() != null) {
+                                        match = redirectBoundType.isCompatibleWith(genericsType.getLowerBound());
+                                    } else {
+                                        match = true;
                                     }
                                 }
                             }
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index d14cdff..8bde750 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -392,6 +392,22 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-9460
+    void testMethodCallWithClassParameterUnbounded() {
+        assertScript '''
+            class Bar {
+                static void baz(Class<?> target) {
+                }
+            }
+            class Foo<D> { // cannot be "T" because that matches type parameter in Class
+                void test(Class<D> param) {
+                    Bar.baz(param) // Cannot call Bar#baz(java.lang.Class<?>) with arguments [java.lang.Class<D>]
+                }
+            }
+            new Foo<String>().test(String.class)
+        '''
+    }
+
     void testConstructorCallWithClassParameterUsingClassLiteralArg() {
         assertScript '''
             class A {}

[groovy] 05/06: GROOVY-9570: collect context generics starting at innermost class/method

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 3bfd28001b2991c9550190258732d9691ffebb1e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 29 20:09:29 2020 -0500

    GROOVY-9570: collect context generics starting at innermost class/method
    
    (cherry picked from commit ba63acef326cd206bd709cd6e9026bb656d54ad4)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 10 +++++++++
 .../transform/stc/StaticTypeCheckingVisitor.java   |  4 ++--
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 24 ++++++++++++++++++++++
 3 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 3e1ee52..b19931b 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -2026,6 +2026,16 @@ public abstract class StaticTypeCheckingSupport {
         return false;
     }
 
+    static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(TypeCheckingContext context) {
+        ClassNode cn = context.getEnclosingClassNode();
+        MethodNode mn = context.getEnclosingMethod();
+        // GROOVY-9570: find the innermost class or method
+        if (cn != null && cn.getEnclosingMethod() == mn) {
+            return getGenericsParameterMapOfThis(cn);
+        }
+        return extractGenericsParameterMapOfThis(mn);
+    }
+
     static Map<GenericsTypeName, GenericsType> extractGenericsParameterMapOfThis(MethodNode mn) {
         if (mn == null) return null;
 
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 1c064ea..a9bbc32 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4996,7 +4996,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (resolvedPlaceholders.isEmpty()) {
             return boundUnboundedWildcards(returnType);
         }
-        Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
+        Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext);
         applyGenericsConnections(placeholdersFromContext, resolvedPlaceholders);
 
         // then resolve receivers from method arguments
@@ -5217,7 +5217,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     private ClassNode resolveGenericsWithContext(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, ClassNode currentType) {
-        Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
+        Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext);
         return resolveClassNodeGenerics(resolvedPlaceholders, placeholdersFromContext, currentType);
     }
 
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index 6aa458f..6cdcf5b 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -1376,6 +1376,30 @@ method()
         '''
     }
 
+    void testGroovy9570() {
+        assertScript '''
+            interface Item {}
+
+            class C<I extends Item> {
+                Queue<I> queue
+
+                def c = { ->
+                    queue.each { I item ->
+                        println item
+                    }
+                }
+
+                def m() {
+                    queue.each { I item ->
+                        println item
+                    }
+                }
+            }
+
+            new C()
+        '''
+    }
+
     void testGroovy9597a() {
         assertScript '''
             import groovy.transform.stc.*

[groovy] 04/06: GROOVY-9526: Failed to reload classes with generic parameters

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 56d06a8ea48cbb4cc96dbfa73fa48512b2044848
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Apr 25 21:18:49 2020 +0800

    GROOVY-9526: Failed to reload classes with generic parameters
    
    2_5_X backport
---
 src/main/groovy/groovy/util/GroovyScriptEngine.java | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/main/groovy/groovy/util/GroovyScriptEngine.java b/src/main/groovy/groovy/util/GroovyScriptEngine.java
index 38ce3fd..a581304 100644
--- a/src/main/groovy/groovy/util/GroovyScriptEngine.java
+++ b/src/main/groovy/groovy/util/GroovyScriptEngine.java
@@ -24,6 +24,7 @@ import groovy.lang.GroovyCodeSource;
 import groovy.lang.GroovyResourceLoader;
 import groovy.lang.Script;
 import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.classgen.GeneratorContext;
@@ -209,7 +210,7 @@ public class GroovyScriptEngine implements ResourceConnector {
                                 precompiledEntries.put(origName, path);
                             }
                             if (clazz != null) {
-                                ClassNode cn = new ClassNode(clazz);
+                                ClassNode cn = ClassHelper.make(clazz);
                                 return new LookupResult(null, cn);
                             }
                         } catch (ResourceException re) {

[groovy] 02/06: GROOVY-9455: !(x instanceof T) shouldn't propagate T as inferred type

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c06ae8aa4e795129a922e363b8409a12ad3bd7b3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Mar 10 11:39:24 2020 -0500

    GROOVY-9455: !(x instanceof T) shouldn't propagate T as inferred type
    
    (cherry picked from commit d5e217aa6fa17b5b015a9f7120ba77817ddbb127)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
    	src/test/groovy/bugs/Groovy8523Bug.groovy
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 10 ++-
 .../transform/stc/TypeInferenceSTCTest.groovy      | 96 ++++++++++++++++++++++
 2 files changed, 105 insertions(+), 1 deletion(-)

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 d6508cb..1c064ea 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -782,7 +782,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitBinaryExpression(BinaryExpression expression) {
+    public void visitNotExpression(final NotExpression expression) {
+        // GROOVY-9455: !(x instanceof T) shouldn't propagate T as inferred type
+        typeCheckingContext.pushTemporaryTypeInfo();
+        super.visitNotExpression(expression);
+        typeCheckingContext.popTemporaryTypeInfo();
+    }
+
+    @Override
+    public void visitBinaryExpression(final BinaryExpression expression) {
         int op = expression.getOperation().getType();
         if (op == COMPARE_IDENTICAL) {
             return; // we'll report those as errors later
diff --git a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
index cabdcc0..6e8128a 100644
--- a/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TypeInferenceSTCTest.groovy
@@ -216,6 +216,102 @@ class TypeInferenceSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-8523
+    void testNotInstanceof1() {
+        assertScript '''
+            class Test1 {
+                static int checkRes = 0
+
+                static void f1(Object var1) {
+                    if (!(var1 instanceof Runnable)){
+                        checkRes = 3
+                        return
+                    }
+                    f2(var1)
+                }
+
+                static void f2(Runnable var2) {
+                    checkRes = 4
+                }
+            }
+
+            Runnable r = {}
+            Test1.f1(r)
+            assert Test1.checkRes == 4
+            Test1.f1(42)
+            assert Test1.checkRes == 3
+        '''
+    }
+
+    // GROOVY-8523
+    void testNotInstanceOf2() {
+        assertScript '''
+            class Test1 {
+                static int checkRes = 0
+
+                static void f1(Object var1) {
+                    if (!(var1 instanceof Runnable)){
+                        checkRes = 3
+                        return
+                    }
+                    if (!(var1 instanceof List)){
+                        checkRes = 5
+                        return
+                    }
+                    f2(var1)
+                }
+
+                static void f2(Runnable var2) {
+                    checkRes = 4
+                }
+            }
+
+            Runnable r = {}
+            Test1.f1(r)
+            assert Test1.checkRes == 5
+        '''
+    }
+
+    // GROOVY-8523
+    void testNotInstanceOf3() {
+        assertScript '''
+            class Test1 {
+                static int checkRes = 0
+
+                static void f1(Object var1) {
+                    if (!(var1 instanceof Runnable)){
+                        checkRes = 3
+                        return
+                    }
+                    if (!(var1 instanceof Thread)){
+                        checkRes = 5
+                        return
+                    }
+                    f2(var1)
+                }
+
+                static void f2(Runnable var2) {
+                    checkRes = 4
+                }
+            }
+
+            Runnable r = {}
+            Test1.f1(r)
+            assert Test1.checkRes == 5
+        '''
+    }
+
+    // GROOVY-9455
+    void testNotInstanceOf4() {
+        shouldFailWithMessages '''
+            void test(object) {
+                if (!(object instanceof String)) {
+                    object.toUpperCase()
+                }
+            }
+        ''', 'Cannot find matching method java.lang.Object#toUpperCase()'
+    }
+
     void testShouldNotAllowDynamicVariable() {
         shouldFailWithMessages '''
             String name = 'Guillaume'

[groovy] 06/06: GROOVY-9575: `ASTNode#hashCode` does not conform to the general contract

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 491d3f2c481297f65a457110ef28d1ba13fff47d
Author: Anders Wallgren <aw...@cloudbees.com>
AuthorDate: Tue May 26 19:18:37 2020 -0700

    GROOVY-9575: `ASTNode#hashCode` does not conform to the general contract
    
    (cherry picked from commit eb8539f45daf1b980b99ddd824cb05ed2e14cc1f)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/ast/ASTNode.java
---
 src/main/java/org/codehaus/groovy/ast/ASTNode.java | 45 ++++++++--------------
 src/test/org/codehaus/groovy/ast/ASTNodeTest.java  | 33 ++++++++++++++++
 2 files changed, 50 insertions(+), 28 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ASTNode.java b/src/main/java/org/codehaus/groovy/ast/ASTNode.java
index 3b68f1e..598d9af 100644
--- a/src/main/java/org/codehaus/groovy/ast/ASTNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ASTNode.java
@@ -23,7 +23,6 @@ import org.codehaus.groovy.util.ListHashMap;
 
 import java.util.Collections;
 import java.util.Map;
-import java.util.Objects;
 
 /**
  * Base class for any AST node. This class supports basic information used in all nodes of the AST:
@@ -31,15 +30,15 @@ import java.util.Objects;
  * <li> line and column number information. Usually a node represents a certain
  * area in a text file determined by a starting position and an ending position.
  * For nodes that do not represent this, this information will be -1. A node can
- * also be configured in its line/col information using another node through 
+ * also be configured in its line/col information using another node through
  * setSourcePosition(otherNode).</li>
- * <li> every node can store meta data. A phase operation or transform can use 
- * this to transport arbitrary information to another phase operation or 
+ * <li> every node can store meta data. A phase operation or transform can use
+ * this to transport arbitrary information to another phase operation or
  * transform. The only requirement is that the other phase operation or transform
- * runs after the part storing the information. If the information transport is 
- * done it is strongly recommended to remove that meta data.</li> 
+ * runs after the part storing the information. If the information transport is
+ * done it is strongly recommended to remove that meta data.</li>
  * <li> a text representation of this node trough getText(). This was in the
- * past used for assertion messages. Since the usage of power asserts this 
+ * past used for assertion messages. Since the usage of power asserts this
  * method will not be called for this purpose anymore and might be removed in
  * future versions of Groovy</li>
  * </ul>
@@ -91,13 +90,13 @@ public class ASTNode {
     public void setLastColumnNumber(int lastColumnNumber) {
         this.lastColumnNumber = lastColumnNumber;
     }
-    
+
     /**
      * Sets the source position using another ASTNode.
      * The sourcePosition consists of a line/column pair for
      * the start and a line/column pair for the end of the
-     * expression or statement 
-     * 
+     * expression or statement
+     *
      * @param node - the node used to configure the position information
      */
     public void setSourcePosition(ASTNode node) {
@@ -106,10 +105,10 @@ public class ASTNode {
         this.lastColumnNumber = node.getLastColumnNumber();
         this.lineNumber = node.getLineNumber();
     }
-    
+
     /**
-     * Gets the node meta data. 
-     * 
+     * Gets the node meta data.
+     *
      * @param key - the meta data key
      * @return the node meta data value for this key
      */
@@ -133,13 +132,13 @@ public class ASTNode {
         }
         metaDataMap.putAll(other.metaDataMap);
     }
-    
+
     /**
-     * Sets the node meta data. 
-     * 
+     * Sets the node meta data.
+     *
      * @param key - the meta data key
      * @param value - the meta data value
-     * @throws GroovyBugError if key is null or there is already meta 
+     * @throws GroovyBugError if key is null or there is already meta
      *                        data under that key
      */
     public void setNodeMetaData(Object key, Object value) {
@@ -169,7 +168,7 @@ public class ASTNode {
 
     /**
      * Removes a node meta data entry.
-     * 
+     *
      * @param key - the meta data key
      * @throws GroovyBugError if the key is null
      */
@@ -195,14 +194,4 @@ public class ASTNode {
     public ListHashMap getMetaDataMap() {
         return metaDataMap;
     }
-
-    @Override
-    public boolean equals(Object o) {
-        return this == o;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(lineNumber, columnNumber, lastLineNumber, lastColumnNumber);
-    }
 }
diff --git a/src/test/org/codehaus/groovy/ast/ASTNodeTest.java b/src/test/org/codehaus/groovy/ast/ASTNodeTest.java
new file mode 100644
index 0000000..c069b4b
--- /dev/null
+++ b/src/test/org/codehaus/groovy/ast/ASTNodeTest.java
@@ -0,0 +1,33 @@
+/*
+ *  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 org.codehaus.groovy.ast;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public final class ASTNodeTest {
+    @Test
+    public void testHashCode() {
+        ASTNode astNode = new ASTNode();
+        int hashcode = astNode.hashCode();
+        astNode.setLineNumber(astNode.getLineNumber() + 10);
+        assertEquals("hashCode is consistent", hashcode, astNode.hashCode());
+    }
+}

[groovy] 01/06: GROOVY-9336: integer target type for shift RHS in constant initializer

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 8bc4644aa5038ec6496193c7612f299bde552084
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Jan 11 12:23:47 2020 -0600

    GROOVY-9336: integer target type for shift RHS in constant initializer
    
    (cherry picked from commit b133efc8efbeb24da4601bdfd12bf5a008032d72)
    
    Conflicts:
    	src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
---
 .../apache/groovy/ast/tools/ExpressionUtils.java   | 35 +++++++-----------
 src/test/groovy/bugs/Groovy9336.groovy             | 42 ++++++++++++++++++++++
 2 files changed, 55 insertions(+), 22 deletions(-)

diff --git a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
index 8cec61a..2321404 100644
--- a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
@@ -33,7 +33,7 @@ import org.codehaus.groovy.runtime.typehandling.NumberMath;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
+import java.util.Arrays;
 
 import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
 import static org.codehaus.groovy.syntax.Types.BITWISE_OR;
@@ -48,25 +48,16 @@ import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT;
 import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
 
 public final class ExpressionUtils {
-    private static ArrayList<Integer> handledTypes = new ArrayList<Integer>();
 
     private ExpressionUtils() {
-
     }
 
-    static {
-        handledTypes.add(PLUS);
-        handledTypes.add(MINUS);
-        handledTypes.add(MULTIPLY);
-        handledTypes.add(DIVIDE);
-        handledTypes.add(LEFT_SHIFT);
-        handledTypes.add(RIGHT_SHIFT);
-        handledTypes.add(RIGHT_SHIFT_UNSIGNED);
-        handledTypes.add(BITWISE_OR);
-        handledTypes.add(BITWISE_AND);
-        handledTypes.add(BITWISE_XOR);
-        handledTypes.add(POWER);
-    }
+    // NOTE: values are sorted in ascending order
+    private static final int[] HANDLED_TYPES = {
+        PLUS, MINUS, MULTIPLY, DIVIDE, POWER,
+        LEFT_SHIFT, RIGHT_SHIFT, RIGHT_SHIFT_UNSIGNED,
+        BITWISE_OR, BITWISE_AND, BITWISE_XOR,
+    };
 
     /**
      * Turns expressions of the form ConstantExpression(40) + ConstantExpression(2)
@@ -92,9 +83,10 @@ public final class ExpressionUtils {
             }
         } else if (isNumberOrArrayOfNumber(wrapperType, false)) {
             int type = be.getOperation().getType();
-            if (handledTypes.contains(type)) {
+            if (Arrays.binarySearch(HANDLED_TYPES, type) >= 0) {
+                boolean isShift = (type >= LEFT_SHIFT && type <= RIGHT_SHIFT_UNSIGNED);
                 Expression leftX = transformInlineConstants(be.getLeftExpression(), targetType);
-                Expression rightX = transformInlineConstants(be.getRightExpression(), targetType);
+                Expression rightX = transformInlineConstants(be.getRightExpression(), isShift ? ClassHelper.int_TYPE : targetType);
                 if (leftX instanceof ConstantExpression && rightX instanceof ConstantExpression) {
                     Number left = safeNumber((ConstantExpression) leftX);
                     Number right = safeNumber((ConstantExpression) rightX);
@@ -342,10 +334,9 @@ public final class ExpressionUtils {
     }
 
     private static Expression findConstant(FieldNode fn) {
-        if (fn != null && !fn.isEnum() && fn.isStatic() && fn.isFinal()) {
-            if (fn.getInitialValueExpression() instanceof ConstantExpression) {
-                return fn.getInitialValueExpression();
-            }
+        if (fn != null && !fn.isEnum() && fn.isStatic() && fn.isFinal()
+                && fn.getInitialValueExpression() instanceof ConstantExpression) {
+            return fn.getInitialValueExpression();
         }
         return null;
     }
diff --git a/src/test/groovy/bugs/Groovy9336.groovy b/src/test/groovy/bugs/Groovy9336.groovy
new file mode 100644
index 0000000..5aa837e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9336.groovy
@@ -0,0 +1,42 @@
+/*
+ *  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.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9336 {
+
+    @Test
+    void testShiftInStaticFieldInitializer() {
+        assertScript '''
+            class Groovy9336 {
+                // initializer evaluated like (2 as double) << ((16 - 1) as double); need int on RHS
+                public static double N = 2 << 16 - 1
+
+                static main(args) {
+                    assert N == 65536.0d
+                }
+            }
+        '''
+    }
+}