Search in sources :

Example 6 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode 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 7 with ConstructorNode

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

the class ConstructorCallTransformer method transformConstructorCall.

Expression transformConstructorCall(final ConstructorCallExpression expr) {
    ConstructorNode node = (ConstructorNode) expr.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
    if (node == null)
        return expr;
    if (node.getParameters().length == 1 && StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(node.getParameters()[0].getType(), ClassHelper.MAP_TYPE) && node.getCode() == StaticTypeCheckingVisitor.GENERATED_EMPTY_STATEMENT) {
        Expression arguments = expr.getArguments();
        if (arguments instanceof TupleExpression) {
            TupleExpression tupleExpression = (TupleExpression) arguments;
            List<Expression> expressions = tupleExpression.getExpressions();
            if (expressions.size() == 1) {
                Expression expression = expressions.get(0);
                if (expression instanceof MapExpression) {
                    MapExpression map = (MapExpression) expression;
                    // check that the node doesn't belong to the list of declared constructors
                    ClassNode declaringClass = node.getDeclaringClass();
                    for (ConstructorNode constructorNode : declaringClass.getDeclaredConstructors()) {
                        if (constructorNode == node) {
                            return staticCompilationTransformer.superTransform(expr);
                        }
                    }
                    // replace this call with a call to <init>() + appropriate setters
                    // for example, foo(x:1, y:2) is replaced with:
                    // { def tmp = new Foo(); tmp.x = 1; tmp.y = 2; return tmp }()
                    MapStyleConstructorCall result = new MapStyleConstructorCall(staticCompilationTransformer, declaringClass, map, expr);
                    return result;
                }
            }
        }
    }
    return staticCompilationTransformer.superTransform(expr);
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) ClassNode(org.codehaus.groovy.ast.ClassNode) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) MapExpression(org.codehaus.groovy.ast.expr.MapExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) BytecodeExpression(org.codehaus.groovy.classgen.BytecodeExpression) Expression(org.codehaus.groovy.ast.expr.Expression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression)

Example 8 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode 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 9 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode 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 10 with ConstructorNode

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

the class StaticTypeCheckingVisitor method addTypeCheckingInfoAnnotation.

protected void addTypeCheckingInfoAnnotation(final MethodNode node) {
    // TypeChecked$TypeCheckingInfo can not be applied on constructors
    if (node instanceof ConstructorNode)
        return;
    // if a returned inferred type is available and no @TypeCheckingInfo is on node, then add an
    // annotation to the method node
    ClassNode rtype = getInferredReturnType(node);
    if (rtype != null && node.getAnnotations(TYPECHECKING_INFO_NODE).isEmpty()) {
        AnnotationNode anno = new AnnotationNode(TYPECHECKING_INFO_NODE);
        anno.setMember("version", CURRENT_SIGNATURE_PROTOCOL);
        SignatureCodec codec = SignatureCodecFactory.getCodec(CURRENT_SIGNATURE_PROTOCOL_VERSION, getTransformLoader());
        String genericsSignature = codec.encode(rtype);
        if (genericsSignature != null) {
            ConstantExpression signature = new ConstantExpression(genericsSignature);
            signature.setType(STRING_TYPE);
            anno.setMember("inferredType", signature);
            node.addAnnotation(anno);
        }
    }
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode)

Aggregations

ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)59 Parameter (org.codehaus.groovy.ast.Parameter)30 ClassNode (org.codehaus.groovy.ast.ClassNode)28 MethodNode (org.codehaus.groovy.ast.MethodNode)21 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)19 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)19 FieldNode (org.codehaus.groovy.ast.FieldNode)13 Expression (org.codehaus.groovy.ast.expr.Expression)10 ArrayList (java.util.ArrayList)8 Statement (org.codehaus.groovy.ast.stmt.Statement)8 PropertyNode (org.codehaus.groovy.ast.PropertyNode)6 MapExpression (org.codehaus.groovy.ast.expr.MapExpression)6 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)6 ExpressionStatement (org.codehaus.groovy.ast.stmt.ExpressionStatement)6 MethodVisitor (org.objectweb.asm.MethodVisitor)6 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)5 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)5 EmptyStatement (org.codehaus.groovy.ast.stmt.EmptyStatement)5 ThrowStatement (org.codehaus.groovy.ast.stmt.ThrowStatement)5 LinkedList (java.util.LinkedList)4