18
18
*/
19
19
package org .codehaus .groovy .transform .stc ;
20
20
21
+ import groovy .lang .GroovyClassLoader ;
21
22
import org .apache .groovy .util .Maps ;
22
23
import org .codehaus .groovy .GroovyBugError ;
23
24
import org .codehaus .groovy .ast .ClassNode ;
110
111
import static org .codehaus .groovy .ast .ClassHelper .short_TYPE ;
111
112
import static org .codehaus .groovy .ast .ClassHelper .void_WRAPPER_TYPE ;
112
113
import static org .codehaus .groovy .runtime .DefaultGroovyMethods .asBoolean ;
114
+ import static org .codehaus .groovy .runtime .DefaultGroovyMethodsSupport .closeQuietly ;
113
115
import static org .codehaus .groovy .syntax .Types .BITWISE_AND ;
114
116
import static org .codehaus .groovy .syntax .Types .BITWISE_AND_EQUAL ;
115
117
import static org .codehaus .groovy .syntax .Types .BITWISE_OR ;
@@ -2203,41 +2205,55 @@ public static boolean missesGenericsTypes(ClassNode cn) {
2203
2205
}
2204
2206
2205
2207
/**
2206
- * A helper method that can be used to evaluate expressions as found in annotation
2207
- * parameters. For example, it will evaluate a constant, be it referenced directly as
2208
- * an integer or as a reference to a field.
2208
+ * Evaluates expressions as found in annotation parameters. For example, it
2209
+ * will evaluate a constant, be it referenced directly as an integer or as a
2210
+ * reference to a field.
2209
2211
* <p>
2210
- * If this method throws an exception, then the expression cannot be evaluated on its own.
2212
+ * If the expression cannot be evaluated on its own, an exception is thrown .
2211
2213
*
2212
2214
* @param expr the expression to be evaluated
2213
2215
* @param config the compiler configuration
2214
2216
* @return the result of the expression
2217
+ * @throws GroovyBugError
2215
2218
*/
2216
2219
public static Object evaluateExpression (final Expression expr , final CompilerConfiguration config ) {
2217
- // GRECLIPSE add
2220
+ return evaluateExpression (expr , config , null );
2221
+ }
2222
+
2223
+ /**
2224
+ * Evaluates expressions as found in annotation parameters. For example, it
2225
+ * will evaluate a constant, be it referenced directly as an integer or as a
2226
+ * reference to a field.
2227
+ * <p>
2228
+ * If the expression cannot be evaluated on its own, an exception is thrown.
2229
+ *
2230
+ * @param expr the expression to be evaluated
2231
+ * @param config the compiler configuration
2232
+ * @param loader the compiler class loader
2233
+ * @return the result of the expression
2234
+ * @throws GroovyBugError
2235
+ */
2236
+ public static Object evaluateExpression (final Expression expr , final CompilerConfiguration config , /*@Nullable*/ final GroovyClassLoader loader ) {
2218
2237
Expression ce = expr instanceof CastExpression ? ((CastExpression ) expr ).getExpression () : expr ;
2219
2238
if (ce instanceof ConstantExpression ) {
2220
- if (expr .getType ().equals (ce .getType ()))
2221
- return ((ConstantExpression ) ce ).getValue ();
2239
+ if (expr .getType ().equals (getWrapper ( ce .getType ())) || (( ConstantExpression ) ce ). isNullExpression ( ))
2240
+ return ((ConstantExpression ) ce ).getValue (); // boolean, number, string, or null
2222
2241
} else if (ce instanceof ListExpression ) {
2223
2242
if (expr .getType ().isArray () && expr .getType ().getComponentType ().equals (STRING_TYPE ))
2224
- return ((ListExpression ) ce ).getExpressions ().stream ().map (e -> evaluateExpression (e , config )).toArray (String []::new );
2243
+ return ((ListExpression ) ce ).getExpressions ().stream ().map (e -> evaluateExpression (e , config , loader )).toArray (String []::new );
2225
2244
}
2226
- // GRECLIPSE end
2245
+
2227
2246
String className = "Expression$" +UUID .randomUUID ().toString ().replace ('-' , '$' );
2228
2247
ClassNode classNode = new ClassNode (className , Opcodes .ACC_PUBLIC , OBJECT_TYPE );
2229
2248
addGeneratedMethod (classNode , "eval" , Opcodes .ACC_PUBLIC | Opcodes .ACC_STATIC , OBJECT_TYPE , Parameter .EMPTY_ARRAY , ClassNode .EMPTY_ARRAY , new ReturnStatement (expr ));
2230
2249
2231
- CompilerConfiguration copyConf = new CompilerConfiguration (config );
2232
- // disable preview features so class can be executed by this JVM
2233
- copyConf .setPreviewFeatures (false );
2234
- copyConf .setScriptBaseClass (null );
2235
- copyConf .setTargetBytecode (CompilerConfiguration .DEFAULT .getTargetBytecode ());
2236
- /* GRECLIPSE edit -- supply the GroovyClassLoader
2237
- CompilationUnit cu = new CompilationUnit(copyConf);
2238
- */
2239
- CompilationUnit cu = new CompilationUnit (copyConf , null , new groovy .lang .GroovyClassLoader (classNode .getClass ().getClassLoader (), copyConf ));
2240
- // GRECLIPSE end
2250
+ // adjust configuration so class can be executed by this JVM
2251
+ CompilerConfiguration cc = new CompilerConfiguration (config );
2252
+ cc .setPreviewFeatures (false );
2253
+ cc .setScriptBaseClass (null );
2254
+ cc .setTargetBytecode (CompilerConfiguration .DEFAULT .getTargetBytecode ());
2255
+
2256
+ CompilationUnit cu = new CompilationUnit (cc , null , loader );
2241
2257
try {
2242
2258
cu .addClassNode (classNode );
2243
2259
cu .compile (Phases .CLASS_GENERATION );
@@ -2248,7 +2264,8 @@ public static Object evaluateExpression(final Expression expr, final CompilerCon
2248
2264
} catch (ReflectiveOperationException e ) {
2249
2265
throw new GroovyBugError (e );
2250
2266
} finally {
2251
- org .codehaus .groovy .runtime .DefaultGroovyMethodsSupport .closeQuietly (cu .getClassLoader ());
2267
+ if (loader == null )
2268
+ closeQuietly (cu .getClassLoader ());
2252
2269
}
2253
2270
}
2254
2271
0 commit comments