Search in sources :

Example 96 with PropertyNode

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

the class SortableASTTransformation method createCompareToMethodBody.

private static Statement createCompareToMethodBody(List<PropertyNode> properties) {
    List<Statement> statements = new ArrayList<Statement>();
    // if (this.is(other)) return 0;
    statements.add(ifS(callThisX("is", args(OTHER)), returnS(constX(0))));
    if (properties.isEmpty()) {
        // perhaps overkill but let compareTo be based on hashes for commutativity
        // return this.hashCode() <=> other.hashCode()
        statements.add(declS(varX(THIS_HASH, ClassHelper.Integer_TYPE), callX(varX("this"), "hashCode")));
        statements.add(declS(varX(OTHER_HASH, ClassHelper.Integer_TYPE), callX(varX(OTHER), "hashCode")));
        statements.add(returnS(cmpX(varX(THIS_HASH), varX(OTHER_HASH))));
    } else {
        // int value = 0;
        statements.add(declS(varX(VALUE, ClassHelper.int_TYPE), constX(0)));
        for (PropertyNode property : properties) {
            String propName = property.getName();
            // value = this.prop <=> other.prop;
            statements.add(assignS(varX(VALUE), cmpX(propX(varX("this"), propName), propX(varX(OTHER), propName))));
            // if (value != 0) return value;
            statements.add(ifS(neX(varX(VALUE), constX(0)), returnS(varX(VALUE))));
        }
        // objects are equal
        statements.add(returnS(constX(0)));
    }
    final BlockStatement body = new BlockStatement();
    body.addStatements(statements);
    return body;
}
Also used : Statement(org.codehaus.groovy.ast.stmt.Statement) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 97 with PropertyNode

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

the class ToStringASTTransformation method calculateToStringStatements.

private static Expression calculateToStringStatements(ClassNode cNode, boolean includeSuper, boolean includeFields, List<String> excludes, List<String> includes, boolean includeNames, boolean ignoreNulls, boolean includePackage, boolean includeSuperProperties, BlockStatement body) {
    // def _result = new StringBuilder()
    final Expression result = varX("_result");
    body.addStatement(declS(result, ctorX(STRINGBUILDER_TYPE)));
    // def $toStringFirst = true
    final VariableExpression first = varX("$toStringFirst");
    body.addStatement(declS(first, constX(Boolean.TRUE)));
    // <class_name>(
    String className = (includePackage) ? cNode.getName() : cNode.getNameWithoutPackage();
    body.addStatement(appendS(result, constX(className + "(")));
    // append properties
    List<PropertyNode> pList;
    if (includeSuperProperties) {
        pList = getAllProperties(cNode);
        Iterator<PropertyNode> pIterator = pList.iterator();
        while (pIterator.hasNext()) {
            if (pIterator.next().isStatic()) {
                pIterator.remove();
            }
        }
    } else {
        pList = getInstanceProperties(cNode);
    }
    for (PropertyNode pNode : pList) {
        if (shouldSkip(pNode.getName(), excludes, includes))
            continue;
        Expression getter = getterX(cNode, pNode);
        appendValue(body, result, first, getter, pNode.getName(), includeNames, ignoreNulls);
    }
    // append fields if needed
    if (includeFields) {
        List<FieldNode> fList = new ArrayList<FieldNode>();
        fList.addAll(getInstanceNonPropertyFields(cNode));
        for (FieldNode fNode : fList) {
            if (shouldSkip(fNode.getName(), excludes, includes))
                continue;
            appendValue(body, result, first, varX(fNode), fNode.getName(), includeNames, ignoreNulls);
        }
    }
    // append super if needed
    if (includeSuper) {
        appendCommaIfNotFirst(body, result, first);
        appendPrefix(body, result, "super", includeNames);
        // not through MOP to avoid infinite recursion
        body.addStatement(appendS(result, callSuperX("toString")));
    }
    // wrap up
    body.addStatement(appendS(result, constX(")")));
    MethodCallExpression toString = callX(result, "toString");
    toString.setImplicitThis(false);
    return toString;
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ToString(groovy.transform.ToString)

Example 98 with PropertyNode

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

the class EqualsAndHashCodeASTTransformation method createEquals.

public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes) {
    if (useCanEqual)
        createCanEqual(cNode);
    // make a public method if none exists otherwise try a private method with leading underscore
    boolean hasExistingEquals = hasDeclaredMethod(cNode, "equals", 1);
    if (hasExistingEquals && hasDeclaredMethod(cNode, "_equals", 1))
        return;
    final BlockStatement body = new BlockStatement();
    VariableExpression other = varX("other");
    // some short circuit cases for efficiency
    body.addStatement(ifS(equalsNullX(other), returnS(constX(Boolean.FALSE, true))));
    body.addStatement(ifS(sameX(varX("this"), other), returnS(constX(Boolean.TRUE, true))));
    if (useCanEqual) {
        body.addStatement(ifS(notX(isInstanceOfX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE, true))));
    } else {
        body.addStatement(ifS(notX(hasClassX(other, GenericsUtils.nonGeneric(cNode))), returnS(constX(Boolean.FALSE, true))));
    }
    VariableExpression otherTyped = varX("otherTyped", GenericsUtils.nonGeneric(cNode));
    CastExpression castExpression = new CastExpression(GenericsUtils.nonGeneric(cNode), other);
    castExpression.setStrict(true);
    body.addStatement(declS(otherTyped, castExpression));
    if (useCanEqual) {
        body.addStatement(ifS(notX(callX(otherTyped, "canEqual", varX("this"))), returnS(constX(Boolean.FALSE, true))));
    }
    List<PropertyNode> pList = getInstanceProperties(cNode);
    for (PropertyNode pNode : pList) {
        if (shouldSkip(pNode.getName(), excludes, includes))
            continue;
        boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(pNode.getOriginType(), cNode);
        if (!canBeSelf) {
            body.addStatement(ifS(notX(hasEqualPropertyX(pNode, otherTyped)), returnS(constX(Boolean.FALSE, true))));
        } else {
            body.addStatement(ifS(notX(hasSamePropertyX(pNode, otherTyped)), ifElseS(differentSelfRecursivePropertyX(pNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursivePropertyX(pNode, otherTyped)), ifS(notX(hasEqualPropertyX(pNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))))));
        }
    }
    List<FieldNode> fList = new ArrayList<FieldNode>();
    if (includeFields) {
        fList.addAll(getInstanceNonPropertyFields(cNode));
    }
    for (FieldNode fNode : fList) {
        if (shouldSkip(fNode.getName(), excludes, includes))
            continue;
        body.addStatement(ifS(notX(hasSameFieldX(fNode, otherTyped)), ifElseS(differentSelfRecursiveFieldX(fNode, otherTyped), returnS(constX(Boolean.FALSE, true)), ifS(notX(bothSelfRecursiveFieldX(fNode, otherTyped)), ifS(notX(hasEqualFieldX(fNode, otherTyped)), returnS(constX(Boolean.FALSE, true)))))));
    }
    if (callSuper) {
        body.addStatement(ifS(notX(isTrueX(callSuperX("equals", other))), returnS(constX(Boolean.FALSE, true))));
    }
    // default
    body.addStatement(returnS(constX(Boolean.TRUE, true)));
    cNode.addMethod(new MethodNode(hasExistingEquals ? "_equals" : "equals", hasExistingEquals ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.boolean_TYPE, params(param(OBJECT_TYPE, other.getName())), ClassNode.EMPTY_ARRAY, body));
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) MethodNode(org.codehaus.groovy.ast.MethodNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression)

Example 99 with PropertyNode

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

the class ImmutableASTTransformation method createConstructorMap.

private void createConstructorMap(ClassNode cNode, List<PropertyNode> list, List<String> knownImmutableClasses, List<String> knownImmutables) {
    final BlockStatement body = new BlockStatement();
    body.addStatement(ifS(equalsNullX(varX("args")), assignS(varX("args"), new MapExpression())));
    for (PropertyNode pNode : list) {
        body.addStatement(createConstructorStatement(cNode, pNode, knownImmutableClasses, knownImmutables));
    }
    // check for missing properties
    body.addStatement(stmt(callX(SELF_TYPE, "checkPropNames", args("this", "args"))));
    createConstructorMapCommon(cNode, body);
    if (list.size() > 0) {
        createNoArgConstructor(cNode);
    }
}
Also used : MapExpression(org.codehaus.groovy.ast.expr.MapExpression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 100 with PropertyNode

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

the class StaticTypeCheckingVisitor method existsProperty.

/**
 * Checks whether a property exists on the receiver, or on any of the possible receiver classes (found in the
 * temporary type information table)
 *
 * @param pexp             a property expression
 * @param readMode         if true, look for property read, else for property set
 * @param visitor          if not null, when the property node is found, visit it with the provided visitor
 * @return true if the property is defined in any of the possible receiver classes
 */
protected boolean existsProperty(final PropertyExpression pexp, final boolean readMode, final ClassCodeVisitorSupport visitor) {
    super.visitPropertyExpression(pexp);
    String propertyName = pexp.getPropertyAsString();
    if (propertyName == null)
        return false;
    Expression objectExpression = pexp.getObjectExpression();
    final ClassNode objectExpressionType = getType(objectExpression);
    boolean staticOnlyAccess = isClassClassNodeWrappingConcreteType(objectExpressionType);
    if ("this".equals(propertyName) && staticOnlyAccess) {
        // Outer.this
        ClassNode outerNode = objectExpressionType.getGenericsTypes()[0].getType();
        ClassNode current = typeCheckingContext.getEnclosingClassNode();
        if (!current.isStaticClass() && current instanceof InnerClassNode) {
            InnerClassNode icn = (InnerClassNode) current;
            if (outerNode.equals(icn.getOuterClass())) {
                storeType(pexp, outerNode);
                return true;
            }
        }
    }
    if (objectExpressionType.isArray() && "length".equals(pexp.getPropertyAsString())) {
        storeType(pexp, int_TYPE);
        if (visitor != null) {
            PropertyNode node = new PropertyNode("length", Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL, int_TYPE, objectExpressionType, null, null, null);
            visitor.visitProperty(node);
        }
        return true;
    }
    boolean foundGetterOrSetter = false;
    List<Receiver<String>> receivers = new LinkedList<Receiver<String>>();
    List<Receiver<String>> owners = makeOwnerList(objectExpression);
    addReceivers(receivers, owners, pexp.isImplicitThis());
    String capName = MetaClassHelper.capitalize(propertyName);
    boolean isAttributeExpression = pexp instanceof AttributeExpression;
    HashSet<ClassNode> handledNodes = new HashSet<ClassNode>();
    for (Receiver<String> receiver : receivers) {
        ClassNode testClass = receiver.getType();
        LinkedList<ClassNode> queue = new LinkedList<ClassNode>();
        queue.add(testClass);
        if (isPrimitiveType(testClass)) {
            queue.add(getWrapper(testClass));
        }
        while (!queue.isEmpty()) {
            ClassNode current = queue.removeFirst();
            if (handledNodes.contains(current))
                continue;
            handledNodes.add(current);
            Set<ClassNode> allInterfaces = current.getAllInterfaces();
            for (ClassNode intf : allInterfaces) {
                // TODO: apply right generics here!
                queue.add(GenericsUtils.parameterizeType(current, intf));
            }
            // in case of a lookup on Class we look for instance methods on Class
            // as well, since in case of a static property access we have the class
            // itself in the list of receivers already;
            boolean staticOnly;
            if (isClassClassNodeWrappingConcreteType(current)) {
                staticOnly = false;
            } else {
                staticOnly = staticOnlyAccess;
            }
            FieldNode field = current.getDeclaredField(propertyName);
            field = allowStaticAccessToMember(field, staticOnly);
            if (storeField(field, isAttributeExpression, pexp, current, visitor, receiver.getData()))
                return true;
            PropertyNode propertyNode = current.getProperty(propertyName);
            propertyNode = allowStaticAccessToMember(propertyNode, staticOnly);
            if (storeProperty(propertyNode, pexp, current, visitor, receiver.getData()))
                return true;
            boolean isThisExpression = objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression();
            if (storeField(field, isThisExpression, pexp, receiver.getType(), visitor, receiver.getData()))
                return true;
            MethodNode getter = current.getGetterMethod("get" + capName);
            getter = allowStaticAccessToMember(getter, staticOnly);
            if (getter == null)
                getter = current.getGetterMethod("is" + capName);
            getter = allowStaticAccessToMember(getter, staticOnly);
            final String setterName = "set" + capName;
            List<MethodNode> setters = findSetters(current, setterName, false);
            setters = allowStaticAccessToMember(setters, staticOnly);
            // need to visit even if we only look for a setters for compatibility
            if (visitor != null && getter != null)
                visitor.visitMethod(getter);
            if (readMode) {
                if (getter != null) {
                    ClassNode cn = inferReturnTypeGenerics(current, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
                    storeInferredTypeForPropertyExpression(pexp, cn);
                    pexp.removeNodeMetaData(StaticTypesMarker.READONLY_PROPERTY);
                    String delegationData = receiver.getData();
                    if (delegationData != null)
                        pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
                    return true;
                }
            } else {
                if (!setters.isEmpty()) {
                    if (visitor != null) {
                        if (field != null) {
                            visitor.visitField(field);
                        } else {
                            for (MethodNode setter : setters) {
                                ClassNode setterType = setter.getParameters()[0].getOriginType();
                                FieldNode virtual = new FieldNode(propertyName, 0, setterType, current, EmptyExpression.INSTANCE);
                                visitor.visitField(virtual);
                            }
                        }
                    }
                    // TODO: apply generics on parameter[0]?
                    // storeType(pexp, setter.getParameters()[0].getType());
                    SetterInfo info = new SetterInfo(current, setterName, setters);
                    BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
                    if (enclosingBinaryExpression != null) {
                        putSetterInfo(enclosingBinaryExpression.getLeftExpression(), info);
                    }
                    String delegationData = receiver.getData();
                    if (delegationData != null) {
                        pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
                    }
                    return true;
                } else if (getter != null) {
                    pexp.putNodeMetaData(StaticTypesMarker.READONLY_PROPERTY, true);
                }
            }
            foundGetterOrSetter = foundGetterOrSetter || !setters.isEmpty() || getter != null;
            if (storeField(field, true, pexp, current, visitor, receiver.getData()))
                return true;
            // we stop now, otherwise we must check the parent class
            if (/*!isAttributeExpression && */
            current.getSuperClass() != null) {
                queue.add(current.getUnresolvedSuperClass());
            }
        }
        // GROOVY-5568, the property may be defined by DGM
        List<MethodNode> methods = findDGMMethodsByNameAndArguments(getTransformLoader(), testClass, "get" + capName, ClassNode.EMPTY_ARRAY);
        if (!methods.isEmpty()) {
            List<MethodNode> methodNodes = chooseBestMethod(testClass, methods, ClassNode.EMPTY_ARRAY);
            if (methodNodes.size() == 1) {
                MethodNode getter = methodNodes.get(0);
                if (visitor != null) {
                    visitor.visitMethod(getter);
                }
                ClassNode cn = inferReturnTypeGenerics(testClass, getter, ArgumentListExpression.EMPTY_ARGUMENTS);
                storeInferredTypeForPropertyExpression(pexp, cn);
                return true;
            }
        }
    }
    for (Receiver<String> receiver : receivers) {
        ClassNode testClass = receiver.getType();
        ClassNode propertyType = getTypeForMapPropertyExpression(testClass, objectExpressionType, pexp);
        if (propertyType == null)
            propertyType = getTypeForListPropertyExpression(testClass, objectExpressionType, pexp);
        if (propertyType == null)
            propertyType = getTypeForSpreadExpression(testClass, objectExpressionType, pexp);
        if (propertyType == null)
            continue;
        if (visitor != null) {
            // todo : type inference on maps and lists, if possible
            PropertyNode node = new PropertyNode(propertyName, Opcodes.ACC_PUBLIC, propertyType, receiver.getType(), null, null, null);
            node.setDeclaringClass(receiver.getType());
            visitor.visitProperty(node);
        }
        storeType(pexp, propertyType);
        String delegationData = receiver.getData();
        if (delegationData != null)
            pexp.putNodeMetaData(StaticTypesMarker.IMPLICIT_RECEIVER, delegationData);
        return true;
    }
    return foundGetterOrSetter;
}
Also used : LowestUpperBoundClassNode(org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) LinkedList(java.util.LinkedList) MethodNode(org.codehaus.groovy.ast.MethodNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet)

Aggregations

PropertyNode (org.codehaus.groovy.ast.PropertyNode)105 ClassNode (org.codehaus.groovy.ast.ClassNode)50 FieldNode (org.codehaus.groovy.ast.FieldNode)44 ArrayList (java.util.ArrayList)41 MethodNode (org.codehaus.groovy.ast.MethodNode)28 Expression (org.codehaus.groovy.ast.expr.Expression)27 BlockStatement (org.codehaus.groovy.ast.stmt.BlockStatement)24 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)23 Parameter (org.codehaus.groovy.ast.Parameter)22 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)19 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)19 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)16 HashSet (java.util.HashSet)14 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)14 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)14 PropertyExpression (org.codehaus.groovy.ast.expr.PropertyExpression)14 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)13 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)13 Statement (org.codehaus.groovy.ast.stmt.Statement)12 ConstructorNode (org.codehaus.groovy.ast.ConstructorNode)11