Search in sources :

Example 26 with Parameter

use of org.codehaus.groovy.ast.Parameter in project grails-core by grails.

the class DefaultASTValidateableHelper method addValidateMethod.

protected void addValidateMethod(final ClassNode classNode) {
    String fieldsToValidateParameterName = "$fieldsToValidate";
    final MethodNode listArgValidateMethod = classNode.getMethod(VALIDATE_METHOD_NAME, new Parameter[] { new Parameter(new ClassNode(List.class), fieldsToValidateParameterName) });
    if (listArgValidateMethod == null) {
        final BlockStatement validateMethodCode = new BlockStatement();
        final ArgumentListExpression validateInstanceArguments = new ArgumentListExpression();
        validateInstanceArguments.addExpression(new VariableExpression("this"));
        validateInstanceArguments.addExpression(new VariableExpression(fieldsToValidateParameterName, ClassHelper.LIST_TYPE));
        final ClassNode validationSupportClassNode = ClassHelper.make(ValidationSupport.class);
        final StaticMethodCallExpression invokeValidateInstanceExpression = new StaticMethodCallExpression(validationSupportClassNode, "validateInstance", validateInstanceArguments);
        validateMethodCode.addStatement(new ExpressionStatement(invokeValidateInstanceExpression));
        final Parameter fieldsToValidateParameter = new Parameter(new ClassNode(List.class), fieldsToValidateParameterName);
        classNode.addMethod(new MethodNode(VALIDATE_METHOD_NAME, Modifier.PUBLIC, ClassHelper.boolean_TYPE, new Parameter[] { fieldsToValidateParameter }, EMPTY_CLASS_ARRAY, validateMethodCode));
    }
    final MethodNode noArgValidateMethod = classNode.getMethod(VALIDATE_METHOD_NAME, ZERO_PARAMETERS);
    if (noArgValidateMethod == null) {
        final BlockStatement validateMethodCode = new BlockStatement();
        final ArgumentListExpression validateInstanceArguments = new ArgumentListExpression();
        validateInstanceArguments.addExpression(new CastExpression(new ClassNode(List.class), new ConstantExpression(null)));
        final Expression callListArgValidateMethod = new MethodCallExpression(new VariableExpression("this"), VALIDATE_METHOD_NAME, validateInstanceArguments);
        validateMethodCode.addStatement(new ReturnStatement(callListArgValidateMethod));
        classNode.addMethod(new MethodNode(VALIDATE_METHOD_NAME, Modifier.PUBLIC, ClassHelper.boolean_TYPE, ZERO_PARAMETERS, EMPTY_CLASS_ARRAY, validateMethodCode));
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) MethodNode(org.codehaus.groovy.ast.MethodNode) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BooleanExpression(org.codehaus.groovy.ast.expr.BooleanExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ReturnStatement(org.codehaus.groovy.ast.stmt.ReturnStatement) Parameter(org.codehaus.groovy.ast.Parameter) ArrayList(java.util.ArrayList) List(java.util.List) CastExpression(org.codehaus.groovy.ast.expr.CastExpression)

Example 27 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class DefaultStrategy method buildMethod.

public void buildMethod(BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno) {
    if (transform.getMemberValue(anno, "includes") != null || transform.getMemberValue(anno, "includes") != null) {
        transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: includes/excludes only allowed on classes", anno);
    }
    ClassNode buildee = mNode.getDeclaringClass();
    ClassNode builder = createBuilder(anno, buildee);
    createBuilderFactoryMethod(anno, buildee, builder);
    for (Parameter parameter : mNode.getParameters()) {
        builder.addField(createFieldCopy(buildee, parameter));
        builder.addMethod(createBuilderMethodForProp(builder, new PropertyInfo(parameter.getName(), parameter.getType()), getPrefix(anno)));
    }
    builder.addMethod(createBuildMethodForMethod(anno, buildee, mNode, mNode.getParameters()));
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 28 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class InitializerStrategy method createBuilderForAnnotatedMethod.

private void createBuilderForAnnotatedMethod(BuilderASTTransformation transform, MethodNode mNode, AnnotationNode anno, boolean useSetters) {
    if (transform.getMemberValue(anno, "includes") != null || transform.getMemberValue(anno, "includes") != null) {
        transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: includes/excludes only allowed on classes", anno);
    }
    if (mNode instanceof ConstructorNode) {
        mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC);
    } else {
        if ((mNode.getModifiers() & ACC_STATIC) == 0) {
            transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: method builders only allowed on static methods", anno);
        }
        mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC);
    }
    ClassNode buildee = mNode.getDeclaringClass();
    Parameter[] parameters = mNode.getParameters();
    ClassNode builder = createInnerHelperClass(buildee, getBuilderClassName(buildee, anno), parameters.length);
    List<FieldNode> convertedFields = convertParamsToFields(builder, parameters);
    buildCommon(buildee, anno, convertedFields, builder);
    if (mNode instanceof ConstructorNode) {
        createBuildeeConstructors(transform, buildee, builder, convertedFields, false, useSetters);
    } else {
        createBuildeeMethods(buildee, mNode, builder, convertedFields);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 29 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class InitializerStrategy method convertParamsToFields.

private List<FieldNode> convertParamsToFields(ClassNode builder, Parameter[] parameters) {
    List<FieldNode> fieldNodes = new ArrayList<FieldNode>();
    for (Parameter parameter : parameters) {
        Map<String, ClassNode> genericsSpec = createGenericsSpec(builder);
        ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, parameter.getType());
        FieldNode fieldNode = new FieldNode(parameter.getName(), parameter.getModifiers(), correctedType, builder, DEFAULT_INITIAL_VALUE);
        fieldNodes.add(fieldNode);
        builder.addField(fieldNode);
    }
    return fieldNodes;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ArrayList(java.util.ArrayList) Parameter(org.codehaus.groovy.ast.Parameter)

Example 30 with Parameter

use of org.codehaus.groovy.ast.Parameter in project groovy-core by groovy.

the class StaticTypeCheckingVisitor method visitMethodCallExpression.

@Override
public void visitMethodCallExpression(MethodCallExpression call) {
    final String name = call.getMethodAsString();
    if (name == null) {
        addStaticTypeError("cannot resolve dynamic method name at compile time.", call.getMethod());
        return;
    }
    if (extension.beforeMethodCall(call)) {
        extension.afterMethodCall(call);
        return;
    }
    typeCheckingContext.pushEnclosingMethodCall(call);
    final Expression objectExpression = call.getObjectExpression();
    objectExpression.visit(this);
    call.getMethod().visit(this);
    // the call is made on a collection type
    if (call.isSpreadSafe()) {
        //TODO check if this should not be change to iterator based call logic
        ClassNode expressionType = getType(objectExpression);
        if (!implementsInterfaceOrIsSubclassOf(expressionType, Collection_TYPE) && !expressionType.isArray()) {
            addStaticTypeError("Spread operator can only be used on collection types", objectExpression);
            return;
        } else {
            // type check call as if it was made on component type
            ClassNode componentType = inferComponentType(expressionType, int_TYPE);
            MethodCallExpression subcall = new MethodCallExpression(new CastExpression(componentType, EmptyExpression.INSTANCE), name, call.getArguments());
            subcall.setLineNumber(call.getLineNumber());
            subcall.setColumnNumber(call.getColumnNumber());
            subcall.setImplicitThis(call.isImplicitThis());
            visitMethodCallExpression(subcall);
            // the inferred type here should be a list of what the subcall returns
            ClassNode subcallReturnType = getType(subcall);
            ClassNode listNode = LIST_TYPE.getPlainNodeReference();
            listNode.setGenericsTypes(new GenericsType[] { new GenericsType(wrapTypeIfNecessary(subcallReturnType)) });
            storeType(call, listNode);
            // store target method
            storeTargetMethod(call, (MethodNode) subcall.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET));
            typeCheckingContext.popEnclosingMethodCall();
            return;
        }
    }
    final ClassNode rememberLastItType = typeCheckingContext.lastImplicitItType;
    Expression callArguments = call.getArguments();
    ArgumentListExpression argumentList = InvocationWriter.makeArgumentList(callArguments);
    checkForbiddenSpreadArgument(argumentList);
    // for arguments, we need to visit closures *after* the method has been chosen
    final ClassNode receiver = getType(objectExpression);
    visitMethodCallArguments(receiver, argumentList, false, null);
    ClassNode[] args = getArgumentTypes(argumentList);
    final boolean isCallOnClosure = isClosureCall(name, objectExpression, callArguments);
    try {
        boolean callArgsVisited = false;
        if (isCallOnClosure) {
            // this is a closure.call() call
            if (objectExpression == VariableExpression.THIS_EXPRESSION) {
                // isClosureCall() check verified earlier that a field exists
                FieldNode field = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name);
                GenericsType[] genericsTypes = field.getType().getGenericsTypes();
                if (genericsTypes != null) {
                    ClassNode closureReturnType = genericsTypes[0].getType();
                    Object data = field.getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
                    if (data != null) {
                        Parameter[] parameters = (Parameter[]) data;
                        typeCheckClosureCall(callArguments, args, parameters);
                    }
                    storeType(call, closureReturnType);
                }
            } else if (objectExpression instanceof VariableExpression) {
                Variable variable = findTargetVariable((VariableExpression) objectExpression);
                if (variable instanceof ASTNode) {
                    Object data = ((ASTNode) variable).getNodeMetaData(StaticTypesMarker.CLOSURE_ARGUMENTS);
                    if (data != null) {
                        Parameter[] parameters = (Parameter[]) data;
                        typeCheckClosureCall(callArguments, args, parameters);
                    }
                    ClassNode type = getType(((ASTNode) variable));
                    if (type != null && type.equals(CLOSURE_TYPE)) {
                        GenericsType[] genericsTypes = type.getGenericsTypes();
                        type = OBJECT_TYPE;
                        if (genericsTypes != null) {
                            if (!genericsTypes[0].isPlaceholder()) {
                                type = genericsTypes[0].getType();
                            }
                        }
                    }
                    if (type != null) {
                        storeType(call, type);
                    }
                }
            } else if (objectExpression instanceof ClosureExpression) {
                // we can get actual parameters directly
                Parameter[] parameters = ((ClosureExpression) objectExpression).getParameters();
                typeCheckClosureCall(callArguments, args, parameters);
                ClassNode data = getInferredReturnType(objectExpression);
                if (data != null) {
                    storeType(call, data);
                }
            }
            int nbOfArgs = 0;
            if (callArguments instanceof ArgumentListExpression) {
                ArgumentListExpression list = (ArgumentListExpression) callArguments;
                nbOfArgs = list.getExpressions().size();
            } else {
                // todo : other cases
                nbOfArgs = 0;
            }
            storeTargetMethod(call, nbOfArgs == 0 ? CLOSURE_CALL_NO_ARG : nbOfArgs == 1 ? CLOSURE_CALL_ONE_ARG : CLOSURE_CALL_VARGS);
        } else {
            // method call receivers are :
            //   - possible "with" receivers
            //   - the actual receiver as found in the method call expression
            //   - any of the potential receivers found in the instanceof temporary table
            // in that order
            List<Receiver<String>> receivers = new LinkedList<Receiver<String>>();
            List<Receiver<String>> owners = makeOwnerList(objectExpression);
            addReceivers(receivers, owners, call.isImplicitThis());
            List<MethodNode> mn = null;
            Receiver<String> chosenReceiver = null;
            for (Receiver<String> currentReceiver : receivers) {
                mn = findMethod(currentReceiver.getType(), name, args);
                // methods are only static if we are in a static context
                if (!mn.isEmpty() && typeCheckingContext.isInStaticContext && (call.isImplicitThis() || (objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression()))) {
                    // we create a separate method list just to be able to print out
                    // a nice error message to the user
                    List<MethodNode> staticMethods = new LinkedList<MethodNode>();
                    List<MethodNode> nonStaticMethods = new LinkedList<MethodNode>();
                    for (final MethodNode node : mn) {
                        if (node.isStatic()) {
                            staticMethods.add(node);
                        } else {
                            nonStaticMethods.add(node);
                        }
                    }
                    mn = staticMethods;
                    if (staticMethods.isEmpty()) {
                        // choose an arbitrary method to display an error message
                        MethodNode node = nonStaticMethods.get(0);
                        ClassNode owner = node.getDeclaringClass();
                        addStaticTypeError("Non static method " + owner.getName() + "#" + node.getName() + " cannot be called from static context", call);
                    }
                }
                if (!mn.isEmpty()) {
                    chosenReceiver = currentReceiver;
                    break;
                }
            }
            if (mn.isEmpty() && typeCheckingContext.getEnclosingClosure() != null && args.length == 0) {
                // add special handling of getDelegate() and getOwner()
                if ("getDelegate".equals(name)) {
                    mn = Collections.singletonList(GET_DELEGATE);
                } else if ("getOwner".equals(name)) {
                    mn = Collections.singletonList(GET_OWNER);
                } else if ("getThisObject".equals(name)) {
                    mn = Collections.singletonList(GET_THISOBJECT);
                }
            }
            if (mn.isEmpty()) {
                mn = extension.handleMissingMethod(receiver, name, argumentList, args, call);
            }
            if (mn.isEmpty()) {
                addNoMatchingMethodError(receiver, name, args, call);
            } else {
                if (areCategoryMethodCalls(mn, name, args)) {
                    addCategoryMethodCallError(call);
                }
                mn = disambiguateMethods(mn, chosenReceiver != null ? chosenReceiver.getType() : null, args, call);
                if (mn.size() == 1) {
                    MethodNode directMethodCallCandidate = mn.get(0);
                    if (chosenReceiver == null) {
                        chosenReceiver = Receiver.make(directMethodCallCandidate.getDeclaringClass());
                    }
                    ClassNode returnType = getType(directMethodCallCandidate);
                    if (isUsingGenericsOrIsArrayUsingGenerics(returnType)) {
                        visitMethodCallArguments(chosenReceiver.getType(), argumentList, true, directMethodCallCandidate);
                        ClassNode irtg = inferReturnTypeGenerics(chosenReceiver.getType(), directMethodCallCandidate, callArguments, call.getGenericsTypes());
                        returnType = irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType;
                        callArgsVisited = true;
                    }
                    if (directMethodCallCandidate == GET_DELEGATE && typeCheckingContext.getEnclosingClosure() != null) {
                        DelegationMetadata md = getDelegationMetadata(typeCheckingContext.getEnclosingClosure().getClosureExpression());
                        returnType = typeCheckingContext.getEnclosingClassNode();
                        if (md != null) {
                            returnType = md.getType();
                        }
                    }
                    if (typeCheckMethodsWithGenericsOrFail(chosenReceiver.getType(), args, mn.get(0), call)) {
                        returnType = adjustWithTraits(directMethodCallCandidate, chosenReceiver.getType(), args, returnType);
                        storeType(call, returnType);
                        storeTargetMethod(call, directMethodCallCandidate);
                        String data = chosenReceiver.getData();
                        if (data != null) {
                            // the method which has been chosen is supposed to be a call on delegate or owner
                            // so we store the information so that the static compiler may reuse it
                            call.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, data);
                        }
                        // if the object expression is a closure shared variable, we will have to perform a second pass
                        if (objectExpression instanceof VariableExpression) {
                            VariableExpression var = (VariableExpression) objectExpression;
                            if (var.isClosureSharedVariable()) {
                                SecondPassExpression<ClassNode[]> wrapper = new SecondPassExpression<ClassNode[]>(call, args);
                                typeCheckingContext.secondPassExpressions.add(wrapper);
                            }
                        }
                    }
                } else {
                    addAmbiguousErrorMessage(mn, name, args, call);
                }
            }
        }
        // now that a method has been chosen, we are allowed to visit the closures
        if (!callArgsVisited) {
            MethodNode mn = (MethodNode) call.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
            visitMethodCallArguments(receiver, argumentList, true, mn);
            // GROOVY-6219
            if (mn != null) {
                List<Expression> argExpressions = argumentList.getExpressions();
                Parameter[] parameters = mn.getParameters();
                for (int i = 0; i < argExpressions.size() && i < parameters.length; i++) {
                    Expression arg = argExpressions.get(i);
                    ClassNode pType = parameters[i].getType();
                    ClassNode aType = getType(arg);
                    if (CLOSURE_TYPE.equals(pType) && CLOSURE_TYPE.equals(aType)) {
                        if (!isAssignableTo(aType, pType)) {
                            addNoMatchingMethodError(receiver, name, getArgumentTypes(argumentList), call);
                            call.removeNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
                        }
                    }
                }
            }
        }
    } finally {
        typeCheckingContext.popEnclosingMethodCall();
        extension.afterMethodCall(call);
    }
}
Also used : Variable(org.codehaus.groovy.ast.Variable) DynamicVariable(org.codehaus.groovy.ast.DynamicVariable) MethodNode(org.codehaus.groovy.ast.MethodNode) GenericsType(org.codehaus.groovy.ast.GenericsType) ASTNode(org.codehaus.groovy.ast.ASTNode) LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint) LinkedList(java.util.LinkedList) Parameter(org.codehaus.groovy.ast.Parameter)

Aggregations

Parameter (org.codehaus.groovy.ast.Parameter)221 ClassNode (org.codehaus.groovy.ast.ClassNode)135 MethodNode (org.codehaus.groovy.ast.MethodNode)79 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)70 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)67 FieldNode (org.codehaus.groovy.ast.FieldNode)49 Expression (org.codehaus.groovy.ast.expr.Expression)47 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)47 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)44 Statement (org.codehaus.groovy.ast.stmt.Statement)34 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)33 ArrayList (java.util.ArrayList)32 LinkedList (java.util.LinkedList)32 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)30 ReturnStatement (org.codehaus.groovy.ast.stmt.ReturnStatement)29 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)26 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)26 IfStatement (org.codehaus.groovy.ast.stmt.IfStatement)26 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)25 EmptyStatement (org.codehaus.groovy.ast.stmt.EmptyStatement)25