Search in sources :

Example 76 with PropertyNode

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

the class SortableASTTransformation method createSortable.

private void createSortable(AnnotationNode anno, ClassNode classNode) {
    List<String> includes = getMemberStringList(anno, "includes");
    List<String> excludes = getMemberStringList(anno, "excludes");
    boolean reversed = memberHasValue(anno, "reversed", true);
    boolean includeSuperProperties = memberHasValue(anno, "includeSuperProperties", true);
    boolean allNames = memberHasValue(anno, "allNames", true);
    boolean allProperties = !memberHasValue(anno, "allProperties", false);
    if (!checkIncludeExcludeUndefinedAware(anno, excludes, includes, MY_TYPE_NAME))
        return;
    if (!checkPropertyList(classNode, includes, "includes", anno, MY_TYPE_NAME, false, includeSuperProperties, allProperties))
        return;
    if (!checkPropertyList(classNode, excludes, "excludes", anno, MY_TYPE_NAME, false, includeSuperProperties, allProperties))
        return;
    if (classNode.isInterface()) {
        addError(MY_TYPE_NAME + " cannot be applied to interface " + classNode.getName(), anno);
    }
    List<PropertyNode> properties = findProperties(anno, classNode, includes, excludes, allProperties, includeSuperProperties, allNames);
    implementComparable(classNode);
    addGeneratedMethod(classNode, "compareTo", ACC_PUBLIC, ClassHelper.int_TYPE, params(param(newClass(classNode), OTHER)), ClassNode.EMPTY_ARRAY, createCompareToMethodBody(properties, reversed));
    for (PropertyNode property : properties) {
        createComparatorFor(classNode, property, reversed);
    }
    new VariableScopeVisitor(sourceUnit, true).visitClass(classNode);
}
Also used : PropertyNode(org.codehaus.groovy.ast.PropertyNode) VariableScopeVisitor(org.codehaus.groovy.classgen.VariableScopeVisitor)

Example 77 with PropertyNode

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

the class SortableASTTransformation method createCompareToMethodBody.

private static Statement createCompareToMethodBody(List<PropertyNode> properties, boolean reversed) {
    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(localVarX(THIS_HASH, ClassHelper.Integer_TYPE), callX(varX("this"), "hashCode")));
        statements.add(declS(localVarX(OTHER_HASH, ClassHelper.Integer_TYPE), callX(varX(OTHER), "hashCode")));
        statements.add(returnS(compareExpr(varX(THIS_HASH), varX(OTHER_HASH), reversed)));
    } else {
        // int value = 0;
        statements.add(declS(localVarX(VALUE, ClassHelper.int_TYPE), constX(0)));
        for (PropertyNode property : properties) {
            String propName = property.getName();
            // value = this.prop <=> other.prop;
            statements.add(assignS(varX(VALUE), compareExpr(propX(varX("this"), propName), propX(varX(OTHER), propName), reversed)));
            // 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 : BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement)

Example 78 with PropertyNode

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

the class ToStringASTTransformation method calculateToStringStatements.

private static Expression calculateToStringStatements(ClassNode cNode, boolean includeSuper, boolean includeFields, boolean includeSuperFields, List<String> excludes, final List<String> includes, boolean includeNames, boolean ignoreNulls, boolean includePackage, boolean includeSuperProperties, boolean allProperties, BlockStatement body, boolean allNames, boolean pojo, String[] delims) {
    // def _result = new StringBuilder()
    final Expression result = localVarX("_result");
    body.addStatement(declS(result, ctorX(STRINGBUILDER_TYPE)));
    List<ToStringElement> elements = new ArrayList<>();
    // def $toStringFirst = true
    final VariableExpression first = localVarX("$toStringFirst");
    body.addStatement(declS(first, constX(Boolean.TRUE)));
    // <class_name>(
    String className = (includePackage) ? cNode.getName() : cNode.getNameWithoutPackage();
    body.addStatement(appendS(result, constX(className + delims[0])));
    Set<String> names = new HashSet<>();
    List<PropertyNode> superList;
    if (includeSuperProperties || includeSuperFields) {
        superList = getAllProperties(names, cNode, cNode.getSuperClass(), includeSuperProperties, includeSuperFields, allProperties, false, true, true, true, allNames, false);
    } else {
        superList = new ArrayList<PropertyNode>();
    }
    List<PropertyNode> list = getAllProperties(names, cNode, cNode, true, includeFields, allProperties, false, false, true, false, allNames, false);
    list.addAll(superList);
    for (PropertyNode pNode : list) {
        String name = pNode.getName();
        if (shouldSkipUndefinedAware(name, excludes, includes, allNames))
            continue;
        FieldNode fNode = pNode.getField();
        if (!cNode.hasProperty(name) && fNode.getDeclaringClass() != null) {
            // it's really just a field
            elements.add(new ToStringElement(varX(fNode), name, canBeSelf(cNode, fNode.getType())));
        } else {
            Expression getter = getterThisX(cNode, pNode);
            elements.add(new ToStringElement(getter, name, canBeSelf(cNode, pNode.getType())));
        }
    }
    // append super if needed
    if (includeSuper) {
        // not through MOP to avoid infinite recursion
        elements.add(new ToStringElement(callSuperX(TO_STRING), "super", false));
    }
    if (includes != null) {
        Comparator<ToStringElement> includeComparator = Comparator.comparingInt(tse -> includes.indexOf(tse.name));
        elements.sort(includeComparator);
    }
    for (ToStringElement el : elements) {
        appendValue(body, result, first, el.value, el.name, includeNames, ignoreNulls, el.canBeSelf, pojo, delims);
    }
    // wrap up
    body.addStatement(appendS(result, constX(delims[1])));
    return toStringX(result);
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) ArrayList(java.util.ArrayList) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ToString(groovy.transform.ToString) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) Expression(org.codehaus.groovy.ast.expr.Expression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) HashSet(java.util.HashSet)

Example 79 with PropertyNode

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

the class AstBuilder method declareProperty.

private PropertyNode declareProperty(final GroovyParserRuleContext ctx, final ModifierManager modifierManager, final ClassNode variableType, final ClassNode classNode, final int i, final ASTNode startNode, final String fieldName, final int modifiers, final Expression initialValue) {
    PropertyNode propertyNode;
    FieldNode fieldNode = classNode.getDeclaredField(fieldName);
    if (fieldNode != null && !classNode.hasProperty(fieldName)) {
        if (fieldNode.hasInitialExpression() && initialValue != null) {
            throw createParsingFailedException("The split property definition named '" + fieldName + "' must not have an initial value for both the field and the property", ctx);
        }
        if (!fieldNode.getType().equals(variableType)) {
            throw createParsingFailedException("The split property definition named '" + fieldName + "' must not have different types for the field and the property", ctx);
        }
        classNode.getFields().remove(fieldNode);
        propertyNode = new PropertyNode(fieldNode, modifiers | Opcodes.ACC_PUBLIC, null, null);
        classNode.addProperty(propertyNode);
        if (initialValue != null) {
            fieldNode.setInitialValueExpression(initialValue);
        }
        modifierManager.attachAnnotations(propertyNode);
        propertyNode.addAnnotation(new AnnotationNode(ClassHelper.make(CompileStatic.class)));
        // expand properties early so AST transforms will be handled correctly
        PropertyExpander expander = new PropertyExpander(classNode);
        expander.visitProperty(propertyNode);
    } else {
        propertyNode = new PropertyNode(fieldName, modifiers | Opcodes.ACC_PUBLIC, variableType, classNode, initialValue, null, null);
        classNode.addProperty(propertyNode);
        fieldNode = propertyNode.getField();
        fieldNode.setModifiers(modifiers & ~Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE);
        fieldNode.setSynthetic(!classNode.isInterface());
        modifierManager.attachAnnotations(fieldNode);
        modifierManager.attachAnnotations(propertyNode);
        if (i == 0) {
            configureAST(fieldNode, ctx, initialValue);
        } else {
            configureAST(fieldNode, startNode, initialValue);
        }
    }
    groovydocManager.handle(fieldNode, ctx);
    groovydocManager.handle(propertyNode, ctx);
    if (i == 0) {
        configureAST(propertyNode, ctx, initialValue);
    } else {
        configureAST(propertyNode, startNode, initialValue);
    }
    return propertyNode;
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) PropertyNode(org.codehaus.groovy.ast.PropertyNode)

Example 80 with PropertyNode

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

the class AutoImplementASTTransformation method getAllCorrectedMethodsMap.

/**
 * Returns all methods including abstract super/interface methods but only
 * if not overridden by a concrete declared/inherited method.
 */
private static Map<String, MethodNode> getAllCorrectedMethodsMap(final ClassNode cNode) {
    Map<String, MethodNode> result = new HashMap<>();
    for (MethodNode mn : cNode.getMethods()) {
        result.put(methodDescriptorWithoutReturnType(mn), mn);
    }
    ClassNode next = cNode;
    while (true) {
        Map<String, ClassNode> genericsSpec = createGenericsSpec(next);
        if (next != cNode) {
            for (MethodNode mn : next.getMethods()) {
                MethodNode correctedMethod = correctToGenericsSpec(genericsSpec, mn);
                ClassNode correctedClass = correctToGenericsSpecRecurse(genericsSpec, next);
                MethodNode found = getDeclaredMethodCorrected(genericsSpec, correctedMethod, correctedClass);
                if (found != null) {
                    String td = methodDescriptorWithoutReturnType(found);
                    if (result.containsKey(td) && isWeakerCandidate(result.get(td), found))
                        continue;
                    result.put(td, found);
                }
            }
        }
        List<ClassNode> interfaces = new ArrayList<>();
        Collections.addAll(interfaces, next.getInterfaces());
        Map<String, ClassNode> updatedGenericsSpec = new HashMap<>(genericsSpec);
        while (!interfaces.isEmpty()) {
            ClassNode origInterface = interfaces.remove(0);
            // ignore java.lang.Object; also methods added by Verifier for GroovyObject are already good enough
            if (!isObjectType(origInterface) && !isGroovyObjectType(origInterface)) {
                updatedGenericsSpec = createGenericsSpec(origInterface, updatedGenericsSpec);
                ClassNode correctedInterface = correctToGenericsSpecRecurse(updatedGenericsSpec, origInterface);
                for (MethodNode nextMethod : correctedInterface.getMethods()) {
                    MethodNode correctedMethod = correctToGenericsSpec(updatedGenericsSpec, nextMethod);
                    MethodNode found = getDeclaredMethodCorrected(updatedGenericsSpec, correctedMethod, correctedInterface);
                    if (found != null) {
                        String td = methodDescriptorWithoutReturnType(found);
                        if (result.containsKey(td) && isWeakerCandidate(result.get(td), found))
                            continue;
                        result.put(td, found);
                    }
                }
                Collections.addAll(interfaces, correctedInterface.getInterfaces());
            }
        }
        ClassNode superClass = next.getUnresolvedSuperClass();
        if (superClass == null) {
            break;
        }
        next = correctToGenericsSpecRecurse(updatedGenericsSpec, superClass);
    }
    // GROOVY-9816: remove entries for to-be-generated property access and mutate methods
    for (ClassNode cn = cNode; cn != null && !isObjectType(cn); cn = cn.getSuperClass()) {
        for (PropertyNode pn : cn.getProperties()) {
            if (!pn.getField().isFinal()) {
                result.remove(pn.getSetterNameOrDefault() + ":" + pn.getType().getText() + ",");
            }
            if (!isPrimitiveBoolean(pn.getType())) {
                result.remove(pn.getGetterNameOrDefault() + ":");
            } else if (pn.getGetterName() != null) {
                result.remove(pn.getGetterName() + ":");
            } else {
                // getter generated only if no explicit isser and vice versa
                String isserName = "is" + capitalize(pn.getName());
                String getterName = getGetterName(pn.getName());
                if (!cNode.hasMethod(isserName, Parameter.EMPTY_ARRAY)) {
                    result.remove(getterName + ":");
                }
                if (!cNode.hasMethod(getterName, Parameter.EMPTY_ARRAY)) {
                    result.remove(isserName + ":");
                }
            }
        }
    }
    return result;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) MethodNode(org.codehaus.groovy.ast.MethodNode) HashMap(java.util.HashMap) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList)

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