You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/05/26 02:05:37 UTC

[1/3] groovy git commit: GROOVY-8114: Include correct time unit in timeout error message (closes #549)

Repository: groovy
Updated Branches:
  refs/heads/GROOVY_2_6_X ec6c596a2 -> cfadc929b


GROOVY-8114: Include correct time unit in timeout error message (closes #549)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/c2eb667c
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/c2eb667c
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/c2eb667c

Branch: refs/heads/GROOVY_2_6_X
Commit: c2eb667cb1fa3bf20cb6caf9b817490d112b9e52
Parents: ec6c596
Author: paulk <pa...@asert.com.au>
Authored: Thu May 25 16:32:11 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Fri May 26 12:05:19 2017 +1000

----------------------------------------------------------------------
 .../transform/TimedInterruptibleASTTransformation.groovy  | 10 ++++++++--
 src/test/groovy/transform/TimedInterruptTest.groovy       |  8 +++++---
 2 files changed, 13 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/c2eb667c/src/main/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy b/src/main/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
index 6ad4898..fbc923b 100644
--- a/src/main/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
+++ b/src/main/org/codehaus/groovy/transform/TimedInterruptibleASTTransformation.groovy
@@ -187,8 +187,14 @@ public class TimedInterruptibleASTTransformation extends AbstractASTTransformati
                             ctorX(thrown,
                                     args(
                                             plusX(
-                                                    constX('Execution timed out after ' + maximum + ' units. Start time: '),
-                                                    propX(varX("this"), basename + '$startTime'),
+                                                    plusX(
+                                                            constX('Execution timed out after ' + maximum + ' '),
+                                                            callX(callX(unit, 'name'), 'toLowerCase', propX(classX(Locale), 'US'))
+                                                    ),
+                                                    plusX(
+                                                            constX('. Start time: '),
+                                                            propX(varX("this"), basename + '$startTime')
+                                                    )
                                             )
 
                                     )

http://git-wip-us.apache.org/repos/asf/groovy/blob/c2eb667c/src/test/groovy/transform/TimedInterruptTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/transform/TimedInterruptTest.groovy b/src/test/groovy/transform/TimedInterruptTest.groovy
index d0d8652..366b665 100644
--- a/src/test/groovy/transform/TimedInterruptTest.groovy
+++ b/src/test/groovy/transform/TimedInterruptTest.groovy
@@ -19,6 +19,8 @@
 package groovy.transform
 
 import groovy.mock.interceptor.StubFor
+
+import java.util.concurrent.TimeUnit
 import java.util.concurrent.TimeoutException
 import org.codehaus.groovy.control.MultipleCompilationErrorsException
 import org.codehaus.groovy.transform.TimedInterruptibleASTTransformation
@@ -140,7 +142,7 @@ class TimedInterruptTest extends GroovyTestCase {
       @TimedInterrupt(value = 18000000L, unit = TimeUnit.MILLISECONDS)
       def myMethod() { }
     ''')
-    assertPassesNormalFailsSlowExecution(c, 18000000000666, '18000000') //5 hours in future
+    assertPassesNormalFailsSlowExecution(c, 18000000000666, '18000000', 'myMethod', TimeoutException, 'milliseconds') //5 hours in future
   }
 
   // TODO not sure all these tests are pulling their weight - testing Groovy annotation type handing not subject
@@ -244,7 +246,7 @@ class TimedInterruptTest extends GroovyTestCase {
     }
   }
 
-  private void assertPassesNormalFailsSlowExecution(c, long expireTime=1000000666L, units='1', methodName='myMethod', exception=TimeoutException) {
+  private void assertPassesNormalFailsSlowExecution(c, long expireTime=1000000666L, units='1', methodName='myMethod', exception=TimeoutException, timeUnitName='seconds') {
     def system = new StubFor(System)
     // start time initialized to the Long of the Beast
     system.demand.nanoTime() { 666L }
@@ -266,7 +268,7 @@ class TimedInterruptTest extends GroovyTestCase {
       def e = shouldFail(exception) {
         instance."$methodName"()
       }
-      assert e.contains('Execution timed out after ' + units + ' units')
+      assert e.contains('Execution timed out after ' + units + ' ' + timeUnitName)
     }
   }
 


[3/3] groovy git commit: GROOVY-8204: @Delegate on arrays causes NPE during compilation (closes #551)

Posted by pa...@apache.org.
GROOVY-8204: @Delegate on arrays causes NPE during compilation (closes #551)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/cfadc929
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/cfadc929
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/cfadc929

Branch: refs/heads/GROOVY_2_6_X
Commit: cfadc929ba4781e402687c0dafb9002bfe5d2fb6
Parents: e264347
Author: paulk <pa...@asert.com.au>
Authored: Thu May 25 23:37:14 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Fri May 26 12:05:20 2017 +1000

----------------------------------------------------------------------
 .../org/codehaus/groovy/ast/ClassHelper.java    | 323 ++++++++++---------
 .../groovy/ast/tools/GenericsUtils.java         |   2 +
 .../transform/DelegateASTTransformation.java    |  11 +
 .../transform/DelegateTransformTest.groovy      |  18 +-
 4 files changed, 192 insertions(+), 162 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/cfadc929/src/main/org/codehaus/groovy/ast/ClassHelper.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/ClassHelper.java b/src/main/org/codehaus/groovy/ast/ClassHelper.java
index a52085d..6fc6a22 100644
--- a/src/main/org/codehaus/groovy/ast/ClassHelper.java
+++ b/src/main/org/codehaus/groovy/ast/ClassHelper.java
@@ -41,90 +41,87 @@ import java.lang.reflect.Modifier;
 
 /**
  * This class is a Helper for ClassNode and classes handling ClassNodes.
- * It does contain a set of predefined ClassNodes for the most used 
- * types and some code for cached ClassNode creation and basic 
- * ClassNode handling 
- * 
- * @author Jochen Theodorou
+ * It does contain a set of predefined ClassNodes for the most used
+ * types and some code for cached ClassNode creation and basic
+ * ClassNode handling
  */
 public class ClassHelper {
 
-    private static final Class[] classes = new Class[] {
-        Object.class, Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE,
-        Integer.TYPE, Long.TYPE, Double.TYPE, Float.TYPE, Void.TYPE,
-        Closure.class, GString.class, List.class, Map.class, Range.class,
-        Pattern.class, Script.class, String.class,  Boolean.class, 
-        Character.class, Byte.class, Short.class, Integer.class, Long.class,
-        Double.class, Float.class, BigDecimal.class, BigInteger.class, 
-        Number.class, Void.class, Reference.class, Class.class, MetaClass.class, 
-        Iterator.class, GeneratedClosure.class, GroovyObjectSupport.class
+    private static final Class[] classes = new Class[]{
+            Object.class, Boolean.TYPE, Character.TYPE, Byte.TYPE, Short.TYPE,
+            Integer.TYPE, Long.TYPE, Double.TYPE, Float.TYPE, Void.TYPE,
+            Closure.class, GString.class, List.class, Map.class, Range.class,
+            Pattern.class, Script.class, String.class, Boolean.class,
+            Character.class, Byte.class, Short.class, Integer.class, Long.class,
+            Double.class, Float.class, BigDecimal.class, BigInteger.class,
+            Number.class, Void.class, Reference.class, Class.class, MetaClass.class,
+            Iterator.class, GeneratedClosure.class, GroovyObjectSupport.class
     };
 
-    private static final String[] primitiveClassNames = new String[] {
-        "", "boolean", "char", "byte", "short", 
-        "int", "long", "double", "float", "void"
+    private static final String[] primitiveClassNames = new String[]{
+            "", "boolean", "char", "byte", "short",
+            "int", "long", "double", "float", "void"
     };
-    
-    public static final ClassNode 
-        DYNAMIC_TYPE = makeCached(Object.class),  OBJECT_TYPE = DYNAMIC_TYPE,
-        VOID_TYPE = makeCached(Void.TYPE),        CLOSURE_TYPE = makeCached(Closure.class),
-        GSTRING_TYPE = makeCached(GString.class), LIST_TYPE = makeWithoutCaching(List.class),
-        MAP_TYPE = makeWithoutCaching(Map.class), RANGE_TYPE = makeCached(Range.class),
-        PATTERN_TYPE = makeCached(Pattern.class), STRING_TYPE = makeCached(String.class),
-        SCRIPT_TYPE = makeCached(Script.class),   REFERENCE_TYPE = makeWithoutCaching(Reference.class),
-        BINDING_TYPE = makeCached(Binding.class),
-
-        boolean_TYPE = makeCached(boolean.class),     char_TYPE = makeCached(char.class),
-        byte_TYPE = makeCached(byte.class),           int_TYPE = makeCached(int.class),
-        long_TYPE = makeCached(long.class),           short_TYPE = makeCached(short.class),
-        double_TYPE = makeCached(double.class),       float_TYPE = makeCached(float.class),
-        Byte_TYPE = makeCached(Byte.class),           Short_TYPE = makeCached(Short.class),
-        Integer_TYPE = makeCached(Integer.class),     Long_TYPE = makeCached(Long.class),
-        Character_TYPE = makeCached(Character.class), Float_TYPE = makeCached(Float.class),
-        Double_TYPE = makeCached(Double.class),       Boolean_TYPE = makeCached(Boolean.class),
-        BigInteger_TYPE =  makeCached(java.math.BigInteger.class),
-        BigDecimal_TYPE = makeCached(java.math.BigDecimal.class),
-        Number_TYPE = makeCached(Number.class),
-        
-        void_WRAPPER_TYPE = makeCached(Void.class),   METACLASS_TYPE = makeCached(MetaClass.class),
-        Iterator_TYPE = makeCached(Iterator.class),
-
-        Enum_Type = makeWithoutCaching(Enum.class),
-        Annotation_TYPE = makeCached(Annotation.class),
-        ELEMENT_TYPE_TYPE = makeCached(ElementType.class),
-
-        // uncached constants.
-        CLASS_Type = makeWithoutCaching(Class.class), COMPARABLE_TYPE = makeWithoutCaching(Comparable.class),        
-        GENERATED_CLOSURE_Type = makeWithoutCaching(GeneratedClosure.class),
-        GROOVY_OBJECT_SUPPORT_TYPE = makeWithoutCaching(GroovyObjectSupport.class),
-        GROOVY_OBJECT_TYPE = makeWithoutCaching(GroovyObject.class),
-        GROOVY_INTERCEPTABLE_TYPE = makeWithoutCaching(GroovyInterceptable.class)
-        ;
-    
-    private static final ClassNode[] types = new ClassNode[] {
-        OBJECT_TYPE,
-        boolean_TYPE, char_TYPE, byte_TYPE, short_TYPE,
-        int_TYPE, long_TYPE, double_TYPE, float_TYPE,
-        VOID_TYPE, CLOSURE_TYPE, GSTRING_TYPE,
-        LIST_TYPE, MAP_TYPE, RANGE_TYPE, PATTERN_TYPE,
-        SCRIPT_TYPE, STRING_TYPE, Boolean_TYPE, Character_TYPE,
-        Byte_TYPE, Short_TYPE, Integer_TYPE, Long_TYPE,
-        Double_TYPE, Float_TYPE, BigDecimal_TYPE, BigInteger_TYPE,
-        Number_TYPE,
-        void_WRAPPER_TYPE, REFERENCE_TYPE, CLASS_Type, METACLASS_TYPE,
-        Iterator_TYPE, GENERATED_CLOSURE_Type, GROOVY_OBJECT_SUPPORT_TYPE, 
-        GROOVY_OBJECT_TYPE, GROOVY_INTERCEPTABLE_TYPE, Enum_Type, Annotation_TYPE
+
+    public static final ClassNode
+            DYNAMIC_TYPE = makeCached(Object.class), OBJECT_TYPE = DYNAMIC_TYPE,
+            VOID_TYPE = makeCached(Void.TYPE), CLOSURE_TYPE = makeCached(Closure.class),
+            GSTRING_TYPE = makeCached(GString.class), LIST_TYPE = makeWithoutCaching(List.class),
+            MAP_TYPE = makeWithoutCaching(Map.class), RANGE_TYPE = makeCached(Range.class),
+            PATTERN_TYPE = makeCached(Pattern.class), STRING_TYPE = makeCached(String.class),
+            SCRIPT_TYPE = makeCached(Script.class), REFERENCE_TYPE = makeWithoutCaching(Reference.class),
+            BINDING_TYPE = makeCached(Binding.class),
+
+    boolean_TYPE = makeCached(boolean.class), char_TYPE = makeCached(char.class),
+            byte_TYPE = makeCached(byte.class), int_TYPE = makeCached(int.class),
+            long_TYPE = makeCached(long.class), short_TYPE = makeCached(short.class),
+            double_TYPE = makeCached(double.class), float_TYPE = makeCached(float.class),
+            Byte_TYPE = makeCached(Byte.class), Short_TYPE = makeCached(Short.class),
+            Integer_TYPE = makeCached(Integer.class), Long_TYPE = makeCached(Long.class),
+            Character_TYPE = makeCached(Character.class), Float_TYPE = makeCached(Float.class),
+            Double_TYPE = makeCached(Double.class), Boolean_TYPE = makeCached(Boolean.class),
+            BigInteger_TYPE = makeCached(java.math.BigInteger.class),
+            BigDecimal_TYPE = makeCached(java.math.BigDecimal.class),
+            Number_TYPE = makeCached(Number.class),
+
+    void_WRAPPER_TYPE = makeCached(Void.class), METACLASS_TYPE = makeCached(MetaClass.class),
+            Iterator_TYPE = makeCached(Iterator.class),
+
+    Enum_Type = makeWithoutCaching(Enum.class),
+            Annotation_TYPE = makeCached(Annotation.class),
+            ELEMENT_TYPE_TYPE = makeCached(ElementType.class),
+
+    // uncached constants.
+    CLASS_Type = makeWithoutCaching(Class.class), COMPARABLE_TYPE = makeWithoutCaching(Comparable.class),
+            GENERATED_CLOSURE_Type = makeWithoutCaching(GeneratedClosure.class),
+            GROOVY_OBJECT_SUPPORT_TYPE = makeWithoutCaching(GroovyObjectSupport.class),
+            GROOVY_OBJECT_TYPE = makeWithoutCaching(GroovyObject.class),
+            GROOVY_INTERCEPTABLE_TYPE = makeWithoutCaching(GroovyInterceptable.class);
+
+    private static final ClassNode[] types = new ClassNode[]{
+            OBJECT_TYPE,
+            boolean_TYPE, char_TYPE, byte_TYPE, short_TYPE,
+            int_TYPE, long_TYPE, double_TYPE, float_TYPE,
+            VOID_TYPE, CLOSURE_TYPE, GSTRING_TYPE,
+            LIST_TYPE, MAP_TYPE, RANGE_TYPE, PATTERN_TYPE,
+            SCRIPT_TYPE, STRING_TYPE, Boolean_TYPE, Character_TYPE,
+            Byte_TYPE, Short_TYPE, Integer_TYPE, Long_TYPE,
+            Double_TYPE, Float_TYPE, BigDecimal_TYPE, BigInteger_TYPE,
+            Number_TYPE,
+            void_WRAPPER_TYPE, REFERENCE_TYPE, CLASS_Type, METACLASS_TYPE,
+            Iterator_TYPE, GENERATED_CLOSURE_Type, GROOVY_OBJECT_SUPPORT_TYPE,
+            GROOVY_OBJECT_TYPE, GROOVY_INTERCEPTABLE_TYPE, Enum_Type, Annotation_TYPE
     };
 
-    private static final int ABSTRACT_STATIC_PRIVATE = 
-            Modifier.ABSTRACT|Modifier.PRIVATE|Modifier.STATIC;
+    private static final int ABSTRACT_STATIC_PRIVATE =
+            Modifier.ABSTRACT | Modifier.PRIVATE | Modifier.STATIC;
     private static final int VISIBILITY = 5; // public|protected
-    
+
     protected static final ClassNode[] EMPTY_TYPE_ARRAY = {};
-    
+
     public static final String OBJECT = "java.lang.Object";
 
-    public static ClassNode makeCached(Class c){
+    public static ClassNode makeCached(Class c) {
         final SoftReference<ClassNode> classNodeSoftReference = ClassHelperCache.classCache.get(c);
         ClassNode classNode;
         if (classNodeSoftReference == null || (classNode = classNodeSoftReference.get()) == null) {
@@ -136,146 +133,146 @@ public class ClassHelper {
 
         return classNode;
     }
-    
+
     /**
      * Creates an array of ClassNodes using an array of classes.
-     * For each of the given classes a new ClassNode will be 
+     * For each of the given classes a new ClassNode will be
      * created
-     * @see #make(Class)
+     *
      * @param classes an array of classes used to create the ClassNodes
      * @return an array of ClassNodes
+     * @see #make(Class)
      */
     public static ClassNode[] make(Class[] classes) {
         ClassNode[] cns = new ClassNode[classes.length];
-        for (int i=0; i<cns.length; i++) {
+        for (int i = 0; i < cns.length; i++) {
             cns[i] = make(classes[i]);
         }
-        
+
         return cns;
     }
-    
+
     /**
      * Creates a ClassNode using a given class.
      * A new ClassNode object is only created if the class
      * is not one of the predefined ones
-     * 
+     *
      * @param c class used to created the ClassNode
      * @return ClassNode instance created from the given class
      */
     public static ClassNode make(Class c) {
-        return make(c,true);
+        return make(c, true);
     }
-    
+
     public static ClassNode make(Class c, boolean includeGenerics) {
-        for (int i=0; i<classes.length; i++) {
-            if (c==classes[i]) return types[i];
+        for (int i = 0; i < classes.length; i++) {
+            if (c == classes[i]) return types[i];
         }
         if (c.isArray()) {
-            ClassNode cn = make(c.getComponentType(),includeGenerics);
+            ClassNode cn = make(c.getComponentType(), includeGenerics);
             return cn.makeArray();
         }
-        return makeWithoutCaching(c,includeGenerics);
+        return makeWithoutCaching(c, includeGenerics);
     }
-    
-    public static ClassNode makeWithoutCaching(Class c){
-        return makeWithoutCaching(c,true);
+
+    public static ClassNode makeWithoutCaching(Class c) {
+        return makeWithoutCaching(c, true);
     }
-    
-    public static ClassNode makeWithoutCaching(Class c, boolean includeGenerics){
+
+    public static ClassNode makeWithoutCaching(Class c, boolean includeGenerics) {
         if (c.isArray()) {
-            ClassNode cn = makeWithoutCaching(c.getComponentType(),includeGenerics);
+            ClassNode cn = makeWithoutCaching(c.getComponentType(), includeGenerics);
             return cn.makeArray();
         }
 
         final ClassNode cached = makeCached(c);
         if (includeGenerics) {
             return cached;
-        }
-        else {
+        } else {
             ClassNode t = makeWithoutCaching(c.getName());
             t.setRedirect(cached);
             return t;
         }
     }
-    
-    
+
+
     /**
      * Creates a ClassNode using a given class.
      * Unlike make(String) this method will not use the cache
      * to create the ClassNode. This means the ClassNode created
      * from this method using the same name will have a different
      * reference
-     * 
-     * @see #make(String)
+     *
      * @param name of the class the ClassNode is representing
+     * @see #make(String)
      */
-    public static ClassNode makeWithoutCaching(String name) { 
-        ClassNode cn = new ClassNode(name,Opcodes.ACC_PUBLIC,OBJECT_TYPE);
+    public static ClassNode makeWithoutCaching(String name) {
+        ClassNode cn = new ClassNode(name, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
         cn.isPrimaryNode = false;
         return cn;
     }
-    
-    /**     * Creates a ClassNode using a given class.
-     * If the name is one of the predefined ClassNodes then the 
+
+    /**
+     * Creates a ClassNode using a given class.
+     * If the name is one of the predefined ClassNodes then the
      * corresponding ClassNode instance will be returned. If the
      * name is null or of length 0 the dynamic type is returned
-     * 
+     *
      * @param name of the class the ClassNode is representing
      */
     public static ClassNode make(String name) {
         if (name == null || name.length() == 0) return DYNAMIC_TYPE;
-        
-        for (int i=0; i<primitiveClassNames.length; i++) {
+
+        for (int i = 0; i < primitiveClassNames.length; i++) {
             if (primitiveClassNames[i].equals(name)) return types[i];
         }
-        
-        for (int i=0; i<classes.length; i++) {
+
+        for (int i = 0; i < classes.length; i++) {
             String cname = classes[i].getName();
             if (name.equals(cname)) return types[i];
-        }        
+        }
         return makeWithoutCaching(name);
     }
-    
+
     /**
-     * Creates a ClassNode containing the wrapper of a ClassNode 
+     * Creates a ClassNode containing the wrapper of a ClassNode
      * of primitive type. Any ClassNode representing a primitive
      * type should be created using the predefined types used in
-     * class. The method will check the parameter for known 
+     * class. The method will check the parameter for known
      * references of ClassNode representing a primitive type. If
      * Reference is found, then a ClassNode will be contained that
      * represents the wrapper class. For example for boolean, the
      * wrapper class is java.lang.Boolean.
-     * 
-     * If the parameter is no primitive type, the redirected 
-     * ClassNode will be returned 
-     *   
+     * <p>
+     * If the parameter is no primitive type, the redirected
+     * ClassNode will be returned
+     *
+     * @param cn the ClassNode containing a possible primitive type
      * @see #make(Class)
      * @see #make(String)
-     * @param cn the ClassNode containing a possible primitive type
      */
     public static ClassNode getWrapper(ClassNode cn) {
         cn = cn.redirect();
         if (!isPrimitiveType(cn)) return cn;
-        if (cn==boolean_TYPE) {
+        if (cn == boolean_TYPE) {
             return Boolean_TYPE;
-        } else if (cn==byte_TYPE) {
+        } else if (cn == byte_TYPE) {
             return Byte_TYPE;
-        } else if (cn==char_TYPE) {
+        } else if (cn == char_TYPE) {
             return Character_TYPE;
-        } else if (cn==short_TYPE) {
+        } else if (cn == short_TYPE) {
             return Short_TYPE;
-        } else if (cn==int_TYPE) {
+        } else if (cn == int_TYPE) {
             return Integer_TYPE;
-        } else if (cn==long_TYPE) {
+        } else if (cn == long_TYPE) {
             return Long_TYPE;
-        } else if (cn==float_TYPE) {
+        } else if (cn == float_TYPE) {
             return Float_TYPE;
-        } else if (cn==double_TYPE) {
+        } else if (cn == double_TYPE) {
             return Double_TYPE;
-        } else if (cn==VOID_TYPE) {
+        } else if (cn == VOID_TYPE) {
             return void_WRAPPER_TYPE;
-        }
-        else {
+        } else {
             return cn;
         }
     }
@@ -283,24 +280,23 @@ public class ClassHelper {
     public static ClassNode getUnwrapper(ClassNode cn) {
         cn = cn.redirect();
         if (isPrimitiveType(cn)) return cn;
-        if (cn==Boolean_TYPE) {
+        if (cn == Boolean_TYPE) {
             return boolean_TYPE;
-        } else if (cn==Byte_TYPE) {
+        } else if (cn == Byte_TYPE) {
             return byte_TYPE;
-        } else if (cn==Character_TYPE) {
+        } else if (cn == Character_TYPE) {
             return char_TYPE;
-        } else if (cn==Short_TYPE) {
+        } else if (cn == Short_TYPE) {
             return short_TYPE;
-        } else if (cn==Integer_TYPE) {
+        } else if (cn == Integer_TYPE) {
             return int_TYPE;
-        } else if (cn==Long_TYPE) {
+        } else if (cn == Long_TYPE) {
             return long_TYPE;
-        } else if (cn==Float_TYPE) {
+        } else if (cn == Float_TYPE) {
             return float_TYPE;
-        } else if (cn==Double_TYPE) {
+        } else if (cn == Double_TYPE) {
             return double_TYPE;
-        }
-        else {
+        } else {
             return cn;
         }
     }
@@ -310,14 +306,14 @@ public class ClassHelper {
      * Test to determine if a ClassNode is a primitive type.
      * Note: this only works for ClassNodes created using a
      * predefined ClassNode
-     * 
-     * @see #make(Class)
-     * @see #make(String)
+     *
      * @param cn the ClassNode containing a possible primitive type
      * @return true if the ClassNode is a primitive type
+     * @see #make(Class)
+     * @see #make(String)
      */
     public static boolean isPrimitiveType(ClassNode cn) {
-        return  cn == boolean_TYPE ||
+        return cn == boolean_TYPE ||
                 cn == char_TYPE ||
                 cn == byte_TYPE ||
                 cn == short_TYPE ||
@@ -331,17 +327,17 @@ public class ClassHelper {
     /**
      * Test to determine if a ClassNode is a type belongs to the list of types which
      * are allowed to initialize constants directly in bytecode instead of using &lt;cinit&gt;
-     *
+     * <p>
      * Note: this only works for ClassNodes created using a
      * predefined ClassNode
      *
-     * @see #make(Class)
-     * @see #make(String)
      * @param cn the ClassNode to be tested
      * @return true if the ClassNode is of int, float, long, double or String type
+     * @see #make(Class)
+     * @see #make(String)
      */
     public static boolean isStaticConstantInitializerType(ClassNode cn) {
-        return  cn == int_TYPE ||
+        return cn == int_TYPE ||
                 cn == float_TYPE ||
                 cn == long_TYPE ||
                 cn == double_TYPE ||
@@ -353,7 +349,7 @@ public class ClassHelper {
     }
 
     public static boolean isNumberType(ClassNode cn) {
-        return  cn == Byte_TYPE ||
+        return cn == Byte_TYPE ||
                 cn == Short_TYPE ||
                 cn == Integer_TYPE ||
                 cn == Long_TYPE ||
@@ -381,13 +377,14 @@ public class ClassHelper {
     static class ClassHelperCache {
         static ManagedConcurrentMap<Class, SoftReference<ClassNode>> classCache = new ManagedConcurrentMap<Class, SoftReference<ClassNode>>(ReferenceBundle.getWeakBundle());
     }
-    
+
     public static boolean isSAMType(ClassNode type) {
         return findSAM(type) != null;
     }
 
     /**
      * Returns the single abstract method of a class node, if it is a SAM type, or null otherwise.
+     *
      * @param type a type for which to search for a single abstract method
      * @return the method node if type is a SAM type, null otherwise
      */
@@ -395,17 +392,17 @@ public class ClassHelper {
         if (!Modifier.isAbstract(type.getModifiers())) return null;
         if (type.isInterface()) {
             List<MethodNode> methods = type.getMethods();
-            MethodNode found=null;
+            MethodNode found = null;
             for (MethodNode mi : methods) {
                 // ignore methods, that are not abstract and from Object
                 if (!Modifier.isAbstract(mi.getModifiers())) continue;
                 // ignore trait methods which have a default implementation
                 if (Traits.hasDefaultImplementation(mi)) continue;
                 if (mi.getDeclaringClass().equals(OBJECT_TYPE)) continue;
-                if (OBJECT_TYPE.getDeclaredMethod(mi.getName(), mi.getParameters())!=null) continue;
+                if (OBJECT_TYPE.getDeclaredMethod(mi.getName(), mi.getParameters()) != null) continue;
 
                 // we have two methods, so no SAM
-                if (found!=null) return null;
+                if (found != null) return null;
                 found = mi;
             }
             return found;
@@ -414,10 +411,10 @@ public class ClassHelper {
 
             List<MethodNode> methods = type.getAbstractMethods();
             MethodNode found = null;
-            if (methods!=null) {
+            if (methods != null) {
                 for (MethodNode mi : methods) {
                     if (!hasUsableImplementation(type, mi)) {
-                        if (found!=null) return null;
+                        if (found != null) return null;
                         found = mi;
                     }
                 }
@@ -427,12 +424,12 @@ public class ClassHelper {
     }
 
     private static boolean hasUsableImplementation(ClassNode c, MethodNode m) {
-        if (c==m.getDeclaringClass()) return false;
+        if (c == m.getDeclaringClass()) return false;
         MethodNode found = c.getDeclaredMethod(m.getName(), m.getParameters());
-        if (found==null) return false;
+        if (found == null) return false;
         int asp = found.getModifiers() & ABSTRACT_STATIC_PRIVATE;
         int visible = found.getModifiers() & VISIBILITY;
-        if (visible !=0 && asp == 0) return true;
+        if (visible != 0 && asp == 0) return true;
         if (c.equals(OBJECT_TYPE)) return false;
         return hasUsableImplementation(c.getSuperClass(), m);
     }
@@ -440,14 +437,18 @@ public class ClassHelper {
     /**
      * Returns a super class or interface for a given class depending on a given target.
      * If the target is no super class or interface, then null will be returned.
-     * @param clazz the start class
+     * For a non-primitive array type, returns an array of the componentType's super class
+     * or interface if the target is also an array.
+     *
+     * @param clazz     the start class
      * @param goalClazz the goal class
      * @return the next super class or interface
      */
     public static ClassNode getNextSuperClass(ClassNode clazz, ClassNode goalClazz) {
         if (clazz.isArray()) {
-            ClassNode cn = getNextSuperClass(clazz.getComponentType(),goalClazz.getComponentType());
-            if (cn!=null) cn = cn.makeArray();
+            if (!goalClazz.isArray()) return null;
+            ClassNode cn = getNextSuperClass(clazz.getComponentType(), goalClazz.getComponentType());
+            if (cn != null) cn = cn.makeArray();
             return cn;
         }
 
@@ -461,9 +462,9 @@ public class ClassHelper {
         }
 
         ClassNode[] interfaces = clazz.getUnresolvedInterfaces();
-        for (int i=0; i<interfaces.length; i++) {
-            if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(interfaces[i],goalClazz)) {
-                return interfaces[i];
+        for (ClassNode anInterface : interfaces) {
+            if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(anInterface, goalClazz)) {
+                return anInterface;
             }
         }
         //none of the interfaces here match, so continue with super class

http://git-wip-us.apache.org/repos/asf/groovy/blob/cfadc929/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 79449e4..653f327 100644
--- a/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -431,6 +431,8 @@ public class GenericsUtils {
         if (target==null || type==target) return;
         if (type.isArray() && target.isArray()) {
             extractSuperClassGenerics(type.getComponentType(), target.getComponentType(), spec);
+        } else if (type.isArray() && target.getName().equals("java.lang.Object")) {
+            // Object is superclass of arrays but no generics involved
         } else if (target.isGenericsPlaceHolder() || type.equals(target) || !StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(type, target)) {
             // structural match route
             if (target.isGenericsPlaceHolder()) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/cfadc929/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java b/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java
index 8e1daa5..d56da3d 100644
--- a/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/DelegateASTTransformation.java
@@ -164,6 +164,17 @@ public class DelegateASTTransformation extends AbstractASTTransformation {
                 addGetterIfNeeded(delegate, prop, name, allNames);
                 addSetterIfNeeded(delegate, prop, name, allNames);
             }
+            if (delegate.type.isArray()) {
+                boolean skipLength = delegate.excludes != null && (delegate.excludes.contains("length") || delegate.excludes.contains("getLength"));
+                if (!skipLength) {
+                    delegate.owner.addMethod("getLength",
+                            ACC_PUBLIC,
+                            ClassHelper.int_TYPE,
+                            Parameter.EMPTY_ARRAY,
+                            null,
+                            returnS(propX(delegate.getOp, "length")));
+                }
+            }
 
             if (skipInterfaces) return;
 

http://git-wip-us.apache.org/repos/asf/groovy/blob/cfadc929/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy b/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
index 5dd6930..3321344 100644
--- a/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/DelegateTransformTest.groovy
@@ -21,7 +21,7 @@ package org.codehaus.groovy.transform
 import gls.CompilableTestSupport
 
 /**
- * Tests for the @{code @Delegate} AST transform.
+ * Tests for the {@code @Delegate} AST transform.
  */
 class DelegateTransformTest extends CompilableTestSupport {
 
@@ -811,6 +811,22 @@ assert foo.dm.x == '123'
             assert new Foo(bar: new Bar()).pls() == 'foo pls'
         '''
     }
+
+    // GROOVY-8204
+    void testDelegateToArray() {
+        assertScript '''
+            import groovy.lang.Delegate
+
+            class BugsMe {
+                @Delegate
+                String[] content = ['foo', 'bar']
+            }
+
+            assert new BugsMe().content.join() == 'foobar'
+            assert new BugsMe().content.length == 2
+            assert new BugsMe().length == 2
+        '''
+    }
 }
 
 interface DelegateFoo {


[2/3] groovy git commit: GROOVY-8203: Add @Newify will cause ?. operator NPE (closes #550)

Posted by pa...@apache.org.
GROOVY-8203: Add @Newify will cause ?. operator NPE (closes #550)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/e2643472
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/e2643472
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/e2643472

Branch: refs/heads/GROOVY_2_6_X
Commit: e2643472f37dcd291bd828c4b602b4a76a52745f
Parents: c2eb667
Author: paulk <pa...@asert.com.au>
Authored: Thu May 25 17:26:54 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Fri May 26 12:05:20 2017 +1000

----------------------------------------------------------------------
 .../groovy/transform/NewifyASTTransformation.java |  5 ++---
 .../groovy/transform/NewifyTransformTest.groovy   | 18 ++++++++++++++++--
 2 files changed, 18 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/e2643472/src/main/org/codehaus/groovy/transform/NewifyASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/NewifyASTTransformation.java b/src/main/org/codehaus/groovy/transform/NewifyASTTransformation.java
index 909b6ec..55ae7de 100644
--- a/src/main/org/codehaus/groovy/transform/NewifyASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/NewifyASTTransformation.java
@@ -49,9 +49,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 
 /**
- * Handles generation of code for the @Newify annotation.
- *
- * @author Paul King
+ * Handles generation of code for the {@code @Newify} AST transform.
  */
 @GroovyASTTransformation(phase = CompilePhase.CANONICALIZATION)
 public class NewifyASTTransformation extends ClassCodeExpressionTransformer implements ASTTransformation {
@@ -167,6 +165,7 @@ public class NewifyASTTransformation extends ClassCodeExpressionTransformer impl
             Expression object = transform(mce.getObjectExpression());
             MethodCallExpression transformed = callX(object, method, args);
             transformed.setImplicitThis(mce.isImplicitThis());
+            transformed.setSafe(mce.isSafe());
             transformed.setSourcePosition(mce);
             return transformed;
         } else if (expr instanceof ClosureExpression) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/e2643472/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy b/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
index b6d0255..e3e9890 100644
--- a/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/NewifyTransformTest.groovy
@@ -19,7 +19,7 @@
 package org.codehaus.groovy.transform
 
 /**
- * @author Paul King
+ * Tests for the {@code @Newify} AST transform.
  */
 class NewifyTransformTest extends GroovyShellTestCase {
 
@@ -158,7 +158,6 @@ class NewifyTransformTest extends GroovyShellTestCase {
         assert test == 'ABC'
     }
 
-
     void testNewifyClosureCompileStatic_Groovy7758() {
         assertScript '''
             class A {
@@ -175,4 +174,19 @@ class NewifyTransformTest extends GroovyShellTestCase {
             assert test(new A()) == 'abc'
         '''
     }
+
+    void testNewifyTransformPreservesSafeMethodCall_Groovy8203() {
+        assertScript '''
+            @Newify(A)
+            class Z {
+                def foo() {
+                    def a
+                    a?.get('b')
+                }
+                class A {}
+            }
+
+            assert !new Z().foo()
+        '''
+    }
 }
\ No newline at end of file