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 2022/03/22 15:57:21 UTC

[groovy] branch master updated: minor 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 bf681d1  minor refactor
bf681d1 is described below

commit bf681d1655a6a8154ba69547ce1a8406f5d2a711
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Mar 22 10:51:17 2022 -0500

    minor refactor
---
 .../org/codehaus/groovy/classgen/Verifier.java     | 205 ++++++++++-----------
 1 file changed, 93 insertions(+), 112 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/Verifier.java b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
index 86e7641..271a20e 100644
--- a/src/main/java/org/codehaus/groovy/classgen/Verifier.java
+++ b/src/main/java/org/codehaus/groovy/classgen/Verifier.java
@@ -77,7 +77,6 @@ import org.objectweb.asm.Opcodes;
 import java.beans.Transient;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -94,6 +93,7 @@ import static java.lang.reflect.Modifier.isPrivate;
 import static java.lang.reflect.Modifier.isPublic;
 import static java.lang.reflect.Modifier.isStatic;
 import static java.util.stream.Collectors.joining;
+import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.hasAnnotation;
 import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
 import static org.apache.groovy.ast.tools.ConstructorNodeUtils.getFirstIfSpecialConstructorCall;
 import static org.apache.groovy.ast.tools.ExpressionUtils.transformInlineConstants;
@@ -111,6 +111,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callThisX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ctorX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.getInterfacesAndSuperInterfaces;
@@ -152,22 +153,18 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
     public static final String STATIC_METACLASS_BOOL = "__$stMC";
     public static final String INITIAL_EXPRESSION = "INITIAL_EXPRESSION";
     public static final String DEFAULT_PARAMETER_GENERATED = "DEFAULT_PARAMETER_GENERATED";
-    private static final Parameter[] SET_METACLASS_PARAMS = {new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
 
     private static final Class<?> GENERATED_ANNOTATION = Generated.class;
-    private static final Class<?> INTERNAL_ANNOTATION = Internal.class;
+    private static final Class<?> INTERNAL_ANNOTATION  = Internal.class;
     private static final Class<?> TRANSIENT_ANNOTATION = Transient.class;
 
     // NOTE: timeStamp constants shouldn't belong to Verifier but kept here for binary compatibility
     public static final String __TIMESTAMP = "__timeStamp";
     public static final String __TIMESTAMP__ = "__timeStamp__239_neverHappen";
-    @Deprecated
-    public static final Class<Sealed> SEALED_CLASS = Sealed.class;
-    @Deprecated
-    public static final Class<NonSealed> NON_SEALED_CLASS = NonSealed.class;
 
     private static final Class<Sealed> SEALED_TYPE = Sealed.class;
     private static final Class<NonSealed> NON_SEALED_TYPE = NonSealed.class;
+    private static final Parameter[] SET_METACLASS_PARAMS = {new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
 
     private ClassNode classNode;
     private MethodNode methodNode;
@@ -184,43 +181,46 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         return methodNode;
     }
 
-    private static FieldNode setMetaClassFieldIfNotExists(final ClassNode node, FieldNode metaClassField) {
-        if (metaClassField != null) return metaClassField;
-        final String classInternalName = BytecodeHelper.getClassInternalName(node);
-        metaClassField =
-                node.addField("metaClass", ACC_PRIVATE | ACC_TRANSIENT | ACC_SYNTHETIC, ClassHelper.METACLASS_TYPE,
-                        bytecodeX(ClassHelper.METACLASS_TYPE, mv -> {
-                            mv.visitVarInsn(ALOAD, 0);
-                            mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
-                        })
-                );
-        metaClassField.setSynthetic(true);
-        return metaClassField;
-    }
-
     private static FieldNode getMetaClassField(final ClassNode node) {
-        FieldNode ret = node.getDeclaredField("metaClass");
-        if (ret != null) {
-            ClassNode mcFieldType = ret.getType();
+        FieldNode metaClassField = node.getDeclaredField("metaClass");
+        if (metaClassField != null) {
+            ClassNode mcFieldType = metaClassField.getType();
             if (!mcFieldType.equals(ClassHelper.METACLASS_TYPE)) {
                 throw new RuntimeParserException("The class " + node.getName() +
                         " cannot declare field 'metaClass' of type " + mcFieldType.getName() + " as it needs to be of " +
-                        "the type " + ClassHelper.METACLASS_TYPE.getName() + " for internal groovy purposes", ret);
+                        "the type " + ClassHelper.METACLASS_TYPE.getName() + " for internal groovy purposes", metaClassField);
             }
-            return ret;
+            return metaClassField;
         }
         ClassNode current = node;
         while (!isObjectType(current)) {
             current = current.getSuperClass();
             if (current == null) break;
-            ret = current.getDeclaredField("metaClass");
-            if (ret == null) continue;
-            if (isPrivate(ret.getModifiers())) continue;
-            return ret;
+            metaClassField = current.getDeclaredField("metaClass");
+            if (metaClassField == null) continue;
+            if (isPrivate(metaClassField.getModifiers())) continue;
+            return metaClassField;
         }
         return null;
     }
 
+    private static FieldNode setMetaClassFieldIfNotExists(final ClassNode node, FieldNode metaClassField) {
+        if (metaClassField == null) {
+            String classInternalName = BytecodeHelper.getClassInternalName(node);
+            metaClassField =
+                    node.addField("metaClass", ACC_PRIVATE | ACC_SYNTHETIC | ACC_TRANSIENT, ClassHelper.METACLASS_TYPE,
+                            bytecodeX(ClassHelper.METACLASS_TYPE, mv -> {
+                                mv.visitVarInsn(ALOAD, 0);
+                                mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+                            })
+                    );
+            metaClassField.setSynthetic(true);
+        }
+        return metaClassField;
+    }
+
+    //--------------------------------------------------------------------------
+
     @Override
     public void visitClass(final ClassNode node) {
         this.classNode = node;
@@ -234,15 +234,13 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
 
         checkForDuplicateInterfaces(node);
 
-        if (classNode.isInterface()
-                || Traits.isTrait(node)) { // maybe possible to have this true in joint compilation mode
-            //interfaces have no constructors, but this code expects one,
-            //so create a dummy and don't add it to the class node
-            ConstructorNode dummy = new ConstructorNode(0, null);
-            addInitialization(node, dummy);
+        if (classNode.isInterface() || Traits.isTrait(node)) {
+            // interfaces have no constructors but this expects one,
+            // so create a dummy but do not add it to the class node
+            addInitialization(node, new ConstructorNode(0, null));
             node.visitContents(this);
             if (classNode.getNodeMetaData(ClassNodeSkip.class) == null) {
-                classNode.setNodeMetaData(ClassNodeSkip.class, true);
+                classNode.setNodeMetaData(ClassNodeSkip.class, Boolean.TRUE);
             }
             return;
         }
@@ -250,18 +248,15 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         addDefaultParameterMethods(node);
         addDefaultParameterConstructors(node);
 
-        final String classInternalName = BytecodeHelper.getClassInternalName(node);
-        boolean skipGroovify = !node.getAnnotations(ClassHelper.make(POJO.class)).isEmpty()
-                    && !node.getAnnotations(ClassHelper.make(CompileStatic.class)).isEmpty();
+        boolean skipGroovify = hasAnnotation(node, ClassHelper.make(POJO.class))
+                    && hasAnnotation(node, ClassHelper.make(CompileStatic.class));
         if (!skipGroovify) {
-            addStaticMetaClassField(node, classInternalName);
+            String classInternalName = BytecodeHelper.getClassInternalName(node);
 
-            boolean knownSpecialCase =
-                    node.isDerivedFrom(ClassHelper.GSTRING_TYPE)
-                            || node.isDerivedFrom(ClassHelper.GROOVY_OBJECT_SUPPORT_TYPE);
-
-            addFastPathHelperFieldsAndHelperMethod(node, classInternalName, knownSpecialCase);
-            if (!knownSpecialCase) addGroovyObjectInterfaceAndMethods(node, classInternalName);
+            addStaticMetaClassField(node, classInternalName);
+            addFastPathHelperFieldsAndHelperMethod(node, classInternalName);
+            if (!node.isDerivedFrom(ClassHelper.GROOVY_OBJECT_SUPPORT_TYPE))
+                addGroovyObjectInterfaceAndMethods(node, classInternalName);
 
             addGetLookupMethod(node);
         }
@@ -280,7 +275,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
 
     private static final String[] INVALID_COMPONENTS = {"clone", "finalize", "getClass", "hashCode", "notify", "notifyAll", "toString", "wait"};
 
-    private void detectInvalidRecordComponentNames(ClassNode node) {
+    private static void detectInvalidRecordComponentNames(final ClassNode node) {
         for (FieldNode fn : node.getFields()) {
             if (Arrays.binarySearch(INVALID_COMPONENTS, fn.getName()) >= 0) {
                 throw new RuntimeParserException("Illegal record component name '" + fn.getName() + "'", fn);
@@ -288,7 +283,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         }
     }
 
-    private void detectNonSealedClasses(ClassNode node) {
+    private static void detectNonSealedClasses(final ClassNode node) {
         if (isFinal(node.getModifiers())) return;
         if (Boolean.TRUE.equals(node.getNodeMetaData(SEALED_TYPE))) return;
         if (Boolean.TRUE.equals(node.getNodeMetaData(NON_SEALED_TYPE))) return;
@@ -306,7 +301,6 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         }
     }
 
-
     private void checkFinalVariables(final ClassNode node) {
         GroovyClassVisitor visitor = new FinalVariableAnalyzer(null, getFinalVariablesCallback());
         visitor.visitClass(node);
@@ -420,8 +414,8 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         return null;
     }
 
-    private static void addFastPathHelperFieldsAndHelperMethod(final ClassNode node, final String classInternalName, final boolean knownSpecialCase) {
-        if (node.getNodeMetaData(ClassNodeSkip.class) != null) return;
+    private static void addFastPathHelperFieldsAndHelperMethod(final ClassNode node, final String classInternalName) {
+        if (Boolean.TRUE.equals(node.getNodeMetaData(ClassNodeSkip.class))) return;
         FieldNode stMCB = checkFieldDoesNotExist(node, STATIC_METACLASS_BOOL);
         if (stMCB == null) {
             stMCB = node.addField(
@@ -441,11 +435,10 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         node.addConstructor(constructor);
     }
 
-    private void addGetLookupMethod(final ClassNode node) {
+    private static void addGetLookupMethod(final ClassNode node) {
         int modifiers = ACC_PUBLIC;
-        boolean nonStaticInnerClass = null != node.getOuterClass() && !Modifier.isStatic(node.getModifiers());
-        if (!nonStaticInnerClass) {
-            // static method cannot be declared in non-static inner class util Java 16
+        if (isStatic(node.getModifiers()) || node.getOuterClass() == null) {
+            // static method cannot be declared in non-static inner class until Java 16
             modifiers |= ACC_STATIC;
         }
 
@@ -528,51 +521,47 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
 
         boolean shouldAnnotate = classNode.getModule().getContext() != null;
         AnnotationNode generatedAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(GENERATED_ANNOTATION)) : null;
-        AnnotationNode internalAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(INTERNAL_ANNOTATION)) : null;
+        AnnotationNode internalAnnotation  = shouldAnnotate ? new AnnotationNode(ClassHelper.make(INTERNAL_ANNOTATION))  : null;
         AnnotationNode transientAnnotation = shouldAnnotate ? new AnnotationNode(ClassHelper.make(TRANSIENT_ANNOTATION)) : null;
 
         if (!node.hasMethod("getMetaClass", Parameter.EMPTY_ARRAY)) {
             metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
-            MethodNode methodNode = addMethod(node, !shouldAnnotate,
-                    "getMetaClass",
-                    ACC_PUBLIC,
-                    ClassHelper.METACLASS_TYPE,
-                    Parameter.EMPTY_ARRAY,
-                    ClassNode.EMPTY_ARRAY,
-                    new BytecodeSequence(new BytecodeInstruction() {
-                        @Override
-                        public void visit(final MethodVisitor mv) {
-                            Label nullLabel = new Label();
-                            /*
-                             *  the code is:
-                             *  if (this.metaClass==null) {
-                             *      this.metaClass = this.$getStaticMetaClass()
-                             *      return this.metaClass
-                             *  } else {
-                             *      return this.metaClass
-                             *  }
-                             *  with the optimization that the result of the
-                             *  first this.metaClass is duped on the operand
-                             *  stack and reused for the return in the else part
-                             */
-                            mv.visitVarInsn(ALOAD, 0);
-                            mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
-                            mv.visitInsn(DUP);
-                            mv.visitJumpInsn(IFNULL, nullLabel);
-                            mv.visitInsn(ARETURN);
-
-                            mv.visitLabel(nullLabel);
-                            mv.visitInsn(POP);
-                            mv.visitVarInsn(ALOAD, 0);
-                            mv.visitInsn(DUP);
-                            mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
-                            mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
-                            mv.visitVarInsn(ALOAD, 0);
-                            mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
-                            mv.visitInsn(ARETURN);
-                        }
-                    })
-            );
+            Statement getMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {
+                @Override
+                public void visit(final MethodVisitor mv) {
+                    Label nullLabel = new Label();
+                    /*
+                     *  the code is:
+                     *  if (this.metaClass==null) {
+                     *      this.metaClass = this.$getStaticMetaClass()
+                     *      return this.metaClass
+                     *  } else {
+                     *      return this.metaClass
+                     *  }
+                     *  with the optimization that the result of the
+                     *  first this.metaClass is duped on the operand
+                     *  stack and reused for the return in the else part
+                     */
+                    mv.visitVarInsn(ALOAD, 0);
+                    mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
+                    mv.visitInsn(DUP);
+                    mv.visitJumpInsn(IFNULL, nullLabel);
+                    mv.visitInsn(ARETURN);
+
+                    mv.visitLabel(nullLabel);
+                    mv.visitInsn(POP);
+                    mv.visitVarInsn(ALOAD, 0);
+                    mv.visitInsn(DUP);
+                    mv.visitMethodInsn(INVOKEVIRTUAL, classInternalName, "$getStaticMetaClass", "()Lgroovy/lang/MetaClass;", false);
+                    mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
+                    mv.visitVarInsn(ALOAD, 0);
+                    mv.visitFieldInsn(GETFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
+                    mv.visitInsn(ARETURN);
+                }
+            });
+
+            MethodNode methodNode = addMethod(node, !shouldAnnotate, "getMetaClass", ACC_PUBLIC,
+                    ClassHelper.METACLASS_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getMetaClassCode);
             if (shouldAnnotate) {
                 methodNode.addAnnotation(generatedAnnotation);
                 methodNode.addAnnotation(internalAnnotation);
@@ -580,14 +569,11 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
             }
         }
 
-        Parameter[] parameters = new Parameter[]{new Parameter(ClassHelper.METACLASS_TYPE, "mc")};
-        if (!node.hasMethod("setMetaClass", parameters)) {
+        if (!node.hasMethod("setMetaClass", SET_METACLASS_PARAMS)) {
             metaClassField = setMetaClassFieldIfNotExists(node, metaClassField);
             Statement setMetaClassCode;
             if (isFinal(metaClassField.getModifiers())) {
-                ConstantExpression text = new ConstantExpression("cannot set read-only meta class");
-                ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
-                setMetaClassCode = new ExpressionStatement(cce);
+                setMetaClassCode = stmt(ctorX(ClassHelper.make(IllegalArgumentException.class), constX("cannot set read-only meta class")));
             } else {
                 setMetaClassCode = new BytecodeSequence(new BytecodeInstruction() {
                     @Override
@@ -598,19 +584,14 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
                          */
                         mv.visitVarInsn(ALOAD, 0);
                         mv.visitVarInsn(ALOAD, 1);
-                        mv.visitFieldInsn(PUTFIELD, classInternalName,
-                                "metaClass", "Lgroovy/lang/MetaClass;");
+                        mv.visitFieldInsn(PUTFIELD, classInternalName, "metaClass", "Lgroovy/lang/MetaClass;");
                         mv.visitInsn(RETURN);
                     }
                 });
             }
 
-            MethodNode methodNode = addMethod(node, !shouldAnnotate,
-                    "setMetaClass",
-                    ACC_PUBLIC, ClassHelper.VOID_TYPE,
-                    SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY,
-                    setMetaClassCode
-            );
+            MethodNode methodNode = addMethod(node, !shouldAnnotate, "setMetaClass", ACC_PUBLIC,
+                    ClassHelper.VOID_TYPE, SET_METACLASS_PARAMS, ClassNode.EMPTY_ARRAY, setMetaClassCode);
             if (shouldAnnotate) {
                 methodNode.addAnnotation(generatedAnnotation);
                 methodNode.addAnnotation(internalAnnotation);
@@ -784,7 +765,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         // no method found, we need to replace
         if (m == null) return true;
         // method is in current class, nothing to be done
-        if (m.getDeclaringClass() == this.getClassNode()) return false;
+        if (m.getDeclaringClass() == getClassNode()) return false;
         // do not overwrite final
         if (isFinal(m.getModifiers())) return false;
         return true;
@@ -862,7 +843,7 @@ public class Verifier implements GroovyClassVisitor, Opcodes {
         visitMethod(getter);
     }
 
-    private void copyMethodAnnotations(PropertyNode node, MethodNode accessor) {
+    private static void copyMethodAnnotations(final PropertyNode node, final MethodNode accessor) {
         for (AnnotationNode annotationNode : node.getAnnotations()) {
             if (annotationNode.isTargetAllowed(METHOD_TARGET)) {
                 accessor.addAnnotation(annotationNode);