Copilot commented on code in PR #2467:
URL: https://github.com/apache/groovy/pull/2467#discussion_r3072638311


##########
src/main/java/org/codehaus/groovy/transform/DelegateASTTransformation.java:
##########
@@ -365,7 +365,7 @@ private static void addGetterIfNeeded(final 
DelegateDescription delegate, final
         }
 
         if (willHaveIsAccessor && !ownerWillHaveIsAccessor.get()
-                && !shouldSkipPropertyMethod(name, getterName, 
delegate.excludes, delegate.includes, allNames)) {
+                && !shouldSkipPropertyMethod(prop, getterName, 
delegate.excludes, delegate.includes, allNames)) {

Review Comment:
   The `willHaveIsAccessor` branch generates `isserName`, but the skip-check 
passes `getterName` into `shouldSkipPropertyMethod`. This means 
excludes/includes for the `isXxx` method name won't be honored. Pass 
`isserName` instead so filtering applies to the actual generated method.
   ```suggestion
                   && !shouldSkipPropertyMethod(prop, isserName, 
delegate.excludes, delegate.includes, allNames)) {
   ```



##########
src/main/java/groovy/lang/MetaClassImpl.java:
##########
@@ -2291,6 +2294,22 @@ private static boolean canAccessLegally(final MetaMethod 
method) {
             || ((CachedMethod) method).canAccessLegally(MetaClassImpl.class);
     }
 
+    private static boolean isMarkedInternal(final MetaBeanProperty mbp) {
+        CachedField field = mbp.getField();
+        if (field != null && 
field.getCachedField().isAnnotationPresent(Internal.class)) {
+            return true;
+        }
+        MetaMethod getter = mbp.getGetter();
+        if (getter instanceof CachedMethod cm && 
cm.getCachedMethod().isAnnotationPresent(Internal.class)) {
+            return true;
+        }
+        MetaMethod setter = mbp.getSetter();
+        if (setter instanceof CachedMethod cm && 
cm.getCachedMethod().isAnnotationPresent(Internal.class)) {

Review Comment:
   `isMarkedInternal` uses `field.getCachedField()` / `cm.getCachedMethod()` 
which both attempt to make members accessible. For methods you can avoid that 
by using `CachedMethod#getAnnotation(Internal.class)` (doesn't call 
`makeAccessible`); for fields consider a similar non-accessing annotation 
lookup to keep `getProperties()` cheap and side-effect free.
   ```suggestion
           if (field != null && field.getAnnotation(Internal.class) != null) {
               return true;
           }
           MetaMethod getter = mbp.getGetter();
           if (getter instanceof CachedMethod cm && 
cm.getAnnotation(Internal.class) != null) {
               return true;
           }
           MetaMethod setter = mbp.getSetter();
           if (setter instanceof CachedMethod cm && 
cm.getAnnotation(Internal.class) != null) {
   ```



##########
src/main/java/org/codehaus/groovy/transform/AbstractASTTransformation.java:
##########
@@ -276,6 +304,25 @@ public static boolean shouldSkip(String name, List<String> 
excludes, List<String
             (includes != null && !includes.isEmpty() && 
!includes.contains(name));
     }
 
+    /**
+     * Variant that checks both the name and {@link groovy.transform.Internal 
@Internal} annotation.
+     *
+     * @since 6.0.0
+     */
+    public static boolean shouldSkip(AnnotatedNode node, List<String> 
excludes, List<String> includes, boolean allNames) {
+        String name = nodeName(node);
+        return (excludes != null && excludes.contains(name)) ||
+            (!allNames && deemedInternal(node)) ||
+            (includes != null && !includes.isEmpty() && 
!includes.contains(name));
+    }
+
+    private static String nodeName(AnnotatedNode node) {
+        if (node instanceof FieldNode fn) return fn.getName();
+        if (node instanceof PropertyNode pn) return pn.getName();
+        if (node instanceof MethodNode mn) return mn.getName();
+        return "";

Review Comment:
   `nodeName` returns an empty string for `AnnotatedNode` types other than 
`FieldNode`/`PropertyNode`/`MethodNode`, which can silently change skip 
behavior (e.g., `includes`/`excludes` checks on ""). Since 
`shouldSkip*(AnnotatedNode, ...)` are public APIs, consider throwing an 
`IllegalArgumentException` for unsupported node types (or explicitly handling 
the additional node types you intend to support).
   ```suggestion
           throw new IllegalArgumentException("Unsupported AnnotatedNode type: 
" + (node == null ? "null" : node.getClass().getName()));
   ```



##########
src/main/java/groovy/lang/MetaClassImpl.java:
##########
@@ -2253,13 +2254,15 @@ public List<MetaProperty> getProperties() {
         // simply return the values of the metaproperty map as a List
         List<MetaProperty> ret = new ArrayList<>(propertyMap.size());
         for (MetaProperty mp : propertyMap.values()) {
-            if (mp instanceof CachedField) {
-                if (mp.isSynthetic()
+            if (mp instanceof CachedField cf) {
+                if (cf.isSynthetic()
+                        || 
cf.getCachedField().isAnnotationPresent(Internal.class)
                         // GROOVY-5169, GROOVY-9081, GROOVY-9103, 
GROOVY-10438, GROOVY-10555, et al.
-                        || (!permissivePropertyAccess && 
!checkAccessible(getClass(), ((CachedField) mp).getDeclaringClass(), 
mp.getModifiers(), false))) {
+                        || (!permissivePropertyAccess && 
!checkAccessible(getClass(), cf.getDeclaringClass(), cf.getModifiers(), 
false))) {

Review Comment:
   `cf.getCachedField().isAnnotationPresent(Internal.class)` forces 
`CachedField#getCachedField()` which calls 
`ReflectionUtils.makeAccessibleInPrivilegedAction(field)` (side-effect + 
overhead) even though we only need to read the annotation. Consider 
adding/using an annotation accessor on `CachedField` that does *not* call 
`makeAccessible`, and use that here to avoid unnecessary accessibility changes 
during property enumeration.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to