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/11/08 15:48:59 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-9541: STC: add `GroovyClassLoader` to `evaluateExpression` params

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 2d5e383a58 GROOVY-9541: STC: add `GroovyClassLoader` to `evaluateExpression` params
2d5e383a58 is described below

commit 2d5e383a586e193d1219136bd615a5a987ce0ee2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Nov 8 08:29:06 2022 -0600

    GROOVY-9541: STC: add `GroovyClassLoader` to `evaluateExpression` params
    
    3_0_X backport
---
 .../ASTTransformationCollectorCodeVisitor.java     |  4 +-
 .../transform/stc/StaticTypeCheckingSupport.java   | 53 +++++++++++++++++-----
 2 files changed, 44 insertions(+), 13 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
index 8638b7286e..d940f0a3db 100644
--- a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
@@ -183,7 +183,7 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
             if (annotation.getClassNode().getName().equals(AnnotationCollector.class.getName())) {
                 Expression mode = annotation.getMember("mode");
                 modes.put(index, Optional.ofNullable(mode)
-                    .map(exp -> evaluateExpression(exp, source.getConfiguration()))
+                    .map(exp -> evaluateExpression(exp, source.getConfiguration(), transformLoader))
                     .map(val -> (AnnotationCollectorMode) val)
                     .orElse(AnnotationCollectorMode.DUPLICATE)
                 );
@@ -191,7 +191,7 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
                 Expression processor = annotation.getMember("processor");
                 AnnotationCollectorTransform act = null;
                 if (processor != null) {
-                    String className = (String) evaluateExpression(processor, source.getConfiguration());
+                    String className = (String) evaluateExpression(processor, source.getConfiguration(), transformLoader);
                     Class<?> klass = loadTransformClass(className, alias);
                     if (klass != null) {
                         try {
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 4420f87aec..9d6f028ba9 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -18,6 +18,7 @@
  */
 package org.codehaus.groovy.transform.stc;
 
+import groovy.lang.GroovyClassLoader;
 import org.apache.groovy.util.Maps;
 import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.ClassNode;
@@ -30,6 +31,7 @@ import org.codehaus.groovy.ast.Variable;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.ArrayExpression;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.CastExpression;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
@@ -107,6 +109,7 @@ import static org.codehaus.groovy.ast.ClassHelper.makeWithoutCaching;
 import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport.closeQuietly;
 import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
 import static org.codehaus.groovy.syntax.Types.BITWISE_AND_EQUAL;
 import static org.codehaus.groovy.syntax.Types.BITWISE_OR;
@@ -2136,28 +2139,55 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     /**
-     * A helper method that can be used to evaluate expressions as found in annotation
-     * parameters. For example, it will evaluate a constant, be it referenced directly as
-     * an integer or as a reference to a field.
+     * Evaluates expressions as found in annotation parameters.  For example, it
+     * will evaluate a constant, be it referenced directly as an integer or as a
+     * reference to a field.
      * <p>
-     * If this method throws an exception, then the expression cannot be evaluated on its own.
+     * If the expression cannot be evaluated on its own, an exception is thrown.
      *
      * @param expr   the expression to be evaluated
      * @param config the compiler configuration
      * @return the result of the expression
+     * @throws GroovyBugError
      */
     public static Object evaluateExpression(final Expression expr, final CompilerConfiguration config) {
+        return evaluateExpression(expr, config, null);
+    }
+
+    /**
+     * Evaluates expressions as found in annotation parameters.  For example, it
+     * will evaluate a constant, be it referenced directly as an integer or as a
+     * reference to a field.
+     * <p>
+     * If the expression cannot be evaluated on its own, an exception is thrown.
+     *
+     * @param expr   the expression to be evaluated
+     * @param config the compiler configuration
+     * @param loader the compiler class loader
+     * @return the result of the expression
+     * @throws GroovyBugError
+     */
+    public static Object evaluateExpression(final Expression expr, final CompilerConfiguration config, /*@Nullable*/ final GroovyClassLoader loader) {
+        Expression ce = expr instanceof CastExpression ? ((CastExpression) expr).getExpression() : expr;
+        if (ce instanceof ConstantExpression) {
+            if (expr.getType().equals(ce.getType()))
+                return ((ConstantExpression) ce).getValue();
+        } else if (ce instanceof ListExpression) {
+            if (expr.getType().isArray() && expr.getType().getComponentType().equals(STRING_TYPE))
+                return ((ListExpression) ce).getExpressions().stream().map(e -> evaluateExpression(e, config, loader)).toArray(String[]::new);
+        }
+
         String className = "Expression$"+UUID.randomUUID().toString().replace('-', '$');
         ClassNode classNode = new ClassNode(className, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
         addGeneratedMethod(classNode, "eval", Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC, OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(expr));
 
-        CompilerConfiguration copyConf = new CompilerConfiguration(config);
-        // disable preview features so class can be executed by this JVM
-        copyConf.setPreviewFeatures(false);
-        copyConf.setScriptBaseClass(null);
-        copyConf.setTargetBytecode(CompilerConfiguration.DEFAULT.getTargetBytecode());
+        // adjust configuration so class can be executed by this JVM
+        CompilerConfiguration cc = new CompilerConfiguration(config);
+        cc.setPreviewFeatures(false);
+        cc.setScriptBaseClass(null);
+        cc.setTargetBytecode(CompilerConfiguration.DEFAULT.getTargetBytecode());
 
-        CompilationUnit cu = new CompilationUnit(copyConf);
+        CompilationUnit cu = new CompilationUnit(cc, null, loader);
         try {
             cu.addClassNode(classNode);
             cu.compile(Phases.CLASS_GENERATION);
@@ -2168,7 +2198,8 @@ public abstract class StaticTypeCheckingSupport {
         } catch (ReflectiveOperationException e) {
             throw new GroovyBugError(e);
         } finally {
-            org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport.closeQuietly(cu.getClassLoader());
+            if (loader == null)
+                closeQuietly(cu.getClassLoader());
         }
     }