@@ -84,7 +84,7 @@ public class MetaClassRegistryImpl implements MetaClassRegistry {
8484 private final ExtensionModuleRegistry moduleRegistry = new ExtensionModuleRegistry ();
8585 private final String disabledString = SystemUtil .getSystemPropertySafe (EXTENSION_DISABLE_PROPERTY );
8686 private final boolean disabling = disabledString != null ;
87- private final Set < String > disabledNames = disabling ? new HashSet <>( Arrays . asList (disabledString . split ( "," )) ) : null ;
87+ private final List < DisabledMethodSpec > disabledSpecs = disabling ? DisabledMethodSpec . parse (disabledString ) : null ;
8888
8989 public static final int LOAD_DEFAULT = 0 ;
9090 public static final int DONT_LOAD_DEFAULT = 1 ;
@@ -207,7 +207,7 @@ private void registerMethods(final Class theClass, final boolean useMethodWrappe
207207 List <GeneratedMetaMethod .DgmMethodRecord > records = GeneratedMetaMethod .DgmMethodRecord .loadDgmInfo ();
208208
209209 for (GeneratedMetaMethod .DgmMethodRecord record : records ) {
210- if (disabling && disabledNames . contains (record .methodName )) continue ;
210+ if (disabling && isDisabled (record .methodName , record . parameters )) continue ;
211211 Class [] newParams = new Class [record .parameters .length - 1 ];
212212 System .arraycopy (record .parameters , 1 , newParams , 0 , newParams .length );
213213
@@ -235,7 +235,7 @@ private void registerMethods(final Class theClass, final boolean useMethodWrappe
235235 CachedMethod [] methods = ReflectionCache .getCachedClass (theClass ).getMethods ();
236236 for (CachedMethod method : methods ) {
237237 if (method .isStatic () && method .isPublic () && method .getAnnotation (Deprecated .class ) == null ) {
238- if (disabling && disabledNames . contains (method .getName ())) continue ;
238+ if (disabling && isDisabled (method .getName (), method . getParameterTypes ())) continue ;
239239 CachedClass [] paramTypes = method .getParameterTypes ();
240240 if (paramTypes .length > 0 ) {
241241 List <MetaMethod > arr = map .computeIfAbsent (paramTypes [0 ], k -> new ArrayList <MetaMethod >(4 ));
@@ -540,4 +540,116 @@ public void onModule(final ExtensionModule module) {
540540 }
541541 }
542542 }
543+
544+ // DGM records use Class[]
545+ private boolean isDisabled (String methodName , Class [] parameters ) {
546+ for (DisabledMethodSpec spec : disabledSpecs ) {
547+ if (spec .matches (methodName , parameters )) return true ;
548+ }
549+ return false ;
550+ }
551+
552+ // Extension module methods use CachedClass[]
553+ private boolean isDisabled (String methodName , CachedClass [] parameters ) {
554+ for (DisabledMethodSpec spec : disabledSpecs ) {
555+ if (spec .matches (methodName , parameters )) return true ;
556+ }
557+ return false ;
558+ }
559+
560+ /**
561+ * Represents a parsed entry from the {@code groovy.extension.disable} system property.
562+ * <p>
563+ * Supported forms:
564+ * <ul>
565+ * <li>{@code methodName} — matches all overloads</li>
566+ * <li>{@code methodName(type)} — matches by receiver type (first parameter)</li>
567+ * <li>{@code methodName(type1,type2,...)} — matches the exact parameter signature</li>
568+ * </ul>
569+ */
570+ private static final class DisabledMethodSpec {
571+ private final String name ;
572+ private final String [] paramTypes ; // null means match all overloads
573+
574+ DisabledMethodSpec (String name , String [] paramTypes ) {
575+ this .name = name ;
576+ this .paramTypes = paramTypes ;
577+ }
578+
579+ boolean matches (String methodName , Class [] parameters ) {
580+ if (!name .equals (methodName )) return false ;
581+ if (paramTypes == null ) return true ;
582+ if (paramTypes .length != parameters .length ) return false ;
583+ for (int i = 0 ; i < paramTypes .length ; i ++) {
584+ if (!matchesType (paramTypes [i ], parameters [i ])) return false ;
585+ }
586+ return true ;
587+ }
588+
589+ boolean matches (String methodName , CachedClass [] parameters ) {
590+ if (!name .equals (methodName )) return false ;
591+ if (paramTypes == null ) return true ;
592+ if (paramTypes .length != parameters .length ) return false ;
593+ for (int i = 0 ; i < paramTypes .length ; i ++) {
594+ if (!matchesType (paramTypes [i ], parameters [i ].getTheClass ())) return false ;
595+ }
596+ return true ;
597+ }
598+
599+ // Allows simple name ("Set"), fully qualified name ("java.util.Set"),
600+ // and array notation ("Object[]", "boolean[][]", etc.).
601+ // Uses Class.getCanonicalName() which produces human-readable names
602+ // like "java.lang.Object[]" instead of JVM names like "[Ljava.lang.Object;".
603+ private static boolean matchesType (String spec , Class <?> type ) {
604+ String canonical = type .getCanonicalName ();
605+ if (spec .equals (canonical )) return true ;
606+ // allow simple name to match: "Set" matches "java.util.Set",
607+ // "Object[]" matches "java.lang.Object[]"
608+ String simpleName = type .getSimpleName ();
609+ return spec .equals (simpleName );
610+ }
611+
612+ /**
613+ * Parses the comma-separated disable property value, respecting parentheses.
614+ * For example: {@code "asChecked,toSorted(Set,Class),collect"} produces three specs.
615+ */
616+ static List <DisabledMethodSpec > parse (String input ) {
617+ List <DisabledMethodSpec > specs = new ArrayList <>();
618+ for (String entry : splitRespectingParens (input )) {
619+ entry = entry .trim ();
620+ if (entry .isEmpty ()) continue ;
621+ int parenIdx = entry .indexOf ('(' );
622+ if (parenIdx < 0 ) {
623+ specs .add (new DisabledMethodSpec (entry , null ));
624+ } else {
625+ String name = entry .substring (0 , parenIdx );
626+ String paramStr = entry .substring (parenIdx + 1 , entry .length () - 1 );
627+ if (paramStr .isEmpty ()) {
628+ specs .add (new DisabledMethodSpec (name , new String [0 ]));
629+ } else {
630+ String [] params = paramStr .split ("," );
631+ for (int i = 0 ; i < params .length ; i ++) params [i ] = params [i ].trim ();
632+ specs .add (new DisabledMethodSpec (name , params ));
633+ }
634+ }
635+ }
636+ return specs ;
637+ }
638+
639+ private static List <String > splitRespectingParens (String input ) {
640+ List <String > result = new ArrayList <>();
641+ int depth = 0 , start = 0 ;
642+ for (int i = 0 ; i < input .length (); i ++) {
643+ char c = input .charAt (i );
644+ if (c == '(' ) depth ++;
645+ else if (c == ')' ) depth --;
646+ else if (c == ',' && depth == 0 ) {
647+ result .add (input .substring (start , i ));
648+ start = i + 1 ;
649+ }
650+ }
651+ result .add (input .substring (start ));
652+ return result ;
653+ }
654+ }
543655}
0 commit comments