use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class AsmClassGenerator method visitAnnotationDefaultExpression.
private void visitAnnotationDefaultExpression(final AnnotationVisitor av, final ClassNode type, final Expression exp) {
if (exp instanceof ClosureExpression) {
ClassNode closureClass = controller.getClosureWriter().getOrAddClosureClass((ClosureExpression) exp, ACC_PUBLIC);
Type t = Type.getType(BytecodeHelper.getTypeDescription(closureClass));
av.visit(null, t);
} else if (type.isArray()) {
AnnotationVisitor avl = av.visitArray(null);
ClassNode componentType = type.getComponentType();
if (exp instanceof ListExpression) {
ListExpression list = (ListExpression) exp;
for (Expression lExp : list.getExpressions()) {
visitAnnotationDefaultExpression(avl, componentType, lExp);
}
} else {
visitAnnotationDefaultExpression(avl, componentType, exp);
}
} else if (isPrimitiveType(type) || isStringType(type)) {
ConstantExpression constExp = (ConstantExpression) exp;
av.visit(null, constExp.getValue());
} else if (isClassType(type)) {
ClassNode clazz = exp.getType();
Type t = Type.getType(BytecodeHelper.getTypeDescription(clazz));
av.visit(null, t);
} else if (type.isDerivedFrom(ClassHelper.Enum_Type)) {
PropertyExpression pExp = (PropertyExpression) exp;
ClassExpression cExp = (ClassExpression) pExp.getObjectExpression();
String desc = BytecodeHelper.getTypeDescription(cExp.getType());
String name = pExp.getPropertyAsString();
av.visitEnum(null, desc, name);
} else if (type.implementsInterface(ClassHelper.Annotation_TYPE)) {
AnnotationConstantExpression avExp = (AnnotationConstantExpression) exp;
AnnotationNode value = (AnnotationNode) avExp.getValue();
AnnotationVisitor avc = av.visitAnnotation(null, BytecodeHelper.getTypeDescription(avExp.getType()));
visitAnnotationAttributes(value, avc);
} else {
throw new GroovyBugError("unexpected annotation type " + type.getName());
}
av.visitEnd();
}
use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class AnnotationVisitor method visitExpression.
protected void visitExpression(String attrName, Expression attrExp, ClassNode attrType) {
if (attrType.isArray()) {
// check needed as @Test(attr = {"elem"}) passes through the parser
if (attrExp instanceof ListExpression) {
ListExpression le = (ListExpression) attrExp;
visitListExpression(attrName, le, attrType.getComponentType());
} else if (attrExp instanceof ClosureExpression) {
addError("Annotation list attributes must use Groovy notation [el1, el2]", attrExp);
} else {
// treat like a singleton list as per Java
ListExpression listExp = new ListExpression();
listExp.addExpression(attrExp);
if (annotation != null) {
annotation.setMember(attrName, listExp);
}
visitExpression(attrName, listExp, attrType);
}
} else if (ClassHelper.isPrimitiveType(attrType)) {
visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), ClassHelper.getWrapper(attrType));
} else if (isStringType(attrType)) {
visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), ClassHelper.STRING_TYPE);
} else if (isClassType(attrType)) {
if (!(attrExp instanceof ClassExpression || attrExp instanceof ClosureExpression)) {
addError("Only classes and closures can be used for attribute '" + attrName + "'", attrExp);
}
} else if (attrType.isDerivedFrom(ClassHelper.Enum_Type)) {
if (attrExp instanceof PropertyExpression) {
visitEnumExpression(attrName, (PropertyExpression) attrExp, attrType);
} else if (attrExp instanceof ConstantExpression) {
visitConstantExpression(attrName, getConstantExpression(attrExp, attrType), attrType);
} else {
addError("Expected enum value for attribute " + attrName, attrExp);
}
} else if (isValidAnnotationClass(attrType)) {
if (attrExp instanceof AnnotationConstantExpression) {
visitAnnotationExpression(attrName, (AnnotationConstantExpression) attrExp, attrType);
} else {
addError("Expected annotation of type '" + attrType.getName() + "' for attribute " + attrName, attrExp);
}
} else {
addError("Unexpected type " + attrType.getName(), attrExp);
}
}
use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class MixinASTTransformation method visit.
@Override
public void visit(ASTNode[] nodes, SourceUnit source) {
init(nodes, source);
AnnotationNode node = (AnnotationNode) nodes[0];
AnnotatedNode parent = (AnnotatedNode) nodes[1];
if (!MY_TYPE.equals(node.getClassNode()))
return;
final Expression expr = node.getMember("value");
if (expr == null) {
return;
}
Expression useClasses = null;
if (expr instanceof ClassExpression) {
useClasses = expr;
} else if (expr instanceof ListExpression) {
ListExpression listExpression = (ListExpression) expr;
for (Expression ex : listExpression.getExpressions()) {
if (!(ex instanceof ClassExpression))
return;
}
useClasses = expr;
}
if (useClasses == null)
return;
if (parent instanceof ClassNode) {
ClassNode annotatedClass = (ClassNode) parent;
final Parameter[] noparams = Parameter.EMPTY_ARRAY;
MethodNode clinit = annotatedClass.getDeclaredMethod("<clinit>", noparams);
if (clinit == null) {
clinit = annotatedClass.addMethod("<clinit>", ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC, ClassHelper.VOID_TYPE, noparams, null, new BlockStatement());
clinit.setSynthetic(true);
}
final BlockStatement code = (BlockStatement) clinit.getCode();
code.addStatement(stmt(callX(propX(classX(annotatedClass), "metaClass"), "mixin", useClasses)));
}
}
use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class Annotations method annotationValueToExpression.
private static Expression annotationValueToExpression(Object value, AsmReferenceResolver resolver) {
if (value instanceof TypeWrapper) {
ClassNode type = resolver.resolveClassNullable(Type.getType(((TypeWrapper) value).desc).getClassName());
return type != null ? new ClassExpression(type) : null;
}
if (value instanceof EnumConstantWrapper) {
EnumConstantWrapper wrapper = (EnumConstantWrapper) value;
return new PropertyExpression(new ClassExpression(resolver.resolveType(Type.getType(wrapper.enumDesc))), wrapper.constant);
}
if (value instanceof AnnotationStub) {
AnnotationNode annotationNode = createAnnotationNode((AnnotationStub) value, resolver);
return annotationNode != null ? new AnnotationConstantExpression(annotationNode) : nullX();
}
if (value != null && 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), resolver));
}
return elementExprs;
}
if (value instanceof List) {
ListExpression elementExprs = new ListExpression();
for (Object o : (List) value) {
elementExprs.addExpression(annotationValueToExpression(o, resolver));
}
return elementExprs;
}
return new ConstantExpression(value);
}
use of org.codehaus.groovy.ast.expr.ListExpression in project groovy by apache.
the class StaticTypeCheckingSupport method checkCompatibleAssignmentTypes.
/**
* Everything that can be done by {@code castToType} should be allowed for assignment.
*
* @see org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation#castToType(Object,Class)
*/
public static boolean checkCompatibleAssignmentTypes(final ClassNode left, final ClassNode right, final Expression rightExpression, final boolean allowConstructorCoercion) {
if (!isPrimitiveType(left) && isNullConstant(rightExpression)) {
return true;
}
if (left.isArray()) {
if (right.isArray()) {
return checkCompatibleAssignmentTypes(left.getComponentType(), right.getComponentType(), rightExpression, false);
}
if (GeneralUtils.isOrImplements(right, Collection_TYPE) && !(rightExpression instanceof ListExpression)) {
GenericsType elementType = GenericsUtils.parameterizeType(right, Collection_TYPE).getGenericsTypes()[0];
return // Object[] can accept any collection element type(s)
OBJECT_TYPE.equals(left.getComponentType()) || (elementType.getLowerBound() == null && isCovariant(extractType(elementType), left.getComponentType()));
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ GROOVY-8984: "? super T" is only compatible with an Object[] target
}
if (GeneralUtils.isOrImplements(right, BaseStream_TYPE)) {
GenericsType elementType = GenericsUtils.parameterizeType(right, BaseStream_TYPE).getGenericsTypes()[0];
return // Object[] can accept any stream API element type(s)
isObjectType(left.getComponentType()) || (elementType.getLowerBound() == null && isCovariant(extractType(elementType), getWrapper(left.getComponentType())));
}
}
ClassNode leftRedirect = left.redirect();
ClassNode rightRedirect = right.redirect();
if (leftRedirect == rightRedirect)
return true;
if (rightRedirect == void_WRAPPER_TYPE)
return leftRedirect == VOID_TYPE;
if (rightRedirect == VOID_TYPE)
return leftRedirect == void_WRAPPER_TYPE;
if (isNumberType(rightRedirect) || isNumberCategory(rightRedirect)) {
if (isBigDecimalType(leftRedirect) || Number_TYPE.equals(leftRedirect)) {
// any number can be assigned to BigDecimal or Number
return true;
}
if (isBigIntegerType(leftRedirect)) {
return isBigIntCategory(getUnwrapper(rightRedirect)) || rightRedirect.isDerivedFrom(BigInteger_TYPE);
}
}
// anything can be assigned to an Object, String, [Bb]oolean or Class receiver; except null to boolean
if (isWildcardLeftHandSide(left) && !(leftRedirect == boolean_TYPE && isNullConstant(rightExpression)))
return true;
if (leftRedirect == char_TYPE && rightRedirect == Character_TYPE)
return true;
if (leftRedirect == Character_TYPE && rightRedirect == char_TYPE)
return true;
if ((leftRedirect == char_TYPE || leftRedirect == Character_TYPE) && rightRedirect == STRING_TYPE) {
return rightExpression instanceof ConstantExpression && rightExpression.getText().length() == 1;
}
// if left is an enum and right is String or GString we do valueOf
if (leftRedirect.isDerivedFrom(Enum_Type) && (rightRedirect == STRING_TYPE || isGStringType(rightRedirect))) {
return true;
}
// if right is array, map or collection we try invoking the constructor
if (allowConstructorCoercion && isGroovyConstructorCompatible(rightExpression)) {
// TODO: in case of the array we could maybe make a partial check
if (rightRedirect.isArray() && !leftRedirect.isArray()) {
return false;
}
return true;
}
// simple check on being subclass
if (right.isDerivedFrom(left) || (left.isInterface() && right.implementsInterface(left)))
return true;
// if left and right are primitives or numbers allow
if (isPrimitiveType(leftRedirect) && isPrimitiveType(rightRedirect))
return true;
if (isNumberType(leftRedirect) && isNumberType(rightRedirect))
return true;
// left is a float/double and right is a BigDecimal
if (isFloatingCategory(leftRedirect) && isBigDecimalType(rightRedirect)) {
return true;
}
if (isGroovyObjectType(leftRedirect) && isBeingCompiled(right)) {
return true;
}
if (right.isDerivedFrom(CLOSURE_TYPE) && isSAMType(left)) {
return true;
}
if (left.isGenericsPlaceHolder()) {
return left.getGenericsTypes()[0].isCompatibleWith(right);
}
// GROOVY-7316, GROOVY-10256: "Type x = m()" given "def <T> T m()"; T adapts to target
return right.isGenericsPlaceHolder() && right.asGenericsType().isCompatibleWith(left);
}
Aggregations