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 2020/08/09 04:52:05 UTC

[groovy] 01/02: GROOVY-9675: There should be a mechanism to disable individual macro methods & extension methods

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

commit 443c25d5ca8e6d63306e9be0bb25a9d6592b10c9
Author: Paul King <pa...@asert.com.au>
AuthorDate: Fri Aug 7 13:09:59 2020 +1000

    GROOVY-9675: There should be a mechanism to disable individual macro methods & extension methods
---
 .../codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java | 9 +++++++++
 .../groovy/transform/stc/AbstractExtensionMethodCache.java       | 4 ++++
 .../org/codehaus/groovy/transform/stc/ExtensionMethodCache.java  | 7 +++++++
 .../org/codehaus/groovy/macro/transform/MacroMethodsCache.java   | 5 +++++
 4 files changed, 25 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java b/src/main/java/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java
index 2838978..08d8b08 100644
--- a/src/main/java/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java
+++ b/src/main/java/org/codehaus/groovy/runtime/metaclass/MetaClassRegistryImpl.java
@@ -25,6 +25,7 @@ import groovy.lang.MetaClassRegistry;
 import groovy.lang.MetaClassRegistryChangeEvent;
 import groovy.lang.MetaClassRegistryChangeEventListener;
 import groovy.lang.MetaMethod;
+import org.apache.groovy.util.SystemUtil;
 import org.codehaus.groovy.classgen.Verifier;
 import org.codehaus.groovy.reflection.CachedClass;
 import org.codehaus.groovy.reflection.CachedMethod;
@@ -66,6 +67,7 @@ public class MetaClassRegistryImpl implements MetaClassRegistry{
     public static final String MODULE_META_INF_FILE = "META-INF/services/org.codehaus.groovy.runtime.ExtensionModule";
     private static final MetaClass[] EMPTY_METACLASS_ARRAY = new MetaClass[0];
     private static final MetaClassRegistryChangeEventListener[] EMPTY_METACLASSREGISTRYCHANGEEVENTLISTENER_ARRAY = new MetaClassRegistryChangeEventListener[0];
+    public static final String EXTENSION_DISABLE_PREFIX = "groovy.extension.disable";
 
     private final boolean useAccessible;
 
@@ -76,6 +78,7 @@ public class MetaClassRegistryImpl implements MetaClassRegistry{
     private final LinkedList<MetaClassRegistryChangeEventListener> nonRemoveableChangeListenerList = new LinkedList<MetaClassRegistryChangeEventListener>();
     private final ManagedConcurrentLinkedQueue<MetaClass> metaClassInfo = new ManagedConcurrentLinkedQueue<MetaClass>(ReferenceBundle.getWeakBundle());
     private final ExtensionModuleRegistry moduleRegistry = new ExtensionModuleRegistry();
+    private final boolean canDisable = SystemUtil.getBooleanSafe(EXTENSION_DISABLE_PREFIX);
 
     public static final int LOAD_DEFAULT = 0;
     public static final int DONT_LOAD_DEFAULT = 1;
@@ -199,6 +202,9 @@ public class MetaClassRegistryImpl implements MetaClassRegistry{
                 List<GeneratedMetaMethod.DgmMethodRecord> records = GeneratedMetaMethod.DgmMethodRecord.loadDgmInfo();
 
                 for (GeneratedMetaMethod.DgmMethodRecord record : records) {
+                    if (canDisable && SystemUtil.getBooleanSafe(EXTENSION_DISABLE_PREFIX + "." + record.methodName)) {
+                        continue;
+                    }
                     Class[] newParams = new Class[record.parameters.length - 1];
                     System.arraycopy(record.parameters, 1, newParams, 0, record.parameters.length-1);
 
@@ -225,6 +231,9 @@ public class MetaClassRegistryImpl implements MetaClassRegistry{
             for (CachedMethod method : methods) {
                 final int mod = method.getModifiers();
                 if (Modifier.isStatic(mod) && Modifier.isPublic(mod) && method.getAnnotation(Deprecated.class) == null) {
+                    if (canDisable && SystemUtil.getBooleanSafe(EXTENSION_DISABLE_PREFIX + "." + method.getName())) {
+                        continue;
+                    }
                     CachedClass[] paramTypes = method.getParameterTypes();
                     if (paramTypes.length > 0) {
                         List<MetaMethod> arr = map.computeIfAbsent(paramTypes[0], k -> new ArrayList<MetaMethod>(4));
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/AbstractExtensionMethodCache.java b/src/main/java/org/codehaus/groovy/transform/stc/AbstractExtensionMethodCache.java
index df8f8b6..e55ccab 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/AbstractExtensionMethodCache.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/AbstractExtensionMethodCache.java
@@ -18,6 +18,7 @@
  */
 package org.codehaus.groovy.transform.stc;
 
+import org.apache.groovy.util.SystemUtil;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
@@ -46,6 +47,7 @@ import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
  */
 public abstract class AbstractExtensionMethodCache {
     final EvictableCache<ClassLoader, Map<String, List<MethodNode>>> cache = new StampedCommonCache<>(new WeakHashMap<>());
+    private final boolean canDisable = SystemUtil.getBooleanSafe(getDisablePrefix());
 
     public Map<String, List<MethodNode>> get(ClassLoader loader) {
         return cache.getAndPut(loader, this::getMethodsFromClassLoader);
@@ -116,12 +118,14 @@ public abstract class AbstractExtensionMethodCache {
             for (MethodNode methodNode : cn.getMethods()) {
                 if (!(methodNode.isStatic() && methodNode.isPublic()) || methodNode.getParameters().length == 0) continue;
                 if (methodFilter.test(methodNode)) continue;
+                if (canDisable && SystemUtil.getBooleanSafe(getDisablePrefix() + "." + methodNode.getName())) continue;
 
                 accumulate(accumulator, isStatic, methodNode, methodMapper);
             }
         }
     }
 
+    protected abstract String getDisablePrefix();
     protected abstract Predicate<MethodNode> getMethodFilter();
     protected abstract Function<MethodNode, String> getMethodMapper();
 
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/ExtensionMethodCache.java b/src/main/java/org/codehaus/groovy/transform/stc/ExtensionMethodCache.java
index 003cf2a..eaff591 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/ExtensionMethodCache.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/ExtensionMethodCache.java
@@ -29,6 +29,8 @@ import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
 
+import static org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.EXTENSION_DISABLE_PREFIX;
+
 /**
  * This class is used to make extension methods lookup faster. Basically, it will only
  * collect the list of extension methods (see {@link ExtensionModule} if the list of
@@ -61,6 +63,11 @@ public class ExtensionMethodCache extends AbstractExtensionMethodCache {
     }
 
     @Override
+    protected String getDisablePrefix() {
+        return EXTENSION_DISABLE_PREFIX;
+    }
+
+    @Override
     protected Predicate<MethodNode> getMethodFilter() {
         return m -> !m.getAnnotations(StaticTypeCheckingSupport.Deprecated_TYPE).isEmpty();
     }
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
index 184e0f1..dc8b74f 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/transform/MacroMethodsCache.java
@@ -42,6 +42,11 @@ class MacroMethodsCache extends AbstractExtensionMethodCache {
     protected void addAdditionalClassesToScan(Set<Class> instanceExtClasses, Set<Class> staticExtClasses) {}
 
     @Override
+    protected String getDisablePrefix() {
+        return "groovy.macro.disable";
+    }
+
+    @Override
     protected Predicate<MethodNode> getMethodFilter() {
         return m -> m.getAnnotations(MACRO_ANNOTATION_CLASS_NODE).isEmpty();
     }