Search in sources :

Example 21 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode in project groovy by apache.

the class DefaultStrategy method createBuildMethodForMethod.

private static MethodNode createBuildMethodForMethod(AnnotationNode anno, ClassNode buildee, MethodNode mNode, Parameter[] params) {
    String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
    final BlockStatement body = new BlockStatement();
    ClassNode returnType;
    if (mNode instanceof ConstructorNode) {
        returnType = newClass(buildee);
        body.addStatement(returnS(ctorX(newClass(mNode.getDeclaringClass()), args(params))));
    } else {
        body.addStatement(returnS(callX(newClass(mNode.getDeclaringClass()), mNode.getName(), args(params))));
        returnType = newClass(mNode.getReturnType());
    }
    return new MethodNode(buildMethodName, ACC_PUBLIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 22 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode in project groovy by apache.

the class AutoCloneASTTransformation method createCloneCopyConstructor.

private static void createCloneCopyConstructor(ClassNode cNode, List<FieldNode> list, List<String> excludes) {
    if (cNode.getDeclaredConstructors().isEmpty()) {
        // add no-arg constructor
        BlockStatement noArgBody = new BlockStatement();
        noArgBody.addStatement(EmptyStatement.INSTANCE);
        cNode.addConstructor(ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, noArgBody);
    }
    boolean hasThisCons = false;
    for (ConstructorNode consNode : cNode.getDeclaredConstructors()) {
        Parameter[] parameters = consNode.getParameters();
        if (parameters.length == 1 && parameters[0].getType().equals(cNode)) {
            hasThisCons = true;
        }
    }
    if (!hasThisCons) {
        BlockStatement initBody = new BlockStatement();
        Parameter initParam = param(GenericsUtils.nonGeneric(cNode), "other");
        final Expression other = varX(initParam);
        boolean hasParent = cNode.getSuperClass() != ClassHelper.OBJECT_TYPE;
        if (hasParent) {
            initBody.addStatement(stmt(ctorX(ClassNode.SUPER, other)));
        }
        for (FieldNode fieldNode : list) {
            String name = fieldNode.getName();
            if (excludes != null && excludes.contains(name))
                continue;
            ClassNode fieldType = fieldNode.getType();
            Expression direct = propX(other, name);
            Expression to = propX(varX("this"), name);
            Statement assignDirect = assignS(to, direct);
            Statement assignCloned = assignS(to, castX(fieldType, callCloneDirectX(direct)));
            Statement assignClonedDynamic = assignS(to, castX(fieldType, callCloneDynamicX(direct)));
            if (isCloneableType(fieldType)) {
                initBody.addStatement(assignCloned);
            } else if (!possiblyCloneable(fieldType)) {
                initBody.addStatement(assignDirect);
            } else {
                initBody.addStatement(ifElseS(isInstanceOfX(direct, CLONEABLE_TYPE), assignClonedDynamic, assignDirect));
            }
        }
        cNode.addConstructor(ACC_PROTECTED, params(initParam), ClassNode.EMPTY_ARRAY, initBody);
    }
    ClassNode[] exceptions = { make(CloneNotSupportedException.class) };
    cNode.addMethod("clone", ACC_PUBLIC, GenericsUtils.nonGeneric(cNode), Parameter.EMPTY_ARRAY, exceptions, block(stmt(ctorX(cNode, args(varX("this"))))));
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Statement(org.codehaus.groovy.ast.stmt.Statement) EmptyStatement(org.codehaus.groovy.ast.stmt.EmptyStatement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 23 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode in project groovy by apache.

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, "excludes") != 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();
    if (parameters.length == 0) {
        transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME + " processing: at least one parameter is required for this strategy", anno);
    }
    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 24 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode in project groovy by apache.

the class TupleConstructorASTTransformation method createConstructor.

public static void createConstructor(AbstractASTTransformation xform, ClassNode cNode, boolean includeFields, boolean includeProperties, boolean includeSuperFields, boolean includeSuperProperties, boolean callSuper, boolean force, List<String> excludes, final List<String> includes, boolean useSetters, boolean defaults, boolean allNames, SourceUnit sourceUnit, ClosureExpression pre, ClosureExpression post) {
    // no processing if existing constructors found
    if (!cNode.getDeclaredConstructors().isEmpty() && !force)
        return;
    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 preBody = new BlockStatement();
    boolean superInPre = false;
    if (pre != null) {
        superInPre = copyStatementsWithSuperAdjustment(pre, preBody);
        if (superInPre && callSuper) {
            xform.addError("Error during " + MY_TYPE_NAME + " processing, can't have a super call in 'pre' " + "closure and also 'callSuper' enabled", cNode);
        }
    }
    final BlockStatement body = new BlockStatement();
    for (FieldNode fNode : superList) {
        String name = fNode.getName();
        if (shouldSkipUndefinedAware(name, excludes, includes, allNames))
            continue;
        params.add(createParam(fNode, name, defaults, xform));
        boolean hasSetter = cNode.getProperty(name) != null && !fNode.isFinal();
        if (callSuper) {
            superParams.add(varX(name));
        } else if (!superInPre) {
            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))));
    }
    if (!preBody.isEmpty()) {
        body.addStatements(preBody.getStatements());
    }
    for (FieldNode fNode : list) {
        String name = fNode.getName();
        if (shouldSkipUndefinedAware(name, excludes, includes, allNames))
            continue;
        Parameter nextParam = createParam(fNode, name, defaults, xform);
        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)));
        }
    }
    if (post != null) {
        body.addStatement(post.getCode());
    }
    if (includes != null) {
        Comparator<Parameter> includeComparator = new Comparator<Parameter>() {

            public int compare(Parameter p1, Parameter p2) {
                return new Integer(includes.indexOf(p1.getName())).compareTo(includes.indexOf(p2.getName()));
            }
        };
        Collections.sort(params, includeComparator);
    }
    cNode.addConstructor(new ConstructorNode(ACC_PUBLIC, params.toArray(new Parameter[params.size()]), ClassNode.EMPTY_ARRAY, body));
    if (sourceUnit != null && !body.isEmpty()) {
        VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(sourceUnit);
        scopeVisitor.visitClass(cNode);
    }
    // or if there is only one Map property (for backwards compatibility)
    if (!params.isEmpty() && defaults) {
        ClassNode firstParam = params.get(0).getType();
        if (params.size() > 1 || firstParam.equals(ClassHelper.OBJECT_TYPE)) {
            String message = "The class " + cNode.getName() + " was incorrectly initialized via the map constructor with null.";
            if (firstParam.equals(ClassHelper.MAP_TYPE)) {
                addMapConstructors(cNode, true, message);
            } else {
                ClassNode candidate = HMAP_TYPE;
                while (candidate != null) {
                    if (candidate.equals(firstParam)) {
                        addMapConstructors(cNode, true, message);
                        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) Comparator(java.util.Comparator) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor)

Example 25 with ConstructorNode

use of org.codehaus.groovy.ast.ConstructorNode in project groovy by apache.

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)

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