use of org.codehaus.groovy.ast.expr.LambdaExpression in project groovy by apache.
the class StaticTypesLambdaWriter method getOrAddLambdaClass.
private ClassNode getOrAddLambdaClass(final LambdaExpression expression, final int modifiers, final MethodNode abstractMethod) {
return lambdaClassNodes.computeIfAbsent(expression, key -> {
ClassNode lambdaClass = createLambdaClass(expression, modifiers, abstractMethod);
controller.getAcg().addInnerClass(lambdaClass);
lambdaClass.addInterface(GENERATED_LAMBDA_TYPE);
lambdaClass.putNodeMetaData(StaticCompilationMetadataKeys.STATIC_COMPILE_NODE, Boolean.TRUE);
lambdaClass.putNodeMetaData(WriterControllerFactory.class, (WriterControllerFactory) x -> controller);
return lambdaClass;
});
}
use of org.codehaus.groovy.ast.expr.LambdaExpression in project groovy by apache.
the class StaticTypesBinaryExpressionMultiTypeDispatcher method evaluateEqual.
@Override
public void evaluateEqual(final BinaryExpression expression, final boolean defineVariable) {
Expression leftExpression = expression.getLeftExpression();
if (!defineVariable) {
if (leftExpression instanceof PropertyExpression) {
PropertyExpression pexp = (PropertyExpression) leftExpression;
if (makeSetProperty(pexp.getObjectExpression(), pexp.getProperty(), expression.getRightExpression(), pexp.isSafe(), pexp.isSpreadSafe(), pexp.isImplicitThis(), pexp instanceof AttributeExpression)) {
return;
}
}
} else {
Expression rightExpression = expression.getRightExpression();
if (rightExpression instanceof LambdaExpression || rightExpression instanceof MethodReferenceExpression) {
rightExpression.putNodeMetaData(INFERRED_FUNCTIONAL_INTERFACE_TYPE, leftExpression.getNodeMetaData(INFERRED_TYPE));
}
}
// GROOVY-5620: spread-safe operator on LHS is not supported
if (leftExpression instanceof PropertyExpression && ((PropertyExpression) leftExpression).isSpreadSafe() && isAssignment(expression.getOperation().getType())) {
// rewrite it so that it can be statically compiled
transformSpreadOnLHS(expression);
return;
}
super.evaluateEqual(expression, defineVariable);
}
use of org.codehaus.groovy.ast.expr.LambdaExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method checkReturnType.
protected ClassNode checkReturnType(final ReturnStatement statement) {
Expression expression = statement.getExpression();
ClassNode type = getType(expression);
TypeCheckingContext.EnclosingClosure enclosingClosure = typeCheckingContext.getEnclosingClosure();
if (enclosingClosure != null) {
// re-visit
if (enclosingClosure.getClosureExpression().getNodeMetaData(INFERRED_TYPE) != null)
return null;
ClassNode inferredReturnType = getInferredReturnType(enclosingClosure.getClosureExpression());
// GROOVY-9995: return ctor call with diamond operator
if (expression instanceof ConstructorCallExpression) {
inferDiamondType((ConstructorCallExpression) expression, inferredReturnType != null ? inferredReturnType : /*GROOVY-10080:*/
dynamicType());
}
if (inferredReturnType != null && !inferredReturnType.equals(type) && !isObjectType(inferredReturnType) && !isPrimitiveVoid(inferredReturnType) && !isPrimitiveBoolean(inferredReturnType) && !GenericsUtils.hasUnresolvedGenerics(inferredReturnType)) {
if (isStringType(inferredReturnType) && isGStringOrGStringStringLUB(type)) {
// GROOVY-9971: convert GString to String at point of return
type = STRING_TYPE;
} else if (GenericsUtils.buildWildcardType(wrapTypeIfNecessary(inferredReturnType)).isCompatibleWith(wrapTypeIfNecessary(type))) {
// GROOVY-8310, GROOVY-10082, GROOVY-10091, GROOVY-10128, GROOVY-10306: allow simple covariance
type = inferredReturnType;
} else if (!isPrimitiveVoid(type) && !extension.handleIncompatibleReturnType(statement, type)) {
// GROOVY-10277: incompatible return value
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " for " + (enclosingClosure.getClosureExpression() instanceof LambdaExpression ? "lambda" : "closure") + " expecting " + prettyPrintType(inferredReturnType), expression);
}
}
return type;
}
MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
if (enclosingMethod != null && !enclosingMethod.isVoidMethod() && !enclosingMethod.isDynamicReturnType()) {
ClassNode returnType = enclosingMethod.getReturnType();
if (!isPrimitiveVoid(getUnwrapper(type)) && !checkCompatibleAssignmentTypes(returnType, type, null, false)) {
if (!extension.handleIncompatibleReturnType(statement, type)) {
addStaticTypeError("Cannot return value of type " + prettyPrintType(type) + " for method returning " + prettyPrintType(returnType), expression);
}
} else if (implementsInterfaceOrIsSubclassOf(type, returnType)) {
BinaryExpression dummy = assignX(varX("{target}", returnType), expression, statement);
// GROOVY-10295
ClassNode resultType = getResultType(returnType, ASSIGN, type, dummy);
checkTypeGenerics(returnType, resultType, expression);
}
}
return null;
}
use of org.codehaus.groovy.ast.expr.LambdaExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method inferParameterAndReturnTypesOfClosureOnRHS.
private void inferParameterAndReturnTypesOfClosureOnRHS(final ClassNode lhsType, final ClosureExpression rhsExpression) {
Tuple2<ClassNode[], ClassNode> typeInfo = GenericsUtils.parameterizeSAM(lhsType);
Parameter[] closureParameters = getParametersSafe(rhsExpression);
ClassNode[] samParameterTypes = typeInfo.getV1();
int n = closureParameters.length, m = samParameterTypes.length;
if (n == m || (1 == m && hasImplicitParameter(rhsExpression))) {
for (int i = 0; i < n; i += 1) {
Parameter parameter = closureParameters[i];
if (parameter.isDynamicTyped()) {
parameter.setType(samParameterTypes[i]);
parameter.setOriginType(samParameterTypes[i]);
} else {
checkParamType(parameter, samParameterTypes[i], i == n - 1, rhsExpression instanceof LambdaExpression);
}
}
} else {
addStaticTypeError("Wrong number of parameters for method target " + toMethodParametersString(findSAM(lhsType).getName(), samParameterTypes), rhsExpression);
}
storeInferredReturnType(rhsExpression, typeInfo.getV2());
}
use of org.codehaus.groovy.ast.expr.LambdaExpression in project groovy by apache.
the class StaticTypeCheckingVisitor method inferMethodReferenceType.
private void inferMethodReferenceType(final ClassNode receiver, final ArgumentListExpression argumentList, final MethodNode selectedMethod) {
if (receiver == null)
return;
if (argumentList == null)
return;
if (selectedMethod == null)
return;
List<Expression> argumentExpressions = argumentList.getExpressions();
if (argumentExpressions == null || argumentExpressions.stream().noneMatch(e -> e instanceof MethodReferenceExpression)) {
return;
}
Parameter[] parameters = selectedMethod.getParameters();
final int nthParameter = parameters.length - 1;
List<Integer> methodReferencePositions = new LinkedList<>();
List<Expression> newArgumentExpressions = new LinkedList<>();
for (int i = 0, n = argumentExpressions.size(); i < n; i += 1) {
Expression argumentExpression = argumentExpressions.get(i);
if (!(argumentExpression instanceof MethodReferenceExpression)) {
newArgumentExpressions.add(argumentExpression);
} else {
// GROOVY-10336
Parameter param = parameters[Math.min(i, nthParameter)];
ClassNode paramType = param.getType();
if (i >= nthParameter && paramType.isArray())
paramType = paramType.getComponentType();
if (!isFunctionalInterface(paramType.redirect())) {
addError("The argument is a method reference, but the parameter type is not a functional interface", argumentExpression);
newArgumentExpressions.add(argumentExpression);
} else {
methodReferencePositions.add(i);
newArgumentExpressions.add(constructLambdaExpressionForMethodReference(paramType));
}
}
}
// GROOVY-10269
if (methodReferencePositions.isEmpty())
return;
visitMethodCallArguments(receiver, args(newArgumentExpressions), true, selectedMethod);
for (int index : methodReferencePositions) {
Expression lambdaExpression = newArgumentExpressions.get(index);
Expression methodReferenceExpression = argumentExpressions.get(index);
methodReferenceExpression.putNodeMetaData(CLOSURE_ARGUMENTS, lambdaExpression.getNodeMetaData(CLOSURE_ARGUMENTS));
}
}
Aggregations