Search in sources :

Example 86 with FieldNode

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

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

the class MethodCallExpressionTransformer method transformMethodCallExpression.

Expression transformMethodCallExpression(final MethodCallExpression expr) {
    Expression trn = tryTransformIsToCompareIdentity(expr);
    if (trn != null) {
        return trn;
    }
    ClassNode superCallReceiver = expr.getNodeMetaData(StaticTypesMarker.SUPER_MOP_METHOD_REQUIRED);
    if (superCallReceiver != null) {
        return transformMethodCallExpression(transformToMopSuperCall(superCallReceiver, expr));
    }
    Expression objectExpression = expr.getObjectExpression();
    ClassNode type = staticCompilationTransformer.getTypeChooser().resolveType(objectExpression, staticCompilationTransformer.getClassNode());
    if (isCallOnClosure(expr)) {
        FieldNode field = staticCompilationTransformer.getClassNode().getField(expr.getMethodAsString());
        if (field != null) {
            VariableExpression vexp = new VariableExpression(field);
            MethodCallExpression result = new MethodCallExpression(vexp, "call", staticCompilationTransformer.transform(expr.getArguments()));
            result.setImplicitThis(false);
            result.setSourcePosition(expr);
            result.setSafe(expr.isSafe());
            result.setSpreadSafe(expr.isSpreadSafe());
            result.setMethodTarget(StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS);
            return result;
        }
    }
    if (type != null && type.isArray()) {
        String method = expr.getMethodAsString();
        ClassNode componentType = type.getComponentType();
        if ("getAt".equals(method)) {
            Expression arguments = expr.getArguments();
            if (arguments instanceof TupleExpression) {
                List<Expression> argList = ((TupleExpression) arguments).getExpressions();
                if (argList.size() == 1) {
                    Expression indexExpr = argList.get(0);
                    ClassNode argType = staticCompilationTransformer.getTypeChooser().resolveType(indexExpr, staticCompilationTransformer.getClassNode());
                    ClassNode indexType = ClassHelper.getWrapper(argType);
                    if (componentType.isEnum() && ClassHelper.Number_TYPE == indexType) {
                        // workaround for generated code in enums which use .next() returning a Number
                        indexType = ClassHelper.Integer_TYPE;
                    }
                    if (argType != null && ClassHelper.Integer_TYPE == indexType) {
                        BinaryExpression binaryExpression = new BinaryExpression(objectExpression, Token.newSymbol("[", indexExpr.getLineNumber(), indexExpr.getColumnNumber()), indexExpr);
                        binaryExpression.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, componentType);
                        return staticCompilationTransformer.transform(binaryExpression);
                    }
                }
            }
        } else if ("putAt".equals(method)) {
            Expression arguments = expr.getArguments();
            if (arguments instanceof TupleExpression) {
                List<Expression> argList = ((TupleExpression) arguments).getExpressions();
                if (argList.size() == 2) {
                    Expression indexExpr = argList.get(0);
                    Expression objExpr = argList.get(1);
                    ClassNode argType = staticCompilationTransformer.getTypeChooser().resolveType(indexExpr, staticCompilationTransformer.getClassNode());
                    if (argType != null && ClassHelper.Integer_TYPE == ClassHelper.getWrapper(argType)) {
                        BinaryExpression arrayGet = new BinaryExpression(objectExpression, Token.newSymbol("[", indexExpr.getLineNumber(), indexExpr.getColumnNumber()), indexExpr);
                        arrayGet.putNodeMetaData(StaticTypesMarker.INFERRED_TYPE, componentType);
                        BinaryExpression assignment = new BinaryExpression(arrayGet, Token.newSymbol("=", objExpr.getLineNumber(), objExpr.getColumnNumber()), objExpr);
                        return staticCompilationTransformer.transform(assignment);
                    }
                }
            }
        }
    }
    return staticCompilationTransformer.superTransform(expr);
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) List(java.util.List)

Example 88 with FieldNode

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

the class FieldASTTransformation method visit.

public void visit(ASTNode[] nodes, SourceUnit source) {
    sourceUnit = source;
    if (nodes.length != 2 || !(nodes[0] instanceof AnnotationNode) || !(nodes[1] instanceof AnnotatedNode)) {
        throw new GroovyBugError("Internal error: expecting [AnnotationNode, AnnotatedNode] but got: " + Arrays.asList(nodes));
    }
    AnnotatedNode parent = (AnnotatedNode) nodes[1];
    AnnotationNode node = (AnnotationNode) nodes[0];
    if (!MY_TYPE.equals(node.getClassNode()))
        return;
    if (parent instanceof DeclarationExpression) {
        DeclarationExpression de = (DeclarationExpression) parent;
        ClassNode cNode = de.getDeclaringClass();
        if (!cNode.isScript()) {
            addError("Annotation " + MY_TYPE_NAME + " can only be used within a Script.", parent);
            return;
        }
        candidate = de;
        // GROOVY-4548: temp fix to stop CCE until proper support is added
        if (de.isMultipleAssignmentDeclaration()) {
            addError("Annotation " + MY_TYPE_NAME + " not supported with multiple assignment notation.", parent);
            return;
        }
        VariableExpression ve = de.getVariableExpression();
        variableName = ve.getName();
        // set owner null here, it will be updated by addField
        fieldNode = new FieldNode(variableName, ve.getModifiers(), ve.getType(), null, de.getRightExpression());
        fieldNode.setSourcePosition(de);
        cNode.addField(fieldNode);
        String setterName = "set" + MetaClassHelper.capitalize(variableName);
        cNode.addMethod(setterName, ACC_PUBLIC | ACC_SYNTHETIC, ClassHelper.VOID_TYPE, params(param(ve.getType(), variableName)), ClassNode.EMPTY_ARRAY, block(stmt(assignX(propX(varX("this"), variableName), varX(variableName)))));
        // GROOVY-4833 : annotations that are not Groovy transforms should be transferred to the generated field
        // GROOVY-6112 : also copy acceptable Groovy transforms
        final List<AnnotationNode> annotations = de.getAnnotations();
        for (AnnotationNode annotation : annotations) {
            // GROOVY-6337 HACK: in case newly created field is @Lazy
            if (annotation.getClassNode().equals(LAZY_TYPE)) {
                LazyASTTransformation.visitField(this, annotation, fieldNode);
            }
            final ClassNode annotationClassNode = annotation.getClassNode();
            if (notTransform(annotationClassNode) || acceptableTransform(annotation)) {
                fieldNode.addAnnotation(annotation);
            }
        }
        super.visitClass(cNode);
        // GROOVY-5207 So that Closures can see newly added fields
        // (not super efficient for a very large class with many @Fields but we chose simplicity
        // and understandability of this solution over more complex but efficient alternatives)
        VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(source);
        scopeVisitor.visitClass(cNode);
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode) DeclarationExpression(org.codehaus.groovy.ast.expr.DeclarationExpression) GroovyBugError(org.codehaus.groovy.GroovyBugError) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor)

Example 89 with FieldNode

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

the class ImmutableASTTransformation method addProperty.

private static void addProperty(ClassNode cNode, PropertyNode pNode) {
    final FieldNode fn = pNode.getField();
    cNode.getFields().remove(fn);
    cNode.addProperty(pNode.getName(), pNode.getModifiers() | ACC_FINAL, pNode.getType(), pNode.getInitialExpression(), pNode.getGetterBlock(), pNode.getSetterBlock());
    final FieldNode newfn = cNode.getField(fn.getName());
    cNode.getFields().remove(newfn);
    cNode.addField(fn);
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode)

Example 90 with FieldNode

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

the class ImmutableASTTransformation method visit.

public void visit(ASTNode[] nodes, SourceUnit source) {
    init(nodes, source);
    AnnotatedNode parent = (AnnotatedNode) nodes[1];
    AnnotationNode node = (AnnotationNode) nodes[0];
    //        if (!MY_TYPE.equals(node.getClassNode())) return;
    if (!node.getClassNode().getName().endsWith(".Immutable"))
        return;
    List<PropertyNode> newProperties = new ArrayList<PropertyNode>();
    if (parent instanceof ClassNode) {
        final List<String> knownImmutableClasses = getKnownImmutableClasses(node);
        final List<String> knownImmutables = getKnownImmutables(node);
        ClassNode cNode = (ClassNode) parent;
        String cName = cNode.getName();
        if (!checkNotInterface(cNode, MY_TYPE_NAME))
            return;
        if (!checkPropertyList(cNode, knownImmutables, "knownImmutables", node, MY_TYPE_NAME, false))
            return;
        makeClassFinal(cNode);
        final List<PropertyNode> pList = getInstanceProperties(cNode);
        for (PropertyNode pNode : pList) {
            adjustPropertyForImmutability(pNode, newProperties);
        }
        for (PropertyNode pNode : newProperties) {
            cNode.getProperties().remove(pNode);
            addProperty(cNode, pNode);
        }
        final List<FieldNode> fList = cNode.getFields();
        for (FieldNode fNode : fList) {
            ensureNotPublic(cName, fNode);
        }
        boolean includeSuperProperties = false;
        if (hasAnnotation(cNode, TupleConstructorASTTransformation.MY_TYPE)) {
            AnnotationNode tupleCons = cNode.getAnnotations(TupleConstructorASTTransformation.MY_TYPE).get(0);
            includeSuperProperties = memberHasValue(tupleCons, "includeSuperProperties", true);
            if (unsupportedTupleAttribute(tupleCons, "excludes"))
                return;
            if (unsupportedTupleAttribute(tupleCons, "includes"))
                return;
            if (unsupportedTupleAttribute(tupleCons, "includeFields"))
                return;
            if (unsupportedTupleAttribute(tupleCons, "includeProperties"))
                return;
            if (unsupportedTupleAttribute(tupleCons, "includeSuperFields"))
                return;
            if (unsupportedTupleAttribute(tupleCons, "callSuper"))
                return;
            if (unsupportedTupleAttribute(tupleCons, "force"))
                return;
        }
        createConstructors(cNode, knownImmutableClasses, knownImmutables, includeSuperProperties);
        if (!hasAnnotation(cNode, EqualsAndHashCodeASTTransformation.MY_TYPE)) {
            createHashCode(cNode, true, false, false, null, null);
            createEquals(cNode, false, false, false, null, null);
        }
        if (!hasAnnotation(cNode, ToStringASTTransformation.MY_TYPE)) {
            createToString(cNode, false, false, null, null, false, true);
        }
        if (memberHasValue(node, MEMBER_ADD_COPY_WITH, true) && !pList.isEmpty() && !hasDeclaredMethod(cNode, COPY_WITH_METHOD, 1)) {
            createCopyWith(cNode, pList);
        }
    }
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) AnnotatedNode(org.codehaus.groovy.ast.AnnotatedNode) ArrayList(java.util.ArrayList) ToStringASTTransformation.createToString(org.codehaus.groovy.transform.ToStringASTTransformation.createToString)

Aggregations

FieldNode (org.codehaus.groovy.ast.FieldNode)204 ClassNode (org.codehaus.groovy.ast.ClassNode)126 Expression (org.codehaus.groovy.ast.expr.Expression)58 MethodNode (org.codehaus.groovy.ast.MethodNode)57 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)54 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)50 Parameter (org.codehaus.groovy.ast.Parameter)49 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)43 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)43 ArrayList (java.util.ArrayList)40 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)38 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)36 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)33 AnnotatedNode (org.codehaus.groovy.ast.AnnotatedNode)31 PropertyNode (org.codehaus.groovy.ast.PropertyNode)30 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)27 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)22 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)19 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)15 CastExpression (org.codehaus.groovy.ast.expr.CastExpression)15