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 2021/06/01 15:31:22 UTC

[groovy] branch master updated: refactor

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


The following commit(s) were added to refs/heads/master by this push:
     new 61df54b  refactor
61df54b is described below

commit 61df54b88bcadf500ac73c5d4f095d4d078dc12e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Jun 1 10:31:11 2021 -0500

    refactor
---
 .../groovy/ast/decompiled/AsmDecompiler.java       | 165 +++++++++++----------
 .../ast/decompiled/MemberSignatureParser.java      | 104 ++++++-------
 2 files changed, 138 insertions(+), 131 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java b/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java
index bee97c0..00efcf5 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/AsmDecompiler.java
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.ast.decompiled;
 
 import groovy.lang.GroovyRuntimeException;
-import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.util.URLStreams;
 import org.objectweb.asm.AnnotationVisitor;
 import org.objectweb.asm.ClassReader;
@@ -41,20 +40,21 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import static org.codehaus.groovy.control.CompilerConfiguration.ASM_API_VERSION;
+import static org.codehaus.groovy.control.ResolveVisitor.EMPTY_STRING_ARRAY;
+
 /**
  * A utility class responsible for decompiling JVM class files and producing {@link ClassStub} objects reflecting their structure.
  */
 public abstract class AsmDecompiler {
 
-    private static class StubCache {
-        /**
-         * Caches stubs per URI. This cache is useful when performing multiple compilations in the same JVM/class loader and in tests.
-         *
-         * It's synchronized "just in case". Occasional misses are expected if several threads attempt to load the same class,
-         * but this shouldn't result in serious memory issues.
-         */
-        static final Map<URI, SoftReference<ClassStub>> map = new ConcurrentHashMap<URI, SoftReference<ClassStub>>();         // According to http://michaelscharf.blogspot.jp/2006/11/javaneturlequals-and-hashcode-make.html, use java.net.URI instead.
-    }
+    /**
+     * Caches stubs per URI. This cache is useful when performing multiple compilations in the same JVM/class loader and in tests.
+     *
+     * It's synchronized "just in case". Occasional misses are expected if several threads attempt to load the same class,
+     * but this shouldn't result in serious memory issues.
+     */
+    private static final Map<URI, SoftReference<ClassStub>> stubCache = new ConcurrentHashMap<>(); // According to http://michaelscharf.blogspot.jp/2006/11/javaneturlequals-and-hashcode-make.html, use java.net.URI instead.
 
     /**
      * Loads the URL contents and parses them with ASM, producing a {@link ClassStub} object representing the structure of
@@ -64,7 +64,7 @@ public abstract class AsmDecompiler {
      * @return the class stub
      * @throws IOException if reading from this URL is impossible
      */
-    public static ClassStub parseClass(URL url) throws IOException {
+    public static ClassStub parseClass(final URL url) throws IOException {
         URI uri;
         try {
             uri = url.toURI();
@@ -72,35 +72,51 @@ public abstract class AsmDecompiler {
             throw new GroovyRuntimeException(e);
         }
 
-        SoftReference<ClassStub> ref = StubCache.map.get(uri);
-        ClassStub stub = ref == null ? null : ref.get();
+        SoftReference<ClassStub> ref = stubCache.get(uri);
+        ClassStub stub = (ref != null ? ref.get() : null);
         if (stub == null) {
             DecompilingVisitor visitor = new DecompilingVisitor();
 
             try (InputStream stream = new BufferedInputStream(URLStreams.openUncachedStream(url))) {
                 new ClassReader(stream).accept(visitor, ClassReader.SKIP_FRAMES);
             }
+
             stub = visitor.result;
-            StubCache.map.put(uri, new SoftReference<ClassStub>(stub));
+            stubCache.put(uri, new SoftReference<>(stub));
         }
         return stub;
     }
 
+    private static AnnotationReader readAnnotationMembers(final AnnotationStub stub) {
+        return new AnnotationReader() {
+            @Override
+            void visitAttribute(final String name, final Object value) {
+                stub.members.put(name, value);
+            }
+        };
+    }
+
+    static String fromInternalName(final String name) {
+        return name.replace('/', '.');
+    }
+
+    //--------------------------------------------------------------------------
+
     private static class DecompilingVisitor extends ClassVisitor {
-        private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
         private ClassStub result;
 
         public DecompilingVisitor() {
-            super(CompilerConfiguration.ASM_API_VERSION);
+            super(ASM_API_VERSION);
         }
 
         @Override
-        public void visit(int version, int access, String name, String signature, String superName, String[] interfaceNames) {
+        public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaceNames) {
             result = new ClassStub(fromInternalName(name), access, signature, superName, interfaceNames);
         }
 
         @Override
-        public void visitInnerClass(String name, String outerName, String innerName, int access) {
+        public void visitInnerClass(final String name, final String outerName, final String innerName, final int access) {
             /*
              * Class files generated for inner classes have an INNERCLASS
              * reference to self. The top level class access modifiers for
@@ -126,105 +142,94 @@ public abstract class AsmDecompiler {
         }
 
         @Override
-        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
-            if (!"<clinit>".equals(name)) {
-                final MethodStub stub = new MethodStub(name, access, desc, signature, exceptions != null ? exceptions : EMPTY_STRING_ARRAY);
-                if (result.methods == null) result.methods = new ArrayList<MethodStub>(1);
-                result.methods.add(stub);
-                return new MethodVisitor(api) {
-                    @Override
-                    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
-                        return readAnnotationMembers(stub.addAnnotation(desc));
-                    }
-
-                    @Override
-                    public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) {
-                        if (stub.parameterAnnotations == null) stub.parameterAnnotations = new HashMap<Integer, List<AnnotationStub>>(1);
-                        List<AnnotationStub> list = stub.parameterAnnotations.computeIfAbsent(parameter, k -> new ArrayList<AnnotationStub>());
-                        AnnotationStub annotationStub = new AnnotationStub(desc);
-                        list.add(annotationStub);
-                        return readAnnotationMembers(annotationStub);
-                    }
-
-                    @Override
-                    public AnnotationVisitor visitAnnotationDefault() {
-                        return new AnnotationReader() {
-                            @Override
-                            void visitAttribute(String name, Object value) {
-                                stub.annotationDefault = value;
-                            }
-                        };
-                    }
-
-                    @Override
-                    public void visitParameter(String name, int access) {
-                        if (stub.parameterNames == null) stub.parameterNames = new ArrayList<String>();
-                        stub.parameterNames.add(name);
-                    }
-                };
-            }
-            return null;
+        public MethodVisitor visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
+            if ("<clinit>".equals(name)) return null;
+
+            MethodStub stub = new MethodStub(name, access, desc, signature, exceptions != null ? exceptions : EMPTY_STRING_ARRAY);
+            if (result.methods == null) result.methods = new ArrayList<>(1);
+            result.methods.add(stub);
+            return new MethodVisitor(api) {
+                @Override
+                public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
+                    return readAnnotationMembers(stub.addAnnotation(desc));
+                }
+
+                @Override
+                public AnnotationVisitor visitParameterAnnotation(final int parameter, final String desc, final boolean visible) {
+                    if (stub.parameterAnnotations == null) stub.parameterAnnotations = new HashMap<>(1);
+                    List<AnnotationStub> list = stub.parameterAnnotations.computeIfAbsent(parameter, k -> new ArrayList<>());
+                    AnnotationStub annotationStub = new AnnotationStub(desc);
+                    list.add(annotationStub);
+                    return readAnnotationMembers(annotationStub);
+                }
+
+                @Override
+                public AnnotationVisitor visitAnnotationDefault() {
+                    return new AnnotationReader() {
+                        @Override
+                        void visitAttribute(final String name, final Object value) {
+                            stub.annotationDefault = value;
+                        }
+                    };
+                }
+
+                @Override
+                public void visitParameter(final String name, final int access) {
+                    if (stub.parameterNames == null) stub.parameterNames = new ArrayList<>();
+                    stub.parameterNames.add(name);
+                }
+            };
         }
 
         @Override
-        public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+        public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
             return readAnnotationMembers(result.addAnnotation(desc));
         }
 
         @Override
-        public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
-            final FieldStub stub = new FieldStub(name, access, desc, signature, value);
-            if (result.fields == null) result.fields = new ArrayList<FieldStub>(1);
+        public FieldVisitor visitField(final int access, final String name, final String desc, final String signature, final Object value) {
+            FieldStub stub = new FieldStub(name, access, desc, signature, value);
+            if (result.fields == null) result.fields = new ArrayList<>(1);
             result.fields.add(stub);
             return new FieldVisitor(api) {
                 @Override
-                public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+                public AnnotationVisitor visitAnnotation(final String desc, final boolean visible) {
                     return readAnnotationMembers(stub.addAnnotation(desc));
                 }
             };
         }
     }
 
-    private static AnnotationReader readAnnotationMembers(final AnnotationStub stub) {
-        return new AnnotationReader() {
-            @Override
-            void visitAttribute(String name, Object value) {
-                stub.members.put(name, value);
-            }
-        };
-    }
-
-    static String fromInternalName(String name) {
-        return name.replace('/', '.');
-    }
+    //--------------------------------------------------------------------------
 
     private abstract static class AnnotationReader extends AnnotationVisitor {
+
         public AnnotationReader() {
-            super(CompilerConfiguration.ASM_API_VERSION);
+            super(ASM_API_VERSION);
         }
 
         abstract void visitAttribute(String name, Object value);
 
         @Override
-        public void visit(String name, Object value) {
+        public void visit(final String name, final Object value) {
             visitAttribute(name, value instanceof Type ? new TypeWrapper(((Type) value).getDescriptor()) : value);
         }
 
         @Override
-        public void visitEnum(String name, String desc, String value) {
+        public void visitEnum(final String name, final String desc, final String value) {
             visitAttribute(name, new EnumConstantWrapper(desc, value));
         }
 
         @Override
-        public AnnotationVisitor visitAnnotation(String name, String desc) {
+        public AnnotationVisitor visitAnnotation(final String name, final String desc) {
             AnnotationStub stub = new AnnotationStub(desc);
             visitAttribute(name, stub);
             return readAnnotationMembers(stub);
         }
 
         @Override
-        public AnnotationVisitor visitArray(String name) {
-            final List<Object> list = new ArrayList<Object>();
+        public AnnotationVisitor visitArray(final String name) {
+            List<Object> list = new ArrayList<>();
             visitAttribute(name, list);
             return new AnnotationReader() {
                 @Override
@@ -233,7 +238,5 @@ public abstract class AsmDecompiler {
                 }
             };
         }
-
     }
 }
-
diff --git a/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java b/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
index dd73433..552547e 100644
--- a/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
+++ b/src/main/java/org/codehaus/groovy/ast/decompiled/MemberSignatureParser.java
@@ -34,73 +34,77 @@ import org.objectweb.asm.signature.SignatureVisitor;
 import java.util.List;
 import java.util.Map;
 
-import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
-
 /**
- * Utility methods for lazy class loading
+ * Utility methods for lazy class loading.
  */
 class MemberSignatureParser {
-    static MethodNode createMethodNode(final AsmReferenceResolver resolver, MethodStub method) {
-        GenericsType[] typeParameters = null;
 
-        Type[] argumentTypes = Type.getArgumentTypes(method.desc);
-        final ClassNode[] parameterTypes = new ClassNode[argumentTypes.length];
-        for (int i = 0; i < argumentTypes.length; i++) {
-            parameterTypes[i] = resolver.resolveType(argumentTypes[i]);
+    static FieldNode createFieldNode(final FieldStub field, final AsmReferenceResolver resolver, final DecompiledClassNode owner) {
+        ClassNode[] type = resolve(resolver, Type.getType(field.desc));
+        if (field.signature != null) {
+            new SignatureReader(field.signature).accept(new TypeSignatureParser(resolver) {
+                @Override
+                void finished(final ClassNode result) {
+                    type[0] = applyErasure(result, type[0]);
+                }
+            });
         }
+        return new FieldNode(field.fieldName, field.accessModifiers, type[0], owner, field.value != null ? new ConstantExpression(field.value) : null);
+    }
 
-        final ClassNode[] exceptions = new ClassNode[method.exceptions.length];
-        for (int i = 0; i < method.exceptions.length; i++) {
-            exceptions[i] = resolver.resolveClass(AsmDecompiler.fromInternalName(method.exceptions[i]));
-        }
+    static MethodNode createMethodNode(final AsmReferenceResolver resolver, final MethodStub method) {
+        GenericsType[] typeParameters = null;
+
+        ClassNode[] returnType = resolve(resolver, Type.getReturnType(method.desc));
 
-        final ClassNode[] returnType = {resolver.resolveType(Type.getReturnType(method.desc))};
+        ClassNode[] parameterTypes = resolve(resolver, Type.getArgumentTypes(method.desc));
+
+        ClassNode[] exceptionTypes = resolve(resolver, method.exceptions);
 
         if (method.signature != null) {
-            FormalParameterParser v = new FormalParameterParser(resolver) {
-                int paramIndex = 0;
+            FormalParameterParser parser = new FormalParameterParser(resolver) {
+                private int exceptionIndex, parameterIndex;
 
                 @Override
-                public SignatureVisitor visitParameterType() {
+                public SignatureVisitor visitReturnType() {
                     return new TypeSignatureParser(resolver) {
                         @Override
-                        void finished(ClassNode result) {
-                            parameterTypes[paramIndex] = applyErasure(result, parameterTypes[paramIndex]);
-                            paramIndex++;
+                        void finished(final ClassNode result) {
+                            returnType[0] = applyErasure(result, returnType[0]);
                         }
                     };
                 }
 
                 @Override
-                public SignatureVisitor visitReturnType() {
+                public SignatureVisitor visitParameterType() {
                     return new TypeSignatureParser(resolver) {
                         @Override
-                        void finished(ClassNode result) {
-                            returnType[0] = applyErasure(result, returnType[0]);
+                        void finished(final ClassNode result) {
+                            parameterTypes[parameterIndex] = applyErasure(result, parameterTypes[parameterIndex]);
+                            parameterIndex += 1;
                         }
                     };
                 }
 
-                int exceptionIndex = 0;
-
                 @Override
                 public SignatureVisitor visitExceptionType() {
                     return new TypeSignatureParser(resolver) {
                         @Override
-                        void finished(ClassNode result) {
-                            exceptions[exceptionIndex] = applyErasure(result, exceptions[exceptionIndex]);
-                            exceptionIndex++;
+                        void finished(final ClassNode result) {
+                            exceptionTypes[exceptionIndex] = applyErasure(result, exceptionTypes[exceptionIndex]);
+                            exceptionIndex += 1;
                         }
                     };
                 }
             };
-            new SignatureReader(method.signature).accept(v);
-            typeParameters = v.getTypeParameters();
+            new SignatureReader(method.signature).accept(parser);
+            typeParameters = parser.getTypeParameters();
         }
 
-        Parameter[] parameters = new Parameter[parameterTypes.length];
+        int nParameters = parameterTypes.length;
+        Parameter[] parameters = new Parameter[nParameters];
         List<String> parameterNames = method.parameterNames;
-        for (int i = 0; i < parameterTypes.length; i++) {
+        for (int i = 0; i < nParameters; i += 1) {
             String parameterName = "param" + i;
             if (parameterNames != null && i < parameterNames.size()) {
                 String decompiledName = parameterNames.get(i);
@@ -124,9 +128,9 @@ class MemberSignatureParser {
 
         MethodNode result;
         if ("<init>".equals(method.methodName)) {
-            result = new ConstructorNode(method.accessModifiers, parameters, exceptions, null);
+            result = new ConstructorNode(method.accessModifiers, parameters, exceptionTypes, null);
         } else {
-            result = new MethodNode(method.methodName, method.accessModifiers, returnType[0], parameters, exceptions, null);
+            result = new MethodNode(method.methodName, method.accessModifiers, returnType[0], parameters, exceptionTypes, null);
             Object annDefault = method.annotationDefault;
             if (annDefault != null) {
                 if (annDefault instanceof TypeWrapper) {
@@ -135,10 +139,9 @@ class MemberSignatureParser {
                 result.setCode(new ReturnStatement(new ConstantExpression(annDefault)));
                 result.setAnnotationDefault(true);
             } else {
-                // Seems wrong but otherwise some tests fail (e.g. TestingASTTransformsTest)
-                result.setCode(new ReturnStatement(nullX()));
+                // seems wrong but otherwise some tests fail (e.g. TestingASTTransformsTest)
+                result.setCode(new ReturnStatement(new ConstantExpression(null)));
             }
-
         }
         if (typeParameters != null && typeParameters.length > 0) {
             result.setGenericsTypes(typeParameters);
@@ -146,7 +149,7 @@ class MemberSignatureParser {
         return result;
     }
 
-    private static ClassNode applyErasure(ClassNode genericType, ClassNode erasure) {
+    private static ClassNode applyErasure(final ClassNode genericType, final ClassNode erasure) {
         if (genericType.isArray() && erasure.isArray() && genericType.getComponentType().isGenericsPlaceHolder()) {
             genericType.setRedirect(erasure);
             genericType.getComponentType().setRedirect(erasure.getComponentType());
@@ -156,18 +159,19 @@ class MemberSignatureParser {
         return genericType;
     }
 
-    static FieldNode createFieldNode(FieldStub field, AsmReferenceResolver resolver, DecompiledClassNode owner) {
-        final ClassNode[] type = {resolver.resolveType(Type.getType(field.desc))};
-        if (field.signature != null) {
-            new SignatureReader(field.signature).accept(new TypeSignatureParser(resolver) {
-                @Override
-                void finished(ClassNode result) {
-                    type[0] = applyErasure(result, type[0]);
-                }
-            });
+    private static ClassNode[] resolve(final AsmReferenceResolver resolver, final String[] names) {
+        int n = names.length; ClassNode[] nodes = new ClassNode[n];
+        for (int i = 0; i < n; i += 1) {
+            nodes[i] = resolver.resolveClass(AsmDecompiler.fromInternalName(names[i]));
         }
-        ConstantExpression value = field.value == null ? null : new ConstantExpression(field.value);
-        return new FieldNode(field.fieldName, field.accessModifiers, type[0], owner, value);
+        return nodes;
     }
-}
 
+    private static ClassNode[] resolve(final AsmReferenceResolver resolver, final Type... types) {
+        int n = types.length; ClassNode[] nodes = new ClassNode[n];
+        for (int i = 0; i < n; i += 1) {
+            nodes[i] = resolver.resolveType(types[i]);
+        }
+        return nodes;
+    }
+}