This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 6a2ca074983c2d3b765e46eb96c8127396ed7afe Author: Eric Milles <[email protected]> AuthorDate: Sun Oct 25 14:47:58 2020 -0500 remove recursion from ClassNodeUtils#getField and reuse in ASM classgen --- .../apache/groovy/ast/tools/ClassNodeUtils.java | 43 +++++++++++++--------- .../groovy/classgen/AsmClassGenerator.java | 16 +++----- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java b/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java index a18b23f..23edfd3 100644 --- a/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java +++ b/src/main/java/org/apache/groovy/ast/tools/ClassNodeUtils.java @@ -34,13 +34,17 @@ import org.codehaus.groovy.ast.stmt.Statement; import org.codehaus.groovy.transform.AbstractASTTransformation; import java.lang.reflect.Modifier; +import java.util.ArrayDeque; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Queue; import java.util.Set; +import java.util.function.Predicate; import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.isGenerated; import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated; @@ -388,27 +392,32 @@ public class ClassNodeUtils { } /** - * Return the (potentially inherited) field of the classnode. - * - * @param classNode the classnode - * @param fieldName the name of the field - * @return the field or null if not found + * Searches the class for a field that matches specified name. */ public static FieldNode getField(final ClassNode classNode, final String fieldName) { - ClassNode node = classNode; - Set<String> visited = new HashSet<>(); - while (node != null) { - FieldNode fn = node.getDeclaredField(fieldName); - if (fn != null) return fn; - ClassNode[] interfaces = node.getInterfaces(); - for (ClassNode iNode : interfaces) { - if (visited.contains(iNode.getName())) continue; - FieldNode ifn = getField(iNode, fieldName); - visited.add(iNode.getName()); - if (ifn != null) return ifn; + return getField(classNode, fieldName, fieldNode -> true); + } + + /** + * Searches the class for a field that matches specified name and test. + */ + public static FieldNode getField(final ClassNode classNode, final String fieldName, final Predicate<FieldNode> acceptability) { + Queue<ClassNode> todo = new ArrayDeque<>(Collections.singletonList(classNode)); + Set<ClassNode> done = new HashSet<>(); + ClassNode next; + + while ((next = todo.poll()) != null) { + if (done.add(next)) { + FieldNode fieldNode = next.getDeclaredField(fieldName); + if (fieldNode != null && acceptability.test(fieldNode)) + return fieldNode; + + Collections.addAll(todo, next.getInterfaces()); + ClassNode superType = next.getSuperClass(); + if (superType != null) todo.add(superType); } - node = node.getSuperClass(); } + return null; } } diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java index 43795f2..022d44b 100644 --- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java +++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java @@ -124,6 +124,7 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; +import static org.apache.groovy.ast.tools.ClassNodeUtils.getField; import static org.apache.groovy.ast.tools.ExpressionUtils.isThisOrSuper; import static org.codehaus.groovy.ast.tools.GeneralUtils.attrX; import static org.codehaus.groovy.ast.tools.GeneralUtils.callX; @@ -959,16 +960,11 @@ public class AsmClassGenerator extends ClassGenerator { return false; } - public static FieldNode getDeclaredFieldOfCurrentClassOrAccessibleFieldOfSuper(final ClassNode accessingNode, final ClassNode current, final String name, final boolean skipCurrent) { - if (!skipCurrent) { - FieldNode currentClassField = current.getDeclaredField(name); - if (isValidFieldNodeForByteCodeAccess(currentClassField, accessingNode)) return currentClassField; - } - for (ClassNode node = current.getSuperClass(); node != null; node = node.getSuperClass()) { - FieldNode fn = node.getDeclaredField(name); - if (isValidFieldNodeForByteCodeAccess(fn, accessingNode)) return fn; - } - return null; + public static FieldNode getDeclaredFieldOfCurrentClassOrAccessibleFieldOfSuper(final ClassNode accessingNode, final ClassNode current, final String fieldName, final boolean skipCurrent) { + return getField(current, fieldName, fieldNode -> + (!skipCurrent || !current.equals(fieldNode.getDeclaringClass())) + && isValidFieldNodeForByteCodeAccess(fieldNode, accessingNode) + ); } private void visitAttributeOrProperty(final PropertyExpression pexp, final MethodCallerMultiAdapter adapter) {
