Search in sources :

Example 81 with PropertyNode

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

the class EqualsAndHashCodeASTTransformation method calculateHashStatementsPOJO.

private static Statement calculateHashStatementsPOJO(ClassNode cNode, Expression hash, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes, boolean allNames, boolean allProperties) {
    final Set<String> names = new HashSet<>();
    final List<PropertyNode> pList = getAllProperties(names, cNode, true, false, allProperties, false, false, false);
    final List<FieldNode> fList = new ArrayList<>();
    if (includeFields) {
        fList.addAll(getInstanceNonPropertyFields(cNode));
    }
    final BlockStatement body = new BlockStatement();
    final ArgumentListExpression args = new ArgumentListExpression();
    for (PropertyNode pNode : pList) {
        if (shouldSkipUndefinedAware(pNode.getName(), excludes, includes, allNames))
            continue;
        args.addExpression(getterThisX(cNode, pNode));
    }
    for (FieldNode fNode : fList) {
        if (shouldSkipUndefinedAware(fNode.getName(), excludes, includes, allNames))
            continue;
        args.addExpression(varX(fNode));
    }
    if (callSuper) {
        args.addExpression(varX("super"));
    }
    Expression calcHash = callX(OBJECTS_TYPE, "hash", args);
    if (hash != null) {
        body.addStatement(assignS(hash, calcHash));
    } else {
        body.addStatement(returnS(calcHash));
    }
    return body;
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) Expression(org.codehaus.groovy.ast.expr.Expression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) HashSet(java.util.HashSet)

Example 82 with PropertyNode

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

the class EqualsAndHashCodeASTTransformation method calculateHashStatementsDefault.

private static Statement calculateHashStatementsDefault(ClassNode cNode, Expression hash, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes, boolean allNames, boolean allProperties) {
    final Set<String> names = new HashSet<>();
    final List<PropertyNode> pList = getAllProperties(names, cNode, true, false, allProperties, false, false, false);
    final List<FieldNode> fList = new ArrayList<>();
    if (includeFields) {
        fList.addAll(getInstanceNonPropertyFields(cNode));
    }
    final BlockStatement body = new BlockStatement();
    // def _result = HashCodeHelper.initHash()
    final Expression result = localVarX("_result");
    body.addStatement(declS(result, callX(HASHUTIL_TYPE, "initHash")));
    for (PropertyNode pNode : pList) {
        if (shouldSkipUndefinedAware(pNode.getName(), excludes, includes, allNames))
            continue;
        // _result = HashCodeHelper.updateHash(_result, getProperty()) // plus self-reference checking
        Expression getter = getterThisX(cNode, pNode);
        final Expression current = callX(HASHUTIL_TYPE, UPDATE_HASH, args(result, getter));
        body.addStatement(ifS(notIdenticalX(getter, varX("this")), assignS(result, current)));
    }
    for (FieldNode fNode : fList) {
        if (shouldSkipUndefinedAware(fNode.getName(), excludes, includes, allNames))
            continue;
        // _result = HashCodeHelper.updateHash(_result, field) // plus self-reference checking
        final Expression fieldExpr = varX(fNode);
        final Expression current = callX(HASHUTIL_TYPE, UPDATE_HASH, args(result, fieldExpr));
        body.addStatement(ifS(notIdenticalX(fieldExpr, varX("this")), assignS(result, current)));
    }
    if (callSuper) {
        // _result = HashCodeHelper.updateHash(_result, super.hashCode())
        final Expression current = callX(HASHUTIL_TYPE, UPDATE_HASH, args(result, callSuperX(HASH_CODE)));
        body.addStatement(assignS(result, current));
    }
    // $hash$code = _result
    if (hash != null) {
        body.addStatement(assignS(hash, result));
    } else {
        body.addStatement(returnS(result));
    }
    return body;
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) CastExpression(org.codehaus.groovy.ast.expr.CastExpression) Expression(org.codehaus.groovy.ast.expr.Expression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) HashSet(java.util.HashSet)

Example 83 with PropertyNode

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

the class JavaStubGenerator method printClassContents.

private void printClassContents(PrintWriter out, ClassNode classNode) {
    if (classNode instanceof InnerClassNode && ((InnerClassNode) classNode).isAnonymous()) {
        // if it is an anonymous inner class, don't generate the stub code for it.
        return;
    }
    try {
        Verifier verifier = new Verifier() {

            @Override
            public void visitClass(ClassNode node) {
                List<Statement> savedStatements = new ArrayList<>(node.getObjectInitializerStatements());
                super.visitClass(node);
                node.getObjectInitializerStatements().addAll(savedStatements);
                for (ClassNode trait : findTraits(node)) {
                    // GROOVY-9031: replace property type placeholder with resolved type from trait generics
                    Map<String, ClassNode> generics = trait.isUsingGenerics() ? createGenericsSpec(trait) : null;
                    for (PropertyNode traitProperty : trait.getProperties()) {
                        ClassNode traitPropertyType = traitProperty.getType();
                        traitProperty.setType(correctToGenericsSpecRecurse(generics, traitPropertyType));
                        super.visitProperty(traitProperty);
                        traitProperty.setType(traitPropertyType);
                    }
                }
            }

            @Override
            public void visitConstructor(ConstructorNode node) {
                Statement stmt = node.getCode();
                if (stmt != null) {
                    stmt.visit(new VerifierCodeVisitor(getClassNode()));
                }
            }

            @Override
            public void visitProperty(PropertyNode node) {
                // GROOVY-8233 skip static properties for traits since they don't make the interface
                if (!node.isStatic() || !Traits.isTrait(node.getDeclaringClass())) {
                    super.visitProperty(node);
                }
            }

            @Override
            public void addCovariantMethods(ClassNode cn) {
            }

            @Override
            protected void addInitialization(ClassNode node) {
            }

            @Override
            protected void addPropertyMethod(MethodNode method) {
                doAddMethod(method);
            }

            @Override
            protected void addReturnIfNeeded(MethodNode node) {
            }

            @Override
            protected MethodNode addMethod(ClassNode node, boolean shouldBeSynthetic, String name, int modifiers, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
                return doAddMethod(new MethodNode(name, modifiers, returnType, parameters, exceptions, code));
            }

            @Override
            protected void addConstructor(Parameter[] newParams, ConstructorNode ctor, Statement code, ClassNode node) {
                if (code instanceof ExpressionStatement) {
                    // GROOVY-4508
                    Statement temp = code;
                    code = new BlockStatement();
                    ((BlockStatement) code).addStatement(temp);
                }
                ConstructorNode ctrNode = new ConstructorNode(ctor.getModifiers(), newParams, ctor.getExceptions(), code);
                ctrNode.setDeclaringClass(node);
                constructors.add(ctrNode);
            }

            @Override
            protected void addDefaultParameters(DefaultArgsAction action, MethodNode method) {
                final Parameter[] parameters = method.getParameters();
                final Expression[] saved = new Expression[parameters.length];
                for (int i = 0; i < parameters.length; i++) {
                    if (parameters[i].hasInitialExpression())
                        saved[i] = parameters[i].getInitialExpression();
                }
                super.addDefaultParameters(action, method);
                for (int i = 0; i < parameters.length; i++) {
                    if (saved[i] != null)
                        parameters[i].setInitialExpression(saved[i]);
                }
            }

            private MethodNode doAddMethod(MethodNode method) {
                String sig = method.getTypeDescriptor();
                if (propertyMethodsWithSigs.containsKey(sig))
                    return method;
                propertyMethods.add(method);
                propertyMethodsWithSigs.put(sig, method);
                return method;
            }

            @Override
            protected void addDefaultConstructor(ClassNode node) {
            // not required for stub generation
            }

            @Override
            protected FinalVariableAnalyzer.VariableNotFinalCallback getFinalVariablesCallback() {
                return null;
            }
        };
        int origNumConstructors = classNode.getDeclaredConstructors().size();
        verifier.visitClass(classNode);
        // undo unwanted side-effect of verifier
        if (origNumConstructors == 0 && classNode.getDeclaredConstructors().size() == 1) {
            classNode.getDeclaredConstructors().clear();
        }
        boolean isInterface = isInterfaceOrTrait(classNode);
        boolean isEnum = classNode.isEnum();
        boolean isAnnotationDefinition = classNode.isAnnotationDefinition();
        printAnnotations(out, classNode);
        printModifiers(out, classNode.getModifiers() & ~(isInterface ? Opcodes.ACC_ABSTRACT : 0) & ~(isEnum ? Opcodes.ACC_FINAL | Opcodes.ACC_ABSTRACT : 0));
        if (isInterface) {
            if (isAnnotationDefinition) {
                out.print("@");
            }
            out.print("interface ");
        } else if (isEnum) {
            out.print("enum ");
        } else {
            out.print("class ");
        }
        String className = classNode.getNameWithoutPackage();
        if (classNode instanceof InnerClassNode)
            className = className.substring(className.lastIndexOf('$') + 1);
        out.println(className);
        printGenericsBounds(out, classNode, true);
        ClassNode superClass = classNode.getUnresolvedSuperClass(false);
        if (!isInterface && !isEnum) {
            out.print("  extends ");
            printType(out, superClass);
        }
        ClassNode[] interfaces = classNode.getInterfaces();
        if (interfaces != null && interfaces.length > 0 && !isAnnotationDefinition) {
            if (isInterface) {
                out.println("  extends");
            } else {
                out.println("  implements");
            }
            for (int i = 0; i < interfaces.length - 1; ++i) {
                out.print("    ");
                printType(out, interfaces[i]);
                out.print(",");
            }
            out.print("    ");
            printType(out, interfaces[interfaces.length - 1]);
        }
        out.println(" {");
        printFields(out, classNode);
        printMethods(out, classNode, isEnum);
        for (Iterator<InnerClassNode> inner = classNode.getInnerClasses(); inner.hasNext(); ) {
            // GROOVY-4004: Clear the methods from the outer class so that they don't get duplicated in inner ones
            propertyMethods.clear();
            propertyMethodsWithSigs.clear();
            constructors.clear();
            printClassContents(out, inner.next());
        }
        out.println("}");
    } finally {
        propertyMethods.clear();
        propertyMethodsWithSigs.clear();
        constructors.clear();
    }
}
Also used : DecompiledClassNode(org.codehaus.groovy.ast.decompiled.DecompiledClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Statement(org.codehaus.groovy.ast.stmt.Statement) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) ArrayList(java.util.ArrayList) BlockStatement(org.codehaus.groovy.ast.stmt.BlockStatement) Verifier(org.codehaus.groovy.classgen.Verifier) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) VerifierCodeVisitor(org.codehaus.groovy.classgen.VerifierCodeVisitor) MethodNode(org.codehaus.groovy.ast.MethodNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) ConstructorNode(org.codehaus.groovy.ast.ConstructorNode) ExpressionStatement(org.codehaus.groovy.ast.stmt.ExpressionStatement) Parameter(org.codehaus.groovy.ast.Parameter) FinalVariableAnalyzer(org.codehaus.groovy.classgen.FinalVariableAnalyzer)

Example 84 with PropertyNode

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

the class StaticTypesBinaryExpressionMultiTypeDispatcher method makeSetProperty.

private boolean makeSetProperty(final Expression receiver, final Expression message, final Expression arguments, final boolean safe, final boolean spreadSafe, final boolean implicitThis, final boolean isAttribute) {
    ClassNode receiverType = controller.getTypeChooser().resolveType(receiver, controller.getClassNode());
    String property = message.getText();
    boolean isThisExpression = isThisExpression(receiver);
    if (isAttribute || (isThisExpression && receiverType.getDeclaredField(property) != null)) {
        ClassNode current = receiverType;
        FieldNode fn = null;
        while (fn == null && current != null) {
            fn = current.getDeclaredField(property);
            if (fn == null) {
                current = current.getSuperClass();
            }
        }
        if (fn != null && receiverType != current && !fn.isPublic()) {
            // check that direct access is allowed
            if (!fn.isProtected()) {
                return false;
            }
            if (!Objects.equals(receiverType.getPackageName(), current.getPackageName())) {
                return false;
            }
            if (!fn.isStatic()) {
                receiver.visit(controller.getAcg());
            }
            arguments.visit(controller.getAcg());
            OperandStack operandStack = controller.getOperandStack();
            operandStack.doGroovyCast(fn.getOriginType());
            MethodVisitor mv = controller.getMethodVisitor();
            mv.visitFieldInsn(fn.isStatic() ? PUTSTATIC : PUTFIELD, BytecodeHelper.getClassInternalName(fn.getOwner()), property, BytecodeHelper.getTypeDescription(fn.getOriginType()));
            operandStack.remove(fn.isStatic() ? 1 : 2);
            return true;
        }
    }
    if (!isAttribute) {
        String setter = getSetterName(property);
        MethodNode setterMethod = receiverType.getSetterMethod(setter, false);
        ClassNode declaringClass = setterMethod != null ? setterMethod.getDeclaringClass() : null;
        if (isThisExpression && declaringClass != null && declaringClass.equals(controller.getClassNode())) {
            // this.x = ... shouldn't use a setter if in the same class
            setterMethod = null;
        } else if (setterMethod == null) {
            PropertyNode propertyNode = receiverType.getProperty(property);
            if (propertyNode != null) {
                if (!Modifier.isFinal(propertyNode.getModifiers())) {
                    setterMethod = new MethodNode(setter, ACC_PUBLIC, ClassHelper.VOID_TYPE, new Parameter[] { new Parameter(propertyNode.getOriginType(), "value") }, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
                    setterMethod.setDeclaringClass(receiverType);
                }
            }
        }
        if (setterMethod != null) {
            Expression call = StaticPropertyAccessHelper.transformToSetterCall(receiver, setterMethod, arguments, implicitThis, safe, spreadSafe, // to be replaced with a proper test whether a return value should be used or not
            true, message);
            call.visit(controller.getAcg());
            return true;
        }
        if (isThisExpression && !controller.isInGeneratedFunction()) {
            receiverType = controller.getClassNode();
        }
        if (makeSetPrivateFieldWithBridgeMethod(receiver, receiverType, property, arguments, safe, spreadSafe, implicitThis)) {
            return true;
        }
    }
    return false;
}
Also used : OperandStack(org.codehaus.groovy.classgen.asm.OperandStack) ClassNode(org.codehaus.groovy.ast.ClassNode) FieldNode(org.codehaus.groovy.ast.FieldNode) MethodNode(org.codehaus.groovy.ast.MethodNode) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ExpressionUtils.isThisExpression(org.apache.groovy.ast.tools.ExpressionUtils.isThisExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MethodReferenceExpression(org.codehaus.groovy.ast.expr.MethodReferenceExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) LambdaExpression(org.codehaus.groovy.ast.expr.LambdaExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) AttributeExpression(org.codehaus.groovy.ast.expr.AttributeExpression) PropertyNode(org.codehaus.groovy.ast.PropertyNode) Parameter(org.codehaus.groovy.ast.Parameter) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 85 with PropertyNode

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

the class GeneralUtils method getAllProperties.

public static List<PropertyNode> getAllProperties(final Set<String> names, final ClassNode origType, final ClassNode cNode, final boolean includeProperties, final boolean includeFields, final boolean includePseudoGetters, final boolean includePseudoSetters, final boolean traverseSuperClasses, final boolean skipReadonly, final boolean reverse, final boolean allNames, final boolean includeStatic) {
    List<PropertyNode> result = new ArrayList<>();
    if (!(isObjectType(cNode)) && traverseSuperClasses && !reverse) {
        result.addAll(getAllProperties(names, origType, cNode.getSuperClass(), includeProperties, includeFields, includePseudoGetters, includePseudoSetters, true, skipReadonly));
    }
    if (includeProperties) {
        for (PropertyNode pNode : cNode.getProperties()) {
            if ((!pNode.isStatic() || includeStatic) && !names.contains(pNode.getName())) {
                result.add(pNode);
                names.add(pNode.getName());
            }
        }
        if (includePseudoGetters || includePseudoSetters) {
            BeanUtils.addPseudoProperties(origType, cNode, result, names, includeStatic, includePseudoGetters, includePseudoSetters);
        }
    }
    if (includeFields) {
        for (FieldNode fNode : cNode.getFields()) {
            if ((fNode.isStatic() && !includeStatic) || fNode.isSynthetic() || cNode.getProperty(fNode.getName()) != null || names.contains(fNode.getName())) {
                continue;
            }
            // internal field
            if (fNode.getName().contains("$") && !allNames) {
                continue;
            }
            if (fNode.isPrivate() && !cNode.equals(origType)) {
                continue;
            }
            if (fNode.isFinal() && fNode.getInitialExpression() != null && skipReadonly) {
                continue;
            }
            result.add(new PropertyNode(fNode, fNode.getModifiers(), null, null));
            names.add(fNode.getName());
        }
    }
    if (!(isObjectType(cNode)) && traverseSuperClasses && reverse) {
        result.addAll(getAllProperties(names, origType, cNode.getSuperClass(), includeProperties, includeFields, includePseudoGetters, includePseudoSetters, true, skipReadonly));
    }
    return result;
}
Also used : FieldNode(org.codehaus.groovy.ast.FieldNode) 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