You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2020/10/25 19:55:52 UTC
[groovy] 02/02: remove recursion from ClassNodeUtils#getField and
reuse in ASM classgen
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 <er...@thomsonreuters.com>
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) {