Search in sources :

Example 1 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 2 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)

Example 3 with ConstructorNode

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

the class ImmutableASTTransformation method createConstructorOrdered.

private static void createConstructorOrdered(ClassNode cNode, List<PropertyNode> list) {
    final MapExpression argMap = new MapExpression();
    final Parameter[] orderedParams = new Parameter[list.size()];
    int index = 0;
    for (PropertyNode pNode : list) {
        Parameter param = new Parameter(pNode.getField().getType(), pNode.getField().getName());
        orderedParams[index++] = param;
        argMap.addMapEntryExpression(constX(pNode.getName()), varX(pNode.getName()));
    }
    final BlockStatement orderedBody = new BlockStatement();
    orderedBody.addStatement(stmt(ctorX(ClassNode.THIS, args(castX(HASHMAP_TYPE, argMap)))));
    doAddConstructor(cNode, new ConstructorNode(ACC_PUBLIC, orderedParams, ClassNode.EMPTY_ARRAY, orderedBody));
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 4 with ConstructorNode

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

the class ImmutableASTTransformation method createConstructorMapCommon.

private static void createConstructorMapCommon(ClassNode cNode, BlockStatement body) {
    final List<FieldNode> fList = cNode.getFields();
    for (FieldNode fNode : fList) {
        // public fields will be rejected elsewhere
        if (fNode.isPublic())
            continue;
        // a property
        if (cNode.getProperty(fNode.getName()) != null)
            continue;
        if (fNode.isFinal() && fNode.isStatic())
            continue;
        // internal field
        if (fNode.getName().contains("$") || fNode.isSynthetic())
            continue;
        if (fNode.isFinal() && fNode.getInitialExpression() != null)
            body.addStatement(checkFinalArgNotOverridden(cNode, fNode));
        body.addStatement(createConstructorStatementDefault(fNode));
    }
    doAddConstructor(cNode, new ConstructorNode(ACC_PUBLIC, params(new Parameter(HASHMAP_TYPE, "args")), ClassNode.EMPTY_ARRAY, body));
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) Parameter(org.codehaus.groovy.ast.Parameter)

Example 5 with ConstructorNode

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

the class InheritConstructorsASTTransformation method processClass.

private void processClass(ClassNode cNode, AnnotationNode node) {
    if (cNode.isInterface()) {
        addError("Error processing interface '" + cNode.getName() + "'. " + MY_TYPE_NAME + " only allowed for classes.", cNode);
        return;
    }
    boolean copyConstructorAnnotations = memberHasValue(node, "constructorAnnotations", true);
    boolean copyParameterAnnotations = memberHasValue(node, "parameterAnnotations", true);
    ClassNode sNode = cNode.getSuperClass();
    List<AnnotationNode> superAnnotations = sNode.getAnnotations(MY_TYPE);
    if (superAnnotations.size() == 1) {
        // We need @InheritConstructors from parent classes processed first
        // so force that order here. The transformation is benign on an already
        // processed node so processing twice in any order won't matter bar
        // a very small time penalty.
        processClass(sNode, node);
    }
    for (ConstructorNode cn : sNode.getDeclaredConstructors()) {
        addConstructorUnlessAlreadyExisting(cNode, cn, copyConstructorAnnotations, copyParameterAnnotations);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) 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