You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2022/08/06 14:25:02 UTC

[groovy] branch master updated: Minor tweak: avoid throwing exceptions and extract variables

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3fa69b2343 Minor tweak: avoid throwing exceptions and extract variables
3fa69b2343 is described below

commit 3fa69b2343fd9dfdf23ffb930e3c90cfa58b2593
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sat Aug 6 21:47:34 2022 +0800

    Minor tweak: avoid throwing exceptions and extract variables
---
 .../reflection/stdclasses/CachedSAMClass.java      | 94 ++++++++++++----------
 1 file changed, 50 insertions(+), 44 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java
index 60d545c183..7483619106 100644
--- a/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java
+++ b/src/main/java/org/codehaus/groovy/reflection/stdclasses/CachedSAMClass.java
@@ -33,15 +33,15 @@ import java.lang.reflect.Proxy;
 import java.security.PrivilegedAction;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 public class CachedSAMClass extends CachedClass {
 
-    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
     private static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
     private final Method method;
@@ -49,7 +49,7 @@ public class CachedSAMClass extends CachedClass {
     public CachedSAMClass(Class klazz, ClassInfo classInfo) {
         super(klazz, classInfo);
         method = getSAMMethod(klazz);
-        if (method==null) throw new GroovyBugError("assigned method should not have been null!");
+        if (method == null) throw new GroovyBugError("assigned method should not have been null!");
     }
 
     @Override
@@ -66,26 +66,23 @@ public class CachedSAMClass extends CachedClass {
     /* Should we make the following method private? */
     @SuppressWarnings("unchecked")
     public static Object coerceToSAM(Closure argument, Method method, Class clazz, boolean isInterface) {
-        if (argument!=null && clazz.isAssignableFrom(argument.getClass())) {
+        if (argument != null && clazz.isAssignableFrom(argument.getClass())) {
             return argument;
         }
+
+        final String name = method.getName();
         if (isInterface) {
             if (Traits.isTrait(clazz)) {
-                Map<String,Closure> impl = Collections.singletonMap(
-                        method.getName(),
-                        argument
-                );
-                return ProxyGenerator.INSTANCE.instantiateAggregate(impl,Collections.singletonList(clazz));
+                Map<String, Closure> impl = Collections.singletonMap(name, argument);
+                return ProxyGenerator.INSTANCE.instantiateAggregate(impl, Collections.singletonList(clazz));
             }
             return Proxy.newProxyInstance(
                     clazz.getClassLoader(),
-                    new Class[]{clazz},
+                    new Class[] { clazz },
                     new ConvertedClosure(argument));
         } else {
-            Map<String, Object> m = new HashMap<String,Object>();
-            m.put(method.getName(), argument);
-            return ProxyGenerator.INSTANCE.
-                    instantiateAggregateFromBaseClass(m, clazz);
+            Map<String, Object> m = Collections.singletonMap(name, argument);
+            return ProxyGenerator.INSTANCE.instantiateAggregateFromBaseClass(m, clazz);
         }
     }
 
@@ -100,49 +97,51 @@ public class CachedSAMClass extends CachedClass {
     }
 
     @SuppressWarnings("removal") // TODO a future Groovy version should remove the security check
-    private static Method[] getDeclaredMethods(final Class c) {
+    private static Method[] getDeclaredMethods(final Class<?> c) {
         try {
             Method[] methods = java.security.AccessController.doPrivileged((PrivilegedAction<Method[]>) c::getDeclaredMethods);
-            if (methods!=null) return methods;
+            if (methods != null) return methods;
         } catch (java.security.AccessControlException ace) {
             // swallow and do as if no method is available
         }
         return EMPTY_METHOD_ARRAY;
     }
 
-    private static void getAbstractMethods(Class c, List<Method> current) {
-        if (c==null || !Modifier.isAbstract(c.getModifiers())) return;
+    private static void getAbstractMethods(Class<?> c, List<Method> current) {
+        if (c == null || !Modifier.isAbstract(c.getModifiers())) return;
         getAbstractMethods(c.getSuperclass(), current);
-        for (Class ci : c.getInterfaces()) {
+        for (Class<?> ci : c.getInterfaces()) {
             getAbstractMethods(ci, current);
         }
         for (Method m : getDeclaredMethods(c)) {
-            if (Modifier.isPrivate(m.getModifiers())) continue;
-            if (Modifier.isAbstract(m.getModifiers())) current.add(m);
+            final int modifiers = m.getModifiers();
+            if (Modifier.isPrivate(modifiers)) continue;
+            if (Modifier.isAbstract(modifiers)) current.add(m);
         }
     }
 
-    private static boolean hasUsableImplementation(Class c, Method m) {
-        if (c==m.getDeclaringClass()) return false;
+    private static boolean hasUsableImplementation(Class<?> c, Method m) {
+        if (c == m.getDeclaringClass()) return false;
         Method found;
         try {
             found = c.getMethod(m.getName(), m.getParameterTypes());
-            int asp = found.getModifiers() & ABSTRACT_STATIC_PRIVATE;
-            int visible = found.getModifiers() & VISIBILITY;
-            if (visible !=0 && asp == 0) return true;
-        } catch (NoSuchMethodException e) {/*ignore*/}
-        if (c==Object.class) return false;
+            final int modifiers = found.getModifiers();
+            int asp = modifiers & ABSTRACT_STATIC_PRIVATE;
+            int visible = modifiers & VISIBILITY;
+            if (visible != 0 && asp == 0) return true;
+        } catch (NoSuchMethodException ignore) {
+        }
+        if (c == Object.class) return false;
         return hasUsableImplementation(c.getSuperclass(), m);
     }
 
     private static Method getSingleNonDuplicateMethod(List<Method> current) {
-        if (current.isEmpty()) return null;
-        if (current.size()==1) return current.get(0);
+        final int size = current.size();
+        if (size == 0) return null;
+        if (size == 1) return current.get(0);
         Method m = current.remove(0);
         for (Method m2 : current) {
-            if (m.getName().equals(m2.getName()) &&
-                Arrays.equals(m.getParameterTypes(), m2.getParameterTypes()))
-            {
+            if (m.getName().equals(m2.getName()) && Arrays.equals(m.getParameterTypes(), m2.getParameterTypes())) {
                 continue;
             }
             return null;
@@ -168,32 +167,39 @@ public class CachedSAMClass extends CachedClass {
         // if the class is not abstract there is no abstract method
         if (!Modifier.isAbstract(c.getModifiers())) return null;
         if (c.isInterface()) {
-            Method[] methods = c.getMethods();
             // res stores the first found abstract method
             Method res = null;
-            for (Method mi : methods) {
+            for (Method mi : c.getMethods()) {
                 // ignore methods, that are not abstract and from Object
                 if (!Modifier.isAbstract(mi.getModifiers())) continue;
                 // ignore trait methods which have a default implementation
-                if (mi.getAnnotation(Traits.Implemented.class)!=null) continue;
-                try {
-                    Object.class.getMethod(mi.getName(), mi.getParameterTypes());
-                    continue;
-                } catch (NoSuchMethodException e) {/*ignore*/}
+                if (mi.getAnnotation(Traits.Implemented.class) != null) continue;
+
+                final String name = mi.getName();
+                // avoid throwing `NoSuchMethodException` as possible as we could
+                if (OBJECT_METHOD_NAME_SET.contains(name)) {
+                    try {
+                        Object.class.getMethod(name, mi.getParameterTypes());
+                        continue;
+                    } catch (NoSuchMethodException ignore) {
+                    }
+                }
 
                 // we have two methods, so no SAM
-                if (res!=null) return null;
+                if (res != null) return null;
                 res = mi;
             }
             return res;
 
         } else {
-
-            LinkedList<Method> methods = new LinkedList();
+            List<Method> methods = new LinkedList<>();
             getAbstractMethods(c, methods);
             if (methods.isEmpty()) return null;
             methods.removeIf(m -> hasUsableImplementation(c, m));
             return getSingleNonDuplicateMethod(methods);
         }
     }
+
+    private static final Set<String> OBJECT_METHOD_NAME_SET =
+            Collections.unmodifiableSet(Arrays.stream(Object.class.getMethods()).map(m -> m.getName()).collect(Collectors.toSet()));
 }