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/08/29 19:31:21 UTC
[groovy] branch GROOVY_3_0_X updated: GROOVY-9871: class model: populate `AnnotationConstantExpression` values
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 2d150af049 GROOVY-9871: class model: populate `AnnotationConstantExpression` values
2d150af049 is described below
commit 2d150af0497e0e33f40b40b140c65cf1539c7956
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Jul 5 11:17:08 2022 -0500
GROOVY-9871: class model: populate `AnnotationConstantExpression` values
---
.../org/codehaus/groovy/vmplugin/v8/Java8.java | 363 +++++++++++----------
.../ast/{Groovy7826Bug.java => Groovy7826.java} | 28 +-
src/test/org/codehaus/groovy/ast/Groovy9871.groovy | 46 +++
3 files changed, 248 insertions(+), 189 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
index d88d108fe5..57a0829b17 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Java8.java
@@ -33,6 +33,7 @@ import org.codehaus.groovy.ast.GenericsType;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.PackageNode;
import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
@@ -81,11 +82,7 @@ public class Java8 implements VMPlugin {
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
private static final Permission ACCESS_PERMISSION = new ReflectPermission("suppressAccessChecks");
- public Java8() {
- super();
- }
-
- public static GenericsType configureTypeVariableDefinition(ClassNode base, ClassNode[] cBounds) {
+ public static GenericsType configureTypeVariableDefinition(final ClassNode base, final ClassNode[] cBounds) {
ClassNode redirect = base.redirect();
base.setRedirect(null);
GenericsType gt;
@@ -100,7 +97,7 @@ public class Java8 implements VMPlugin {
return gt;
}
- private static ClassNode configureClass(Class<?> c) {
+ private static ClassNode configureClass(final Class<?> c) {
if (c.isPrimitive()) {
return ClassHelper.make(c);
} else {
@@ -108,7 +105,7 @@ public class Java8 implements VMPlugin {
}
}
- public static ClassNode configureTypeVariableReference(String name) {
+ public static ClassNode configureTypeVariableReference(final String name) {
ClassNode cn = ClassHelper.makeWithoutCaching(name);
cn.setGenericsPlaceHolder(true);
ClassNode cn2 = ClassHelper.makeWithoutCaching(name);
@@ -119,121 +116,111 @@ public class Java8 implements VMPlugin {
return cn;
}
- private static void setRetentionPolicy(RetentionPolicy value, AnnotationNode node) {
+ private static void setRetentionPolicy(final RetentionPolicy value, final AnnotationNode node) {
switch (value) {
- case RUNTIME:
- node.setRuntimeRetention(true);
- break;
- case SOURCE:
- node.setSourceRetention(true);
- break;
- case CLASS:
- node.setClassRetention(true);
- break;
- default:
- throw new GroovyBugError("unsupported Retention " + value);
+ case RUNTIME:
+ node.setRuntimeRetention(true);
+ break;
+ case SOURCE:
+ node.setSourceRetention(true);
+ break;
+ case CLASS:
+ node.setClassRetention(true);
+ break;
+ default:
+ throw new GroovyBugError("unsupported Retention " + value);
}
}
- private static void setMethodDefaultValue(MethodNode mn, Method m) {
+ private static void setMethodDefaultValue(final MethodNode mn, final Method m) {
ConstantExpression cExp = new ConstantExpression(m.getDefaultValue());
mn.setCode(new ReturnStatement(cExp));
mn.setAnnotationDefault(true);
}
- private static Constructor<MethodHandles.Lookup> getLookupConstructor() {
- return LookupHolder.LOOKUP_Constructor;
- }
-
@Override
public Class<?>[] getPluginDefaultGroovyMethods() {
return new Class[]{PluginDefaultGroovyMethods.class};
}
+ @Override
+ public Class<?>[] getPluginStaticGroovyMethods() {
+ return EMPTY_CLASS_ARRAY;
+ }
+
@Override
public int getVersion() {
return 8;
}
- protected int getElementCode(ElementType value) {
+ protected int getElementCode(final ElementType value) {
switch (value) {
- case TYPE:
- return AnnotationNode.TYPE_TARGET;
- case CONSTRUCTOR:
- return AnnotationNode.CONSTRUCTOR_TARGET;
- case METHOD:
- return AnnotationNode.METHOD_TARGET;
- case FIELD:
- return AnnotationNode.FIELD_TARGET;
- case PARAMETER:
- return AnnotationNode.PARAMETER_TARGET;
- case LOCAL_VARIABLE:
- return AnnotationNode.LOCAL_VARIABLE_TARGET;
- case ANNOTATION_TYPE:
- return AnnotationNode.ANNOTATION_TARGET;
- case PACKAGE:
- return AnnotationNode.PACKAGE_TARGET;
- case TYPE_PARAMETER:
- return AnnotationNode.TYPE_PARAMETER_TARGET;
- case TYPE_USE:
- return AnnotationNode.TYPE_USE_TARGET;
- }
- if ("MODULE".equals(value.name())) {
+ case TYPE:
+ return AnnotationNode.TYPE_TARGET;
+ case CONSTRUCTOR:
+ return AnnotationNode.CONSTRUCTOR_TARGET;
+ case METHOD:
+ return AnnotationNode.METHOD_TARGET;
+ case FIELD:
+ return AnnotationNode.FIELD_TARGET;
+ case PARAMETER:
+ return AnnotationNode.PARAMETER_TARGET;
+ case LOCAL_VARIABLE:
+ return AnnotationNode.LOCAL_VARIABLE_TARGET;
+ case ANNOTATION_TYPE:
+ return AnnotationNode.ANNOTATION_TARGET;
+ case PACKAGE:
+ return AnnotationNode.PACKAGE_TARGET;
+ case TYPE_PARAMETER:
+ return AnnotationNode.TYPE_PARAMETER_TARGET;
+ case TYPE_USE:
+ return AnnotationNode.TYPE_USE_TARGET;
+ default:
+ // falls through
+ }
+ if ("MODULE".equals(value.name())) { // JDK 9+
return AnnotationNode.TYPE_TARGET;
} else {
throw new GroovyBugError("unsupported Target " + value);
}
}
- @Deprecated
- protected Parameter[] processParameters(CompileUnit compileUnit, Method m) {
- java.lang.reflect.Parameter[] parameters = m.getParameters();
- Type[] types = m.getGenericParameterTypes();
- Parameter[] params = Parameter.EMPTY_ARRAY;
- if (types.length > 0) {
- params = new Parameter[types.length];
- for (int i = 0; i < params.length; i++) {
- java.lang.reflect.Parameter p = parameters[i];
- String name = p.isNamePresent() ? p.getName() : "param" + i;
- params[i] = makeParameter(compileUnit, types[i], m.getParameterTypes()[i], m.getParameterAnnotations()[i], name);
- }
- }
- return params;
- }
-
- public void setAdditionalClassInformation(ClassNode cn) {
+ @Override
+ public void setAdditionalClassInformation(final ClassNode cn) {
setGenericsTypes(cn);
}
- private void setGenericsTypes(ClassNode cn) {
+ private void setGenericsTypes(final ClassNode cn) {
TypeVariable[] tvs = cn.getTypeClass().getTypeParameters();
GenericsType[] gts = configureTypeVariable(tvs);
cn.setGenericsTypes(gts);
}
- private GenericsType[] configureTypeVariable(TypeVariable[] tvs) {
- if (tvs.length == 0) return null;
- GenericsType[] gts = new GenericsType[tvs.length];
- for (int i = 0; i < tvs.length; i++) {
+ private GenericsType[] configureTypeVariable(final TypeVariable[] tvs) {
+ final int n = tvs.length;
+ if (n == 0) return null;
+ GenericsType[] gts = new GenericsType[n];
+ for (int i = 0; i < n; i += 1) {
gts[i] = configureTypeVariableDefinition(tvs[i]);
}
return gts;
}
- private GenericsType configureTypeVariableDefinition(TypeVariable tv) {
+ private GenericsType configureTypeVariableDefinition(final TypeVariable tv) {
return configureTypeVariableDefinition(configureTypeVariableReference(tv.getName()), configureTypes(tv.getBounds()));
}
- private ClassNode[] configureTypes(Type[] types) {
- if (types.length == 0) return null;
- ClassNode[] nodes = new ClassNode[types.length];
- for (int i = 0; i < types.length; i++) {
+ private ClassNode[] configureTypes(final Type[] types) {
+ final int n = types.length;
+ if (n == 0) return null;
+ ClassNode[] nodes = new ClassNode[n];
+ for (int i = 0; i < n; i += 1) {
nodes[i] = configureType(types[i]);
}
return nodes;
}
- private ClassNode configureType(Type type) {
+ private ClassNode configureType(final Type type) {
if (type instanceof WildcardType) {
return configureWildcardType((WildcardType) type);
} else if (type instanceof ParameterizedType) {
@@ -244,14 +231,14 @@ public class Java8 implements VMPlugin {
return configureTypeVariableReference(((TypeVariable) type).getName());
} else if (type instanceof Class) {
return configureClass((Class<?>) type);
- } else if (type==null) {
+ } else if (type == null) {
throw new GroovyBugError("Type is null. Most probably you let a transform reuse existing ClassNodes with generics information, that is now used in a wrong context.");
} else {
throw new GroovyBugError("unknown type: " + type + " := " + type.getClass());
}
}
- private ClassNode configureGenericArray(GenericArrayType genericArrayType) {
+ private ClassNode configureGenericArray(final GenericArrayType genericArrayType) {
Type component = genericArrayType.getGenericComponentType();
ClassNode node = configureType(component);
return node.makeArray();
@@ -276,17 +263,18 @@ public class Java8 implements VMPlugin {
return wt;
}
- private ClassNode configureParameterizedType(ParameterizedType parameterizedType) {
+ private ClassNode configureParameterizedType(final ParameterizedType parameterizedType) {
ClassNode base = configureType(parameterizedType.getRawType());
GenericsType[] gts = configureTypeArguments(parameterizedType.getActualTypeArguments());
base.setGenericsTypes(gts);
return base;
}
- private GenericsType[] configureTypeArguments(Type[] ta) {
- if (ta.length == 0) return null;
- GenericsType[] gts = new GenericsType[ta.length];
- for (int i = 0; i < ta.length; i++) {
+ private GenericsType[] configureTypeArguments(final Type[] ta) {
+ final int n = ta.length;
+ if (n == 0) return null;
+ GenericsType[] gts = new GenericsType[n];
+ for (int i = 0; i < n; i += 1) {
ClassNode t = configureType(ta[i]);
if (ta[i] instanceof WildcardType) {
GenericsType[] gen = t.getGenericsTypes();
@@ -298,51 +286,10 @@ public class Java8 implements VMPlugin {
return gts;
}
- public Class<?>[] getPluginStaticGroovyMethods() {
- return EMPTY_CLASS_ARRAY;
- }
-
- private void setAnnotationMetaData(Annotation[] annotations, AnnotatedNode an) {
- for (Annotation annotation : annotations) {
- AnnotationNode node = new AnnotationNode(ClassHelper.make(annotation.annotationType()));
- configureAnnotation(node, annotation);
- an.addAnnotation(node);
- }
- }
-
- @Deprecated
- private void configureAnnotationFromDefinition(AnnotationNode definition, AnnotationNode root) {
- VMPlugin plugin = VMPluginFactory.getPlugin();
- plugin.configureAnnotationNodeFromDefinition(definition, root);
- }
+ //
- public void configureAnnotationNodeFromDefinition(AnnotationNode definition, AnnotationNode root) {
- ClassNode type = definition.getClassNode();
- final String typeName = type.getName();
- if ("java.lang.annotation.Retention".equals(typeName)) {
- Expression exp = definition.getMember("value");
- if (!(exp instanceof PropertyExpression)) return;
- PropertyExpression pe = (PropertyExpression) exp;
- String name = pe.getPropertyAsString();
- RetentionPolicy policy = RetentionPolicy.valueOf(name);
- setRetentionPolicy(policy, root);
- } else if ("java.lang.annotation.Target".equals(typeName)) {
- Expression exp = definition.getMember("value");
- if (!(exp instanceof ListExpression)) return;
- ListExpression le = (ListExpression) exp;
- int bitmap = 0;
- for (Expression e : le.getExpressions()) {
- if (!(e instanceof PropertyExpression)) return;
- PropertyExpression element = (PropertyExpression) e;
- String name = element.getPropertyAsString();
- ElementType value = ElementType.valueOf(name);
- bitmap |= getElementCode(value);
- }
- root.setAllowedTargets(bitmap);
- }
- }
-
- public void configureAnnotation(AnnotationNode node) {
+ @Override
+ public void configureAnnotation(final AnnotationNode node) {
ClassNode type = node.getClassNode();
VMPlugin plugin = VMPluginFactory.getPlugin();
List<AnnotationNode> annotations = type.getAnnotations();
@@ -354,7 +301,7 @@ public class Java8 implements VMPlugin {
}
}
- private void configureAnnotation(AnnotationNode node, Annotation annotation) {
+ private void configureAnnotation(final AnnotationNode node, final Annotation annotation) {
Class<?> type = annotation.annotationType();
if (type == Retention.class) {
Retention r = (Retention) annotation;
@@ -382,38 +329,82 @@ public class Java8 implements VMPlugin {
for (Method declaredMethod : declaredMethods) {
try {
Object value = declaredMethod.invoke(annotation);
- Expression valueExpression = annotationValueToExpression(value);
- if (valueExpression == null)
- continue;
- node.setMember(declaredMethod.getName(), valueExpression);
+ Expression valueExpression = toAnnotationValueExpression(value);
+ if (valueExpression != null) node.setMember(declaredMethod.getName(), valueExpression);
+
} catch (IllegalAccessException | InvocationTargetException ignore) {
}
}
}
}
- private Expression annotationValueToExpression (Object value) {
+ private void setAnnotationMetaData(final Annotation[] annotations, final AnnotatedNode target) {
+ for (Annotation annotation : annotations) {
+ target.addAnnotation(toAnnotationNode(annotation));
+ }
+ }
+
+ private AnnotationNode toAnnotationNode(final Annotation annotation) {
+ ClassNode type = ClassHelper.make(annotation.annotationType());
+ AnnotationNode node = new AnnotationNode(type);
+ configureAnnotation(node, annotation);
+ return node;
+ }
+
+ private Expression toAnnotationValueExpression(final Object value) {
if (value == null || value instanceof String || value instanceof Number || value instanceof Character || value instanceof Boolean)
return new ConstantExpression(value);
if (value instanceof Class)
return new ClassExpression(ClassHelper.makeWithoutCaching((Class<?>)value));
+ if (value instanceof Annotation)
+ return new AnnotationConstantExpression(toAnnotationNode((Annotation)value));
+
if (value instanceof Enum)
return new PropertyExpression(new ClassExpression(ClassHelper.makeWithoutCaching(value.getClass())), value.toString());
if (value.getClass().isArray()) {
- ListExpression elementExprs = new ListExpression();
- int len = Array.getLength(value);
- for (int i = 0; i != len; ++i)
- elementExprs.addExpression(annotationValueToExpression(Array.get(value, i)));
- return elementExprs;
+ ListExpression list = new ListExpression();
+ for (int i = 0, n = Array.getLength(value); i < n; i += 1)
+ list.addExpression(toAnnotationValueExpression(Array.get(value, i)));
+ return list;
}
return null;
}
- public void configureClassNode(CompileUnit compileUnit, ClassNode classNode) {
+ //
+
+ @Override
+ public void configureAnnotationNodeFromDefinition(final AnnotationNode definition, final AnnotationNode root) {
+ ClassNode type = definition.getClassNode();
+ final String typeName = type.getName();
+ if ("java.lang.annotation.Retention".equals(typeName)) {
+ Expression exp = definition.getMember("value");
+ if (!(exp instanceof PropertyExpression)) return;
+ PropertyExpression pe = (PropertyExpression) exp;
+ String name = pe.getPropertyAsString();
+ RetentionPolicy policy = RetentionPolicy.valueOf(name);
+ setRetentionPolicy(policy, root);
+ } else if ("java.lang.annotation.Target".equals(typeName)) {
+ Expression exp = definition.getMember("value");
+ if (!(exp instanceof ListExpression)) return;
+ ListExpression le = (ListExpression) exp;
+ int bitmap = 0;
+ for (Expression e : le.getExpressions()) {
+ if (!(e instanceof PropertyExpression)) return;
+ PropertyExpression element = (PropertyExpression) e;
+ String name = element.getPropertyAsString();
+ ElementType value = ElementType.valueOf(name);
+ bitmap |= getElementCode(value);
+ }
+ root.setAllowedTargets(bitmap);
+ }
+ }
+
+ @Override
+ public void configureClassNode(final CompileUnit compileUnit, final ClassNode classNode) {
try {
Class<?> clazz = classNode.getTypeClass();
Field[] fields = clazz.getDeclaredFields();
@@ -435,8 +426,8 @@ public class Java8 implements VMPlugin {
mn.setGenericsTypes(configureTypeVariable(m.getTypeParameters()));
classNode.addMethod(mn);
}
- Constructor[] constructors = clazz.getDeclaredConstructors();
- for (Constructor ctor : constructors) {
+ Constructor<?>[] constructors = clazz.getDeclaredConstructors();
+ for (Constructor<?> ctor : constructors) {
Parameter[] params = makeParameters(compileUnit, ctor.getGenericParameterTypes(), ctor.getParameterTypes(), getConstructorParameterAnnotations(ctor), ctor);
ClassNode[] exceptions = makeClassNodes(compileUnit, ctor.getGenericExceptionTypes(), ctor.getExceptionTypes());
ConstructorNode cn = classNode.addConstructor(ctor.getModifiers(), params, exceptions, null);
@@ -453,9 +444,9 @@ public class Java8 implements VMPlugin {
setAnnotationMetaData(clazz.getPackage().getAnnotations(), packageNode);
}
} catch (NoClassDefFoundError e) {
- throw new NoClassDefFoundError("Unable to load class "+classNode.toString(false)+" due to missing dependency "+e.getMessage());
+ throw new NoClassDefFoundError("Unable to load class " + classNode.toString(false) + " due to missing dependency " + e.getMessage());
} catch (MalformedParameterizedTypeException e) {
- throw new RuntimeException("Unable to configure class node for class "+classNode.toString(false)+" due to malformed parameterized types", e);
+ throw new RuntimeException("Unable to configure class node for class " + classNode.toString(false) + " due to malformed parameterized types", e);
}
}
@@ -474,7 +465,7 @@ public class Java8 implements VMPlugin {
* @param constructor the Constructor for which to return parameter annotations
* @return array of arrays containing the annotations on the parameters of the given Constructor
*/
- private Annotation[][] getConstructorParameterAnnotations(Constructor<?> constructor) {
+ private Annotation[][] getConstructorParameterAnnotations(final Constructor<?> constructor) {
/*
* TODO: Remove after JDK9 is the minimum JDK supported
*
@@ -495,7 +486,7 @@ public class Java8 implements VMPlugin {
);
}
Annotation[][] adjusted = new Annotation[parameterCount][];
- for (int i = 0; i < diff; i++) {
+ for (int i = 0; i < diff; i += 1) {
adjusted[i] = EMPTY_ANNOTATION_ARRAY;
}
System.arraycopy(annotations, 0, adjusted, diff, annotations.length);
@@ -504,20 +495,20 @@ public class Java8 implements VMPlugin {
return annotations;
}
- private void makeInterfaceTypes(CompileUnit cu, ClassNode classNode, Class<?> clazz) {
+ private void makeInterfaceTypes(final CompileUnit cu, final ClassNode classNode, final Class<?> clazz) {
Type[] interfaceTypes = clazz.getGenericInterfaces();
- if (interfaceTypes.length == 0) {
+ final int n = interfaceTypes.length;
+ if (n == 0) {
classNode.setInterfaces(ClassNode.EMPTY_ARRAY);
} else {
- ClassNode[] ret = new ClassNode[interfaceTypes.length];
- for (int i = 0; i < interfaceTypes.length; i++) {
+ ClassNode[] ret = new ClassNode[n];
+ for (int i = 0; i < n; i += 1) {
Type type = interfaceTypes[i];
while (!(type instanceof Class)) {
ParameterizedType pt = (ParameterizedType) type;
Type t2 = pt.getRawType();
- if (t2==type) {
- throw new GroovyBugError("Cannot transform generic signature of "+clazz+
- " with generic interface "+interfaceTypes[i]+" to a class.");
+ if (t2 == type) {
+ throw new GroovyBugError("Cannot transform generic signature of " + clazz + " with generic interface " + interfaceTypes[i] + " to a class.");
}
type = t2;
}
@@ -527,15 +518,16 @@ public class Java8 implements VMPlugin {
}
}
- private ClassNode[] makeClassNodes(CompileUnit cu, Type[] types, Class<?>[] cls) {
- ClassNode[] nodes = new ClassNode[types.length];
- for (int i = 0; i < nodes.length; i++) {
+ private ClassNode[] makeClassNodes(final CompileUnit cu, final Type[] types, final Class<?>[] cls) {
+ final int n = types.length;
+ ClassNode[] nodes = new ClassNode[n];
+ for (int i = 0; i < n; i += 1) {
nodes[i] = makeClassNode(cu, types[i], cls[i]);
}
return nodes;
}
- private ClassNode makeClassNode(CompileUnit cu, Type t, Class<?> c) {
+ private ClassNode makeClassNode(final CompileUnit cu, Type t, final Class<?> c) {
ClassNode back = null;
if (cu != null) back = cu.getClass(c.getName());
if (back == null) back = ClassHelper.make(c);
@@ -548,14 +540,30 @@ public class Java8 implements VMPlugin {
}
@Deprecated
- protected Parameter makeParameter(CompileUnit cu, Type type, Class<?> cl, Annotation[] annotations, String name) {
+ protected Parameter[] processParameters(final CompileUnit compileUnit, final Method m) {
+ java.lang.reflect.Parameter[] parameters = m.getParameters();
+ Type[] types = m.getGenericParameterTypes();
+ Parameter[] params = Parameter.EMPTY_ARRAY;
+ if (types.length > 0) {
+ params = new Parameter[types.length];
+ for (int i = 0; i < params.length; i++) {
+ java.lang.reflect.Parameter p = parameters[i];
+ String name = p.isNamePresent() ? p.getName() : "param" + i;
+ params[i] = makeParameter(compileUnit, types[i], m.getParameterTypes()[i], m.getParameterAnnotations()[i], name);
+ }
+ }
+ return params;
+ }
+
+ @Deprecated
+ protected Parameter makeParameter(final CompileUnit cu, final Type type, final Class<?> cl, final Annotation[] annotations, final String name) {
ClassNode cn = makeClassNode(cu, type, cl);
Parameter parameter = new Parameter(cn, name);
setAnnotationMetaData(annotations, parameter);
return parameter;
}
- private Parameter[] makeParameters(CompileUnit cu, Type[] types, Class[] cls, Annotation[][] parameterAnnotations, Member member) {
+ private Parameter[] makeParameters(final CompileUnit cu, final Type[] types, final Class<?>[] cls, final Annotation[][] parameterAnnotations, final Member member) {
Parameter[] params = Parameter.EMPTY_ARRAY;
int n = types.length;
if (n > 0) {
@@ -570,14 +578,14 @@ public class Java8 implements VMPlugin {
return params;
}
- protected void fillParameterNames(String[] names, Member member) {
+ protected void fillParameterNames(final String[] names, final Member member) {
try {
java.lang.reflect.Parameter[] parameters = ((java.lang.reflect.Executable) member).getParameters();
for (int i = 0, n = names.length; i < n; i += 1) {
names[i] = parameters[i].getName();
}
} catch (RuntimeException e) {
- throw new GroovyBugError(e); // or Java5.fillParameterNames(names, member);
+ throw new GroovyBugError(e);
}
}
@@ -591,7 +599,7 @@ public class Java8 implements VMPlugin {
* @return the check result
*/
@Override
- public boolean checkCanSetAccessible(AccessibleObject accessibleObject, Class<?> callerClass) {
+ public boolean checkCanSetAccessible(final AccessibleObject accessibleObject, final Class<?> callerClass) {
SecurityManager sm = System.getSecurityManager();
try {
if (sm != null) {
@@ -602,7 +610,7 @@ public class Java8 implements VMPlugin {
}
if (accessibleObject instanceof Constructor) {
- Constructor c = (Constructor) accessibleObject;
+ Constructor<?> c = (Constructor<?>) accessibleObject;
if (c.getDeclaringClass() == Class.class) {
return false; // Cannot make a java.lang.Class constructor accessible
}
@@ -612,12 +620,12 @@ public class Java8 implements VMPlugin {
}
@Override
- public boolean checkAccessible(Class<?> callerClass, Class<?> declaringClass, int memberModifiers, boolean allowIllegalAccess) {
+ public boolean checkAccessible(final Class<?> callerClass, final Class<?> declaringClass, final int memberModifiers, final boolean allowIllegalAccess) {
return true;
}
@Override
- public boolean trySetAccessible(AccessibleObject ao) {
+ public boolean trySetAccessible(final AccessibleObject ao) {
try {
ao.setAccessible(true);
return true;
@@ -629,12 +637,12 @@ public class Java8 implements VMPlugin {
}
@Override
- public MetaMethod transformMetaMethod(MetaClass metaClass, MetaMethod metaMethod, Class<?> caller) {
+ public MetaMethod transformMetaMethod(final MetaClass metaClass, final MetaMethod metaMethod, final Class<?> caller) {
return metaMethod;
}
@Override
- public MetaMethod transformMetaMethod(MetaClass metaClass, MetaMethod metaMethod) {
+ public MetaMethod transformMetaMethod(final MetaClass metaClass, final MetaMethod metaMethod) {
return transformMetaMethod(metaClass, metaMethod, null);
}
@@ -644,7 +652,7 @@ public class Java8 implements VMPlugin {
}
@Override
- public Object getInvokeSpecialHandle(Method method, Object receiver) {
+ public Object getInvokeSpecialHandle(final Method method, final Object receiver) {
final Class<?> receiverType = receiver.getClass();
try {
return of(receiverType).unreflectSpecial(method, receiverType).bindTo(receiver);
@@ -653,7 +661,7 @@ public class Java8 implements VMPlugin {
}
}
- private Object getInvokeSpecialHandleFallback(Method method, Object receiver) {
+ private Object getInvokeSpecialHandleFallback(final Method method, final Object receiver) {
if (getLookupConstructor() == null) {
throw new GroovyBugError("getInvokeSpecialHandle requires at least JDK 7 for private access to Lookup");
}
@@ -676,9 +684,8 @@ public class Java8 implements VMPlugin {
}
@Override
- public Object invokeHandle(Object handle, Object[] args) throws Throwable {
- MethodHandle mh = (MethodHandle) handle;
- return mh.invokeWithArguments(args);
+ public Object invokeHandle(final Object handle, final Object[] args) throws Throwable {
+ return ((MethodHandle) handle).invokeWithArguments(args);
}
public static MethodHandles.Lookup of(final Class<?> declaringClass) {
@@ -691,6 +698,10 @@ public class Java8 implements VMPlugin {
}
}
+ private static Constructor<MethodHandles.Lookup> getLookupConstructor() {
+ return LookupHolder.LOOKUP_Constructor;
+ }
+
private static class LookupHolder {
private static final Constructor<MethodHandles.Lookup> LOOKUP_Constructor;
@@ -698,21 +709,21 @@ public class Java8 implements VMPlugin {
Constructor<MethodHandles.Lookup> lookup;
try {
lookup = MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, Integer.TYPE);
- } catch (final NoSuchMethodException ex) {
- throw new IllegalStateException("Incompatible JVM", ex);
+ } catch (final NoSuchMethodException e) {
+ throw new IllegalStateException("Incompatible JVM", e);
}
try {
if (!lookup.isAccessible()) {
- final Constructor tmp = lookup;
+ final Constructor<MethodHandles.Lookup> finalReference = lookup;
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
- ReflectionUtils.trySetAccessible(tmp);
+ ReflectionUtils.trySetAccessible(finalReference);
return null;
});
}
} catch (SecurityException ignore) {
lookup = null;
- } catch (RuntimeException re) {
- throw re;
+ } catch (RuntimeException e) {
+ throw e;
}
LOOKUP_Constructor = lookup;
}
diff --git a/src/test/org/codehaus/groovy/ast/Groovy7826Bug.java b/src/test/org/codehaus/groovy/ast/Groovy7826.java
similarity index 61%
rename from src/test/org/codehaus/groovy/ast/Groovy7826Bug.java
rename to src/test/org/codehaus/groovy/ast/Groovy7826.java
index ed6b4ab596..fb8745c52a 100644
--- a/src/test/org/codehaus/groovy/ast/Groovy7826Bug.java
+++ b/src/test/org/codehaus/groovy/ast/Groovy7826.java
@@ -19,23 +19,25 @@
package org.codehaus.groovy.ast;
import groovy.lang.GroovyShell;
-import groovy.test.GroovyTestCase;
import org.codehaus.groovy.control.CompilerConfiguration;
+import org.junit.Test;
-public class Groovy7826Bug extends GroovyTestCase {
- public void testComplexTypeArguments() throws Exception {
- String script = "def f(org.codehaus.groovy.ast.Groovy7826Bug.C1 c1) { }";
+public final class Groovy7826 {
- CompilerConfiguration config = new CompilerConfiguration();
- config.getOptimizationOptions().put("asmResolving", false);
+ @Test
+ public void testComplexTypeArguments() throws Exception {
+ String script = "def f(" + getClass().getName() + ".C1 c1) { }";
- GroovyShell shell = new GroovyShell(config);
- shell.evaluate(script, "bug7826.groovy");
- }
+ CompilerConfiguration config = new CompilerConfiguration();
+ config.getOptimizationOptions().put("asmResolving", false);
- public static class C1<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
- }
+ GroovyShell shell = new GroovyShell(config);
+ shell.evaluate(script, "bug7826.groovy");
+ }
- public static class C2<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
- }
+ public static class C1<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
+ }
+
+ public static class C2<T2 extends C2<T2, T1>, T1 extends C1<T2, T1>> {
+ }
}
diff --git a/src/test/org/codehaus/groovy/ast/Groovy9871.groovy b/src/test/org/codehaus/groovy/ast/Groovy9871.groovy
new file mode 100644
index 0000000000..1db74bca01
--- /dev/null
+++ b/src/test/org/codehaus/groovy/ast/Groovy9871.groovy
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.codehaus.groovy.ast
+
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression
+import org.codehaus.groovy.ast.expr.Expression
+import org.codehaus.groovy.ast.expr.ListExpression
+import org.junit.Test
+
+final class Groovy9871 {
+
+ @Test
+ void testAnnotationConstantExpression() {
+ ClassNode cn = new ClassNode(org.codehaus.groovy.runtime.ResourceGroovyMethods)
+ // method with @NamedParam annotations that should be wrapped in @NamedParams container
+ MethodNode mn = cn.getMethod('traverse', new Parameter(ClassHelper.make(File), 'file'), new Parameter(ClassHelper.MAP_TYPE, 'options'))
+
+ List<AnnotationNode> annotations = mn.parameters[1].annotations
+
+ assert annotations.size() == 1
+ assert annotations[0].classNode.name == 'groovy.transform.NamedParams'
+ assert annotations[0].members.value instanceof ListExpression
+
+ List<Expression> expressions = annotations[0].members.value.expressions
+
+ assert expressions.size() > 1 // 12 currently
+ assert expressions[0] instanceof AnnotationConstantExpression
+ assert expressions[0].type.name == 'groovy.transform.NamedParam'
+ }
+}