use of org.codehaus.groovy.ast.expr.MapExpression in project groovy by apache.
the class GrabAnnotationTransformation method addGrabResolverAsStaticInitIfNeeded.
private static void addGrabResolverAsStaticInitIfNeeded(ClassNode grapeClassNode, AnnotationNode node, List<Statement> grabResolverInitializers, Map<String, Object> grabResolverMap) {
if ((node.getMember("initClass") == null) || (node.getMember("initClass") == ConstantExpression.TRUE)) {
MapExpression resolverArgs = new MapExpression();
for (Map.Entry<String, Object> next : grabResolverMap.entrySet()) {
resolverArgs.addMapEntryExpression(constX(next.getKey()), constX(next.getValue()));
}
grabResolverInitializers.add(stmt(callX(grapeClassNode, "addResolver", args(resolverArgs))));
}
}
use of org.codehaus.groovy.ast.expr.MapExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method getResultType.
protected ClassNode getResultType(ClassNode left, final int op, final ClassNode right, final BinaryExpression expr) {
ClassNode leftRedirect = left.redirect();
ClassNode rightRedirect = right.redirect();
Expression leftExpression = expr.getLeftExpression();
Expression rightExpression = expr.getRightExpression();
if (op == EQUAL || op == ELVIS_EQUAL) {
if (rightRedirect.isDerivedFrom(CLOSURE_TYPE)) {
ClosureExpression closureExpression = null;
if (rightExpression instanceof ClosureExpression) {
closureExpression = (ClosureExpression) rightExpression;
} else if (rightExpression instanceof MethodReferenceExpression) {
closureExpression = rightExpression.getNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION);
}
if (closureExpression != null) {
MethodNode abstractMethod = findSAM(left);
if (abstractMethod != null) {
return inferSAMTypeGenericsInAssignment(left, abstractMethod, right, closureExpression);
}
}
}
if (leftExpression instanceof VariableExpression) {
ClassNode initialType = getOriginalDeclarationType(leftExpression);
if (isPrimitiveType(rightRedirect) && initialType.isDerivedFrom(Number_TYPE)) {
return getWrapper(right);
}
if (isPrimitiveType(initialType) && rightRedirect.isDerivedFrom(Number_TYPE)) {
return getUnwrapper(right);
}
// as anything can be assigned to a String, Class or [Bb]oolean, return the left type instead
if (isWildcardLeftHandSide(initialType) && !isObjectType(initialType)) {
return initialType;
}
}
if (!isObjectType(leftRedirect)) {
if (rightExpression instanceof ListExpression) {
if (LIST_TYPE.equals(leftRedirect) || ITERABLE_TYPE.equals(leftRedirect) || Collection_TYPE.equals(leftRedirect) || ArrayList_TYPE.isDerivedFrom(leftRedirect)) {
// GROOVY-7128
return getLiteralResultType(left, right, ArrayList_TYPE);
}
if (SET_TYPE.equals(leftRedirect) || LinkedHashSet_TYPE.isDerivedFrom(leftRedirect)) {
// GROOVY-7128
return getLiteralResultType(left, right, LinkedHashSet_TYPE);
}
}
if (rightExpression instanceof MapExpression) {
if (MAP_TYPE.equals(leftRedirect) || LinkedHashMap_TYPE.isDerivedFrom(leftRedirect)) {
// GROOVY-7128, GROOVY-9844
return getLiteralResultType(left, right, LinkedHashMap_TYPE);
}
}
}
return right;
}
if (isBoolIntrinsicOp(op)) {
return boolean_TYPE;
}
if (op == FIND_REGEX) {
return Matcher_TYPE;
}
if (isArrayOp(op)) {
// using getPNR() to ignore generics at this point
// and a different binary expression not to pollute the AST
BinaryExpression newExpr = binX(leftExpression, expr.getOperation(), rightExpression);
newExpr.setSourcePosition(expr);
MethodNode method = findMethodOrFail(newExpr, left.getPlainNodeReference(), "getAt", right.getPlainNodeReference());
if (method != null && implementsInterfaceOrIsSubclassOf(right, RANGE_TYPE)) {
return inferReturnTypeGenerics(left, method, rightExpression);
}
return method != null ? inferComponentType(left, right) : null;
}
// the left operand is determining the result of the operation
// for primitives and their wrapper we use a fixed table here
String operationName = getOperationName(op);
ClassNode mathResultType = getMathResultType(op, leftRedirect, rightRedirect, operationName);
if (mathResultType != null) {
return mathResultType;
}
// GROOVY-9006: compare to null for types that overload equals
if ("equals".equals(operationName) && (left == UNKNOWN_PARAMETER_TYPE || right == UNKNOWN_PARAMETER_TYPE)) {
return boolean_TYPE;
}
// GROOVY-5890: do not mix Class<Type> with Type
if (leftExpression instanceof ClassExpression) {
left = CLASS_Type.getPlainNodeReference();
}
MethodNode method = findMethodOrFail(expr, left, operationName, right);
if (method != null) {
storeTargetMethod(expr, method);
typeCheckMethodsWithGenericsOrFail(left, new ClassNode[] { right }, method, expr);
if (isAssignment(op))
return left;
if (isCompareToBoolean(op))
return boolean_TYPE;
if (op == COMPARE_TO)
return int_TYPE;
return inferReturnTypeGenerics(left, method, args(rightExpression));
}
return null;
}
use of org.codehaus.groovy.ast.expr.MapExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method checkGroovyConstructorMap.
protected void checkGroovyConstructorMap(final Expression receiver, final ClassNode receiverType, final MapExpression mapExpression) {
// workaround for map-style checks putting setter info on wrong AST nodes
typeCheckingContext.pushEnclosingBinaryExpression(null);
for (MapEntryExpression entryExpression : mapExpression.getMapEntryExpressions()) {
Expression keyExpression = entryExpression.getKeyExpression();
if (!(keyExpression instanceof ConstantExpression)) {
addStaticTypeError("Dynamic keys in map-style constructors are unsupported in static type checking", keyExpression);
} else {
String pName = keyExpression.getText();
AtomicReference<ClassNode> pType = new AtomicReference<>();
if (!existsProperty(propX(varX("_", receiverType), pName), false, new PropertyLookupVisitor(pType))) {
addStaticTypeError("No such property: " + pName + " for class: " + prettyPrintTypeName(receiverType), receiver);
} else {
ClassNode targetType = Optional.ofNullable(receiverType.getSetterMethod(getSetterName(pName), false)).map(setter -> setter.getParameters()[0].getType()).orElseGet(pType::get);
Expression valueExpression = entryExpression.getValueExpression();
ClassNode valueType = getType(valueExpression);
ClassNode resultType = getResultType(targetType, ASSIGN, valueType, assignX(keyExpression, valueExpression, entryExpression));
if (!checkCompatibleAssignmentTypes(targetType, resultType, valueExpression) && !extension.handleIncompatibleAssignment(targetType, valueType, entryExpression)) {
addAssignmentError(targetType, valueType, entryExpression);
}
}
}
}
typeCheckingContext.popEnclosingBinaryExpression();
}
use of org.codehaus.groovy.ast.expr.MapExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method typeCheckAssignment.
protected void typeCheckAssignment(final BinaryExpression assignmentExpression, final Expression leftExpression, final ClassNode leftExpressionType, final Expression rightExpression, final ClassNode rightExpressionType) {
if (leftExpression instanceof TupleExpression) {
if (!typeCheckMultipleAssignmentAndContinue(leftExpression, rightExpression))
return;
}
// TODO: need errors for write-only too!
if (addedReadOnlyPropertyError(leftExpression))
return;
ClassNode rTypeWrapped = adjustTypeForSpreading(rightExpressionType, leftExpression);
if (!checkCompatibleAssignmentTypes(leftExpressionType, rTypeWrapped, rightExpression)) {
if (!extension.handleIncompatibleAssignment(leftExpressionType, rightExpressionType, assignmentExpression)) {
addAssignmentError(leftExpressionType, rightExpressionType, rightExpression);
}
} else {
ClassNode lTypeRedirect = leftExpressionType.redirect();
addPrecisionErrors(lTypeRedirect, leftExpressionType, rightExpressionType, rightExpression);
if (rightExpression instanceof ListExpression) {
addListAssignmentConstructorErrors(lTypeRedirect, leftExpressionType, rightExpressionType, rightExpression, assignmentExpression);
} else if (rightExpression instanceof MapExpression) {
addMapAssignmentConstructorErrors(lTypeRedirect, leftExpression, rightExpression);
}
if (!hasGStringStringError(leftExpressionType, rTypeWrapped, rightExpression) && !isConstructorAbbreviation(leftExpressionType, rightExpression)) {
checkTypeGenerics(leftExpressionType, rTypeWrapped, rightExpression);
}
}
}
use of org.codehaus.groovy.ast.expr.MapExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method typeCheckMapConstructor.
protected MethodNode typeCheckMapConstructor(final ConstructorCallExpression call, final ClassNode receiver, final Expression arguments) {
MethodNode node = null;
if (arguments instanceof TupleExpression) {
TupleExpression texp = (TupleExpression) arguments;
List<Expression> expressions = texp.getExpressions();
// should only get here with size = 2 when inner class constructor
if (expressions.size() == 1 || expressions.size() == 2) {
Expression expression = expressions.get(expressions.size() - 1);
if (expression instanceof MapExpression) {
MapExpression argList = (MapExpression) expression;
checkGroovyConstructorMap(call, receiver, argList);
Parameter[] params = expressions.size() == 1 ? new Parameter[] { new Parameter(MAP_TYPE, "map") } : new Parameter[] { new Parameter(receiver.redirect().getOuterClass(), "$p$"), new Parameter(MAP_TYPE, "map") };
node = new ConstructorNode(Opcodes.ACC_PUBLIC, params, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
node.setDeclaringClass(receiver);
}
}
}
return node;
}
Aggregations