Search in sources :

Example 36 with Parameter

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

the class TupleConstructorASTTransformation method createConstructor.

public static void createConstructor(ClassNode cNode, boolean includeFields, boolean includeProperties, boolean includeSuperFields, boolean includeSuperProperties, boolean callSuper, boolean force, List<String> excludes, List<String> includes, boolean useSetters) {
    // no processing if existing constructors found
    List<ConstructorNode> constructors = cNode.getDeclaredConstructors();
    if (constructors.size() > 1 && !force)
        return;
    boolean foundEmpty = constructors.size() == 1 && constructors.get(0).getFirstStatement() == null;
    if (constructors.size() == 1 && !foundEmpty && !force)
        return;
    // HACK: JavaStubGenerator could have snuck in a constructor we don't want
    if (foundEmpty)
        constructors.remove(0);
    List<FieldNode> superList = new ArrayList<FieldNode>();
    if (includeSuperProperties) {
        superList.addAll(getSuperPropertyFields(cNode.getSuperClass()));
    }
    if (includeSuperFields) {
        superList.addAll(getSuperNonPropertyFields(cNode.getSuperClass()));
    }
    List<FieldNode> list = new ArrayList<FieldNode>();
    if (includeProperties) {
        list.addAll(getInstancePropertyFields(cNode));
    }
    if (includeFields) {
        list.addAll(getInstanceNonPropertyFields(cNode));
    }
    final List<Parameter> params = new ArrayList<Parameter>();
    final List<Expression> superParams = new ArrayList<Expression>();
    final BlockStatement body = new BlockStatement();
    for (FieldNode fNode : superList) {
        String name = fNode.getName();
        if (shouldSkip(name, excludes, includes))
            continue;
        params.add(createParam(fNode, name));
        boolean hasSetter = cNode.getProperty(name) != null && !fNode.isFinal();
        if (callSuper) {
            superParams.add(varX(name));
        } else {
            if (useSetters && hasSetter) {
                body.addStatement(stmt(callThisX(getSetterName(name), varX(name))));
            } else {
                body.addStatement(assignS(propX(varX("this"), name), varX(name)));
            }
        }
    }
    if (callSuper) {
        body.addStatement(stmt(ctorX(ClassNode.SUPER, args(superParams))));
    }
    for (FieldNode fNode : list) {
        String name = fNode.getName();
        if (shouldSkip(name, excludes, includes))
            continue;
        Parameter nextParam = createParam(fNode, name);
        params.add(nextParam);
        boolean hasSetter = cNode.getProperty(name) != null && !fNode.isFinal();
        if (useSetters && hasSetter) {
            body.addStatement(stmt(callThisX(getSetterName(name), varX(nextParam))));
        } else {
            body.addStatement(assignS(propX(varX("this"), name), varX(nextParam)));
        }
    }
    cNode.addConstructor(new ConstructorNode(ACC_PUBLIC, params.toArray(new Parameter[params.size()]), ClassNode.EMPTY_ARRAY, body));
    // or if there is only one Map property (for backwards compatibility)
    if (params.size() > 0) {
        ClassNode firstParam = params.get(0).getType();
        if (params.size() > 1 || firstParam.equals(ClassHelper.OBJECT_TYPE)) {
            if (firstParam.equals(ClassHelper.MAP_TYPE)) {
                addMapConstructors(cNode, true, "The class " + cNode.getName() + " was incorrectly initialized via the map constructor with null.");
            } else {
                ClassNode candidate = HMAP_TYPE;
                while (candidate != null) {
                    if (candidate.equals(firstParam)) {
                        addMapConstructors(cNode, true, "The class " + cNode.getName() + " was incorrectly initialized via the map constructor with null.");
                        break;
                    }
                    candidate = candidate.getSuperClass();
                }
            }
        }
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) Expression(org.codehaus.groovy.ast.expr.Expression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 37 with Parameter

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

the class StaticTypeCheckingVisitor method visitMethodCallArguments.

protected void visitMethodCallArguments(final ClassNode receiver, ArgumentListExpression arguments, boolean visitClosures, final MethodNode selectedMethod) {
    Parameter[] params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
    List<Expression> expressions = new LinkedList<Expression>(arguments.getExpressions());
    if (selectedMethod instanceof ExtensionMethodNode) {
        params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
        expressions.add(0, new VariableExpression("$self", receiver));
    }
    ArgumentListExpression newArgs = new ArgumentListExpression(expressions);
    for (int i = 0, expressionsSize = expressions.size(); i < expressionsSize; i++) {
        final Expression expression = expressions.get(i);
        if (visitClosures && expression instanceof ClosureExpression || !visitClosures && !(expression instanceof ClosureExpression)) {
            if (i < params.length && visitClosures) {
                Parameter param = params[i];
                checkClosureWithDelegatesTo(receiver, selectedMethod, newArgs, params, expression, param);
                if (selectedMethod instanceof ExtensionMethodNode) {
                    if (i > 0) {
                        inferClosureParameterTypes(receiver, arguments, (ClosureExpression) expression, param, selectedMethod);
                    }
                } else {
                    inferClosureParameterTypes(receiver, newArgs, (ClosureExpression) expression, param, selectedMethod);
                }
            }
            expression.visit(this);
            if (expression.getNodeMetaData(StaticTypesMarker.DELEGATION_METADATA) != null) {
                expression.removeNodeMetaData(StaticTypesMarker.DELEGATION_METADATA);
            }
        }
    }
}
Also used : Parameter(org.codehaus.groovy.ast.Parameter) LinkedList(java.util.LinkedList) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

Example 38 with Parameter

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

the class StaticTypeCheckingVisitor method inferReturnTypeGenerics.

/**
     * If a method call returns a parameterized type, then we can perform additional inference on the
     * return type, so that the type gets actual type parameters. For example, the method
     * Arrays.asList(T...) is generified with type T which can be deduced from actual type
     * arguments.
     *
     * @param method    the method node
     * @param arguments the method call arguments
     * @param explicitTypeHints explicit type hints as found for example in Collections.&lt;String&gt;emptyList()
     * @return parameterized, infered, class node
     */
protected ClassNode inferReturnTypeGenerics(ClassNode receiver, MethodNode method, Expression arguments, GenericsType[] explicitTypeHints) {
    ClassNode returnType = method.getReturnType();
    if (method instanceof ExtensionMethodNode && (isUsingGenericsOrIsArrayUsingGenerics(returnType))) {
        // check if the placeholder corresponds to the placeholder of the first parameter
        ExtensionMethodNode emn = (ExtensionMethodNode) method;
        MethodNode dgmMethod = emn.getExtensionMethodNode();
        ClassNode dc = emn.getDeclaringClass();
        ArgumentListExpression argList = new ArgumentListExpression();
        VariableExpression vexp = new VariableExpression("$foo", receiver);
        vexp.setNodeMetaData(ExtensionMethodDeclaringClass.class, dc);
        argList.addExpression(vexp);
        if (arguments instanceof ArgumentListExpression) {
            List<Expression> expressions = ((ArgumentListExpression) arguments).getExpressions();
            for (Expression arg : expressions) {
                argList.addExpression(arg);
            }
        } else {
            argList.addExpression(arguments);
        }
        return inferReturnTypeGenerics(receiver, dgmMethod, argList);
    }
    if (!isUsingGenericsOrIsArrayUsingGenerics(returnType))
        return returnType;
    if (getGenericsWithoutArray(returnType) == null)
        return returnType;
    Map<String, GenericsType> resolvedPlaceholders = resolvePlaceHoldersFromDeclaration(receiver, getDeclaringClass(method, arguments), method, method.isStatic());
    if (!receiver.isGenericsPlaceHolder()) {
        GenericsUtils.extractPlaceholders(receiver, resolvedPlaceholders);
    }
    resolvePlaceholdersFromExplicitTypeHints(method, explicitTypeHints, resolvedPlaceholders);
    if (resolvedPlaceholders.isEmpty())
        return returnType;
    Map<String, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
    applyGenericsConnections(placeholdersFromContext, resolvedPlaceholders);
    // then resolve receivers from method arguments
    Parameter[] parameters = method.getParameters();
    boolean isVargs = isVargs(parameters);
    ArgumentListExpression argList = InvocationWriter.makeArgumentList(arguments);
    List<Expression> expressions = argList.getExpressions();
    int paramLength = parameters.length;
    if (expressions.size() >= paramLength) {
        for (int i = 0; i < paramLength; i++) {
            boolean lastArg = i == paramLength - 1;
            ClassNode type = parameters[i].getType();
            ClassNode actualType = getType(expressions.get(i));
            while (!type.isUsingGenerics() && type.isArray() && actualType.isArray()) {
                type = type.getComponentType();
                actualType = actualType.getComponentType();
            }
            if (isUsingGenericsOrIsArrayUsingGenerics(type)) {
                if (implementsInterfaceOrIsSubclassOf(actualType, CLOSURE_TYPE) && isSAMType(type)) {
                    // implicit closure coercion in action!
                    Map<String, GenericsType> pholders = applyGenericsContextToParameterClass(resolvedPlaceholders, type);
                    actualType = convertClosureTypeToSAMType(expressions.get(i), actualType, type, pholders);
                }
                if (isVargs && lastArg && actualType.isArray()) {
                    actualType = actualType.getComponentType();
                }
                if (isVargs && lastArg && type.isArray()) {
                    type = type.getComponentType();
                }
                actualType = wrapTypeIfNecessary(actualType);
                Map<String, GenericsType> connections = new HashMap<String, GenericsType>();
                extractGenericsConnections(connections, actualType, type);
                extractGenericsConnectionsForSuperClassAndInterfaces(resolvedPlaceholders, connections);
                applyGenericsConnections(connections, resolvedPlaceholders);
            }
        }
    }
    return applyGenericsContext(resolvedPlaceholders, returnType);
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedHashMap(java.util.LinkedHashMap) ListHashMap(org.codehaus.groovy.util.ListHashMap) HashMap(java.util.HashMap) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint) MethodNode(org.codehaus.groovy.ast.MethodNode) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter)

Example 39 with Parameter

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

the class StaticTypeCheckingVisitor method checkGroovyStyleConstructor.

/**
     * Checks that a constructor style expression is valid regarding the number of arguments and the argument types.
     *
     * @param node      the class node for which we will try to find a matching constructor
     * @param arguments the constructor arguments
     */
protected MethodNode checkGroovyStyleConstructor(final ClassNode node, final ClassNode[] arguments, final ASTNode source) {
    if (node.equals(ClassHelper.OBJECT_TYPE) || node.equals(ClassHelper.DYNAMIC_TYPE)) {
        // in that case, we are facing a list constructor assigned to a def or object
        return null;
    }
    List<ConstructorNode> constructors = node.getDeclaredConstructors();
    if (constructors.isEmpty() && arguments.length == 0) {
        return null;
    }
    List<MethodNode> constructorList = findMethod(node, "<init>", arguments);
    if (constructorList.isEmpty()) {
        if (isBeingCompiled(node) && arguments.length == 1 && LINKEDHASHMAP_CLASSNODE.equals(arguments[0])) {
            // there will be a default hash map constructor added later
            ConstructorNode cn = new ConstructorNode(Opcodes.ACC_PUBLIC, new Parameter[] { new Parameter(LINKEDHASHMAP_CLASSNODE, "args") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
            return cn;
        } else {
            addStaticTypeError("No matching constructor found: " + node + toMethodParametersString("<init>", arguments), source);
            return null;
        }
    } else if (constructorList.size() > 1) {
        addStaticTypeError("Ambiguous constructor call " + node + toMethodParametersString("<init>", arguments), source);
        return null;
    }
    return constructorList.get(0);
}
Also used : MethodNode(org.codehaus.groovy.ast.MethodNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 40 with Parameter

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

the class StaticTypeCheckingVisitor method typeCheckMethodsWithGenericsOrFail.

protected boolean typeCheckMethodsWithGenericsOrFail(ClassNode receiver, ClassNode[] arguments, MethodNode candidateMethod, Expression location) {
    if (!typeCheckMethodsWithGenerics(receiver, arguments, candidateMethod)) {
        Map<String, GenericsType> classGTs = GenericsUtils.extractPlaceholders(receiver);
        ClassNode[] ptypes = new ClassNode[candidateMethod.getParameters().length];
        final Parameter[] parameters = candidateMethod.getParameters();
        for (int i = 0; i < parameters.length; i++) {
            final Parameter parameter = parameters[i];
            ClassNode type = parameter.getType();
            ptypes[i] = fullyResolveType(type, classGTs);
        }
        addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" + toMethodParametersString(candidateMethod.getName(), ptypes) + " with arguments " + formatArgumentList(arguments), location);
        return false;
    }
    return true;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) GenericsType(org.codehaus.groovy.ast.GenericsType) Parameter(org.codehaus.groovy.ast.Parameter) ClosureSignatureHint(groovy.transform.stc.ClosureSignatureHint)

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