Java Code Examples for org.codehaus.groovy.ast.stmt.BlockStatement#addStatement()

The following examples show how to use org.codehaus.groovy.ast.stmt.BlockStatement#addStatement() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ReturnAdder.java    From groovy with Apache License 2.0 6 votes vote down vote up
private Statement adjustSwitchCaseCode(final Statement statement, final VariableScope scope, final boolean defaultCase) {
    if (statement instanceof BlockStatement) {
        List<Statement> statements = ((BlockStatement) statement).getStatements();
        if (!statements.isEmpty()) {
            int lastIndex = statements.size() - 1;
            Statement last = statements.get(lastIndex);
            if (last instanceof BreakStatement) {
                if (doAdd) {
                    statements.remove(lastIndex);
                    return addReturnsIfNeeded(statement, scope);
                } else {
                    BlockStatement newBlock = new BlockStatement();
                    for (int i = 0; i < lastIndex; i += 1) {
                        newBlock.addStatement(statements.get(i));
                    }
                    return addReturnsIfNeeded(newBlock, scope);
                }
            } else if (defaultCase) {
                return addReturnsIfNeeded(statement, scope);
            }
        }
    }
    return statement;
}
 
Example 2
Source File: InnerClassVisitorHelper.java    From groovy with Apache License 2.0 6 votes vote down vote up
protected static void setPropertySetterDispatcher(BlockStatement block, Expression thiz, Parameter[] parameters) {
    List<ConstantExpression> gStringStrings = new ArrayList<ConstantExpression>();
    gStringStrings.add(new ConstantExpression(""));
    gStringStrings.add(new ConstantExpression(""));
    List<Expression> gStringValues = new ArrayList<Expression>();
    gStringValues.add(new VariableExpression(parameters[0]));
    block.addStatement(
            new ExpressionStatement(
                    new BinaryExpression(
                            new PropertyExpression(
                                    thiz,
                                    new GStringExpression("$name", gStringStrings, gStringValues)
                            ),
                            Token.newSymbol(Types.ASSIGN, -1, -1),
                            new VariableExpression(parameters[1])
                    )
            )
    );
}
 
Example 3
Source File: InnerClassVisitorHelper.java    From groovy with Apache License 2.0 6 votes vote down vote up
protected static void setMethodDispatcherCode(BlockStatement block, Expression thiz, Parameter[] parameters) {
    List<ConstantExpression> gStringStrings = new ArrayList<ConstantExpression>();
    gStringStrings.add(new ConstantExpression(""));
    gStringStrings.add(new ConstantExpression(""));
    List<Expression> gStringValues = new ArrayList<Expression>();
    gStringValues.add(new VariableExpression(parameters[0]));
    block.addStatement(
            new ReturnStatement(
                    new MethodCallExpression(
                            thiz,
                            new GStringExpression("$name", gStringStrings, gStringValues),
                            new ArgumentListExpression(
                                    new SpreadExpression(new VariableExpression(parameters[1]))
                            )
                    )
            )
    );
}
 
Example 4
Source File: NamedVariantASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
private boolean processExplicitNamedParam(final MethodNode mNode, final Parameter mapParam, final BlockStatement inner, final ArgumentListExpression args, final List<String> propNames, final Parameter fromParam) {
    AnnotationNode namedParam = fromParam.getAnnotations(NAMED_PARAM_TYPE).get(0);
    boolean required = memberHasValue(namedParam, "required", true);
    if (getMemberStringValue(namedParam, "value") == null) {
        namedParam.addMember("value", constX(fromParam.getName()));
    }
    String name = getMemberStringValue(namedParam, "value");
    if (getMemberValue(namedParam, "type") == null) {
        namedParam.addMember("type", classX(fromParam.getType()));
    }
    if (hasDuplicates(mNode, propNames, name)) return false;
    // TODO: Check specified type is assignable from declared param type?
    //ClassNode type = getMemberClassValue(namedParam, "type");
    if (required) {
        if (fromParam.hasInitialExpression()) {
            addError("Error during " + NAMED_VARIANT + " processing. A required parameter can't have an initial value.", mNode);
            return false;
        }
        inner.addStatement(new AssertStatement(boolX(callX(varX(mapParam), "containsKey", args(constX(name)))),
                plusX(constX("Missing required named argument '" + name + "'. Keys found: "), callX(varX(mapParam), "keySet"))));
    }
    args.addExpression(propX(varX(mapParam), name));
    mapParam.addAnnotation(namedParam);
    fromParam.getAnnotations().remove(namedParam);
    return true;
}
 
Example 5
Source File: VetoableASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
private void createListenerSetter(SourceUnit source, boolean bindable, ClassNode declaringClass, PropertyNode propertyNode) {
    if (bindable && needsPropertyChangeSupport(declaringClass, source)) {
        addPropertyChangeSupport(declaringClass);
    }
    if (needsVetoableChangeSupport(declaringClass, source)) {
        addVetoableChangeSupport(declaringClass);
    }
    String setterName = getSetterName(propertyNode.getName());
    if (declaringClass.getMethods(setterName).isEmpty()) {
        Expression fieldExpression = fieldX(propertyNode.getField());
        BlockStatement setterBlock = new BlockStatement();
        setterBlock.addStatement(createConstrainedStatement(propertyNode, fieldExpression));
        if (bindable) {
            setterBlock.addStatement(createBindableStatement(propertyNode, fieldExpression));
        } else {
            setterBlock.addStatement(createSetStatement(fieldExpression));
        }

        // create method void <setter>(<type> fieldName)
        createSetterMethod(declaringClass, propertyNode, setterName, setterBlock);
    } else {
        wrapSetterMethod(declaringClass, bindable, propertyNode.getName());
    }
}
 
Example 6
Source File: LazyASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
private static void addHolderClassIdiomBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) {
    final ClassNode declaringClass = fieldNode.getDeclaringClass();
    final ClassNode fieldType = fieldNode.getType();
    final int visibility = ACC_PRIVATE | ACC_STATIC;
    final String fullName = declaringClass.getName() + "$" + fieldType.getNameWithoutPackage() + "Holder_" + fieldNode.getName().substring(1);
    final InnerClassNode holderClass = new InnerClassNode(declaringClass, fullName, visibility, ClassHelper.OBJECT_TYPE);
    final String innerFieldName = "INSTANCE";

    // we have two options:
    // (1) embed initExpr within holder class but redirect field access/method calls to declaring class members
    // (2) keep initExpr within a declaring class method that is only called by the holder class
    // currently we have gone with (2) for simplicity with only a slight memory footprint increase in the declaring class
    final String initializeMethodName = (fullName + "_initExpr").replace('.', '_');
    addGeneratedMethod(declaringClass, initializeMethodName, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, fieldType,
            Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, returnS(initExpr));
    holderClass.addField(innerFieldName, ACC_PRIVATE | ACC_STATIC | ACC_FINAL, fieldType,
            callX(declaringClass, initializeMethodName));

    final Expression innerField = propX(classX(holderClass), innerFieldName);
    declaringClass.getModule().addClass(holderClass);
    body.addStatement(returnS(innerField));
}
 
Example 7
Source File: ClosureWriter.java    From groovy with Apache License 2.0 6 votes vote down vote up
protected BlockStatement createBlockStatementForConstructor(final ClosureExpression expression, final ClassNode outerClass, final ClassNode thisClassNode) {
    BlockStatement block = new BlockStatement();
    // this block does not get a source position, because we don't
    // want this synthetic constructor to show up in corbertura reports
    VariableExpression outer = new VariableExpression(OUTER_INSTANCE, outerClass);
    outer.setSourcePosition(expression);
    block.getVariableScope().putReferencedLocalVariable(outer);
    VariableExpression thisObject = new VariableExpression(THIS_OBJECT, thisClassNode);
    thisObject.setSourcePosition(expression);
    block.getVariableScope().putReferencedLocalVariable(thisObject);
    TupleExpression conArgs = new TupleExpression(outer, thisObject);
    block.addStatement(
            new ExpressionStatement(
                    new ConstructorCallExpression(
                            ClassNode.SUPER,
                            conArgs)));
    return block;
}
 
Example 8
Source File: ExternalStrategy.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static MethodNode createBuildMethod(BuilderASTTransformation transform, AnnotationNode anno, ClassNode sourceClass, List<PropertyInfo> fields) {
    String buildMethodName = transform.getMemberStringValue(anno, "buildMethodName", "build");
    final BlockStatement body = new BlockStatement();
    Expression sourceClassInstance = initializeInstance(sourceClass, fields, body);
    body.addStatement(returnS(sourceClassInstance));
    return new MethodNode(buildMethodName, ACC_PUBLIC, sourceClass, NO_PARAMS, NO_EXCEPTIONS, body);
}
 
Example 9
Source File: EqualsAndHashCodeASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
public static void createHashCode(ClassNode cNode, boolean cacheResult, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes, boolean allNames, boolean allProperties) {
    // make a public method if none exists otherwise try a private method with leading underscore
    boolean hasExistingHashCode = hasDeclaredMethod(cNode, "hashCode", 0);
    if (hasExistingHashCode && hasDeclaredMethod(cNode, "_hashCode", 0)) return;

    final BlockStatement body = new BlockStatement();
    // TODO use pList and fList
    if (cacheResult) {
        final FieldNode hashField = cNode.addField("$hash$code", ACC_PRIVATE | ACC_SYNTHETIC, ClassHelper.int_TYPE, null);
        final Expression hash = varX(hashField);
        body.addStatement(ifS(
                isZeroX(hash),
                calculateHashStatements(cNode, hash, includeFields, callSuper, excludes, includes, allNames, allProperties)
        ));
        body.addStatement(returnS(hash));
    } else {
        body.addStatement(calculateHashStatements(cNode, null, includeFields, callSuper, excludes, includes, allNames, allProperties));
    }

    addGeneratedMethod(cNode,
            hasExistingHashCode ? "_hashCode" : "hashCode",
            hasExistingHashCode ? ACC_PRIVATE : ACC_PUBLIC,
            ClassHelper.int_TYPE,
            Parameter.EMPTY_ARRAY,
            ClassNode.EMPTY_ARRAY,
            body);
}
 
Example 10
Source File: TupleListTest.java    From groovy with Apache License 2.0 5 votes vote down vote up
protected void assertIterate(String methodName, Expression listExpression) throws Exception {
    ClassNode classNode = new ClassNode("Foo", ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
    classNode.addConstructor(new ConstructorNode(ACC_PUBLIC, null));
    classNode.addProperty(new PropertyNode("bar", ACC_PUBLIC, ClassHelper.STRING_TYPE, classNode, null, null, null));

    Statement loopStatement = createPrintlnStatement(new VariableExpression("i"));

    BlockStatement block = new BlockStatement();
    block.addStatement(new ExpressionStatement(new DeclarationExpression(new VariableExpression("list"), Token.newSymbol("=", 0, 0), listExpression)));
    block.addStatement(new ForStatement(new Parameter(ClassHelper.DYNAMIC_TYPE, "i"), new VariableExpression("list"), loopStatement));
    classNode.addMethod(new MethodNode(methodName, ACC_PUBLIC, ClassHelper.VOID_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, block));

    Class fooClass = loadClass(classNode);
    assertTrue("Loaded a new class", fooClass != null);

    Object bean = fooClass.getDeclaredConstructor().newInstance();
    assertTrue("Managed to create bean", bean != null);

    System.out.println("################ Now about to invoke method");

    try {
        InvokerHelper.invokeMethod(bean, methodName, null);
    }
    catch (InvokerInvocationException e) {
        System.out.println("Caught: " + e.getCause());
        e.getCause().printStackTrace();
        fail("Should not have thrown an exception");
    }
    System.out.println("################ Done");
}
 
Example 11
Source File: IndexedPropertyASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static void addGetter(FieldNode fNode, ClassNode componentType) {
    ClassNode cNode = fNode.getDeclaringClass();
    BlockStatement body = new BlockStatement();
    Parameter[] params = new Parameter[1];
    params[0] = new Parameter(ClassHelper.int_TYPE, "index");
    body.addStatement(stmt(indexX(varX(fNode), varX(params[0]))));
    addGeneratedMethod(cNode, makeName(fNode, "get"), getModifiers(fNode), componentType, params, null, body);
}
 
Example 12
Source File: ExternalStrategy.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static Expression initializeInstance(ClassNode sourceClass, List<PropertyInfo> props, BlockStatement body) {
    Expression instance = localVarX("_the" + sourceClass.getNameWithoutPackage(), sourceClass);
    body.addStatement(declS(instance, ctorX(sourceClass)));
    for (PropertyInfo prop : props) {
        body.addStatement(stmt(assignX(propX(instance, prop.getName()), varX(prop.getName().equals("class") ? "clazz" : prop.getName(), newClass(prop.getType())))));
    }
    return instance;
}
 
Example 13
Source File: LazyASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static void createSoftGetter(FieldNode fieldNode, Expression initExpr, ClassNode type) {
    final BlockStatement body = new BlockStatement();
    final Expression fieldExpr = varX(fieldNode);
    final Expression resExpr = localVarX("_result", type);
    final MethodCallExpression callExpression = callX(fieldExpr, "get");
    callExpression.setSafe(true);
    body.addStatement(declS(resExpr, callExpression));

    final Statement mainIf = ifElseS(notNullX(resExpr), stmt(resExpr), block(
            assignS(resExpr, initExpr),
            assignS(fieldExpr, ctorX(SOFT_REF, resExpr)),
            stmt(resExpr)));

    if (fieldNode.isVolatile()) {
        body.addStatement(ifElseS(
                notNullX(resExpr),
                stmt(resExpr),
                new SynchronizedStatement(syncTarget(fieldNode), block(
                        assignS(resExpr, callExpression),
                        mainIf)
                )
        ));
    } else {
        body.addStatement(mainIf);
    }
    addMethod(fieldNode, body, type);
}
 
Example 14
Source File: SingletonASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private void createField(ClassNode classNode, String propertyName, boolean isLazy, boolean isStrict) {
    int modifiers = isLazy ? ACC_PRIVATE | ACC_STATIC | ACC_VOLATILE : ACC_PUBLIC | ACC_FINAL | ACC_STATIC;
    Expression initialValue = isLazy ? null : ctorX(classNode);
    final FieldNode fieldNode = classNode.addField(propertyName, modifiers, newClass(classNode), initialValue);
    createConstructor(classNode, fieldNode, propertyName, isStrict);
    final BlockStatement body = new BlockStatement();
    body.addStatement(isLazy ? lazyBody(classNode, fieldNode) : nonLazyBody(fieldNode));
    addGeneratedMethod(classNode, getGetterName(propertyName), ACC_STATIC | ACC_PUBLIC, newClass(classNode), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body);
}
 
Example 15
Source File: AutoCloneASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static void addSimpleCloneHelperMethod(ClassNode cNode, List<FieldNode> fieldNodes, List<String> excludes) {
    Parameter methodParam = new Parameter(GenericsUtils.nonGeneric(cNode), "other");
    final Expression other = varX(methodParam);
    boolean hasParent = cNode.getSuperClass() != ClassHelper.OBJECT_TYPE;
    BlockStatement methodBody = new BlockStatement();
    if (hasParent) {
        methodBody.addStatement(stmt(callSuperX("cloneOrCopyMembers", args(other))));
    }
    for (FieldNode fieldNode : fieldNodes) {
        String name = fieldNode.getName();
        if (excludes != null && excludes.contains(name)) continue;
        ClassNode fieldType = fieldNode.getType();
        Expression direct = propX(varX("this"), name);
        Expression to = propX(other, name);
        Statement assignDirect = assignS(to, direct);
        Statement assignCloned = assignS(to, castX(fieldType, callCloneDirectX(direct)));
        Statement assignClonedDynamic = assignS(to, castX(fieldType, callCloneDynamicX(direct)));
        if (isCloneableType(fieldType)) {
            methodBody.addStatement(assignCloned);
        } else if (!possiblyCloneable(fieldType)) {
            methodBody.addStatement(assignDirect);
        } else {
            methodBody.addStatement(ifElseS(isInstanceOfX(direct, CLONEABLE_TYPE), assignClonedDynamic, assignDirect));
        }
    }
    ClassNode[] exceptions = {make(CloneNotSupportedException.class)};
    addGeneratedMethod(cNode, "cloneOrCopyMembers", ACC_PROTECTED, ClassHelper.VOID_TYPE, params(methodParam), exceptions, methodBody);
}
 
Example 16
Source File: LazyASTTransformation.java    From groovy with Apache License 2.0 4 votes vote down vote up
private static void addNonThreadSafeBody(BlockStatement body, FieldNode fieldNode, Expression initExpr) {
    final Expression fieldExpr = varX(fieldNode);
    body.addStatement(ifElseS(notNullX(fieldExpr), stmt(fieldExpr), assignS(fieldExpr, initExpr)));
}
 
Example 17
Source File: MemoizedASTTransformation.java    From groovy with Apache License 2.0 4 votes vote down vote up
public void visit(ASTNode[] nodes, final SourceUnit source) {
    init(nodes, source);
    AnnotationNode annotationNode = (AnnotationNode) nodes[0];
    AnnotatedNode annotatedNode = (AnnotatedNode) nodes[1];
    if (MY_TYPE.equals(annotationNode.getClassNode()) && annotatedNode instanceof MethodNode) {
        MethodNode methodNode = (MethodNode) annotatedNode;
        if (methodNode.isAbstract()) {
            addError("Annotation " + MY_TYPE_NAME + " cannot be used for abstract methods.", methodNode);
            return;
        }
        if (methodNode.isVoidMethod()) {
            addError("Annotation " + MY_TYPE_NAME + " cannot be used for void methods.", methodNode);
            return;
        }

        ClassNode ownerClassNode = methodNode.getDeclaringClass();
        MethodNode delegatingMethod = buildDelegatingMethod(methodNode, ownerClassNode);
        addGeneratedMethod(ownerClassNode, delegatingMethod);

        int modifiers = FieldNode.ACC_PRIVATE | FieldNode.ACC_FINAL;
        if (methodNode.isStatic()) {
            modifiers = modifiers | FieldNode.ACC_STATIC;
        }

        int protectedCacheSize = getMemberIntValue(annotationNode, PROTECTED_CACHE_SIZE_NAME);
        int maxCacheSize = getMemberIntValue(annotationNode, MAX_CACHE_SIZE_NAME);
        MethodCallExpression memoizeClosureCallExpression =
                buildMemoizeClosureCallExpression(delegatingMethod, protectedCacheSize, maxCacheSize);

        String memoizedClosureFieldName = buildUniqueName(ownerClassNode, CLOSURE_LABEL, methodNode);
        FieldNode memoizedClosureField = new FieldNode(memoizedClosureFieldName, modifiers,
                newClass(ClassHelper.CLOSURE_TYPE), null, memoizeClosureCallExpression);
        ownerClassNode.addField(memoizedClosureField);

        BlockStatement newCode = new BlockStatement();
        MethodCallExpression closureCallExpression = callX(
                fieldX(memoizedClosureField), CLOSURE_CALL_METHOD_NAME, args(methodNode.getParameters()));
        closureCallExpression.setImplicitThis(false);
        newCode.addStatement(returnS(closureCallExpression));
        methodNode.setCode(newCode);
        VariableScopeVisitor visitor = new VariableScopeVisitor(source, ownerClassNode instanceof InnerClassNode);
        if (ownerClassNode instanceof InnerClassNode) {
            visitor.visitClass(((InnerClassNode) ownerClassNode).getOuterMostClass());
        } else {
            visitor.visitClass(ownerClassNode);
        }
    }
}
 
Example 18
Source File: ToStringASTTransformation.java    From groovy with Apache License 2.0 4 votes vote down vote up
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) {
    // def _result = new StringBuilder()
    final Expression result = localVarX("_result");
    body.addStatement(declS(result, ctorX(STRINGBUILDER_TYPE)));
    List<ToStringElement> elements = new ArrayList<ToStringElement>();

    // 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 + "(")));

    Set<String> names = new HashSet<String>();
    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("toString"), "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);
    }

    // wrap up
    body.addStatement(appendS(result, constX(")")));
    MethodCallExpression toString = callX(result, "toString");
    toString.setImplicitThis(false);
    return toString;
}
 
Example 19
Source File: DefaultStrategy.java    From groovy with Apache License 2.0 4 votes vote down vote up
private static MethodNode createBuildMethod(AnnotationNode anno, ClassNode buildee, List<PropertyInfo> props) {
    String buildMethodName = getMemberStringValue(anno, "buildMethodName", "build");
    final BlockStatement body = new BlockStatement();
    body.addStatement(returnS(initializeInstance(buildee, props, body)));
    return new MethodNode(buildMethodName, ACC_PUBLIC, newClass(buildee), NO_PARAMS, NO_EXCEPTIONS, body);
}
 
Example 20
Source File: EqualsAndHashCodeASTTransformation.java    From groovy with Apache License 2.0 4 votes vote down vote up
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes, boolean allNames, boolean allProperties) {
    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 = localVarX("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))));
    }

    final Set<String> names = new HashSet<String>();
    final List<PropertyNode> pList = getAllProperties(names, cNode, true, includeFields, allProperties, false, false, false);
    for (PropertyNode pNode : pList) {
        if (shouldSkipUndefinedAware(pNode.getName(), excludes, includes, allNames)) continue;
        boolean canBeSelf = StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(
                pNode.getOriginType(), cNode
        );
        if (!canBeSelf) {
            body.addStatement(ifS(notX(hasEqualPropertyX(otherTyped.getOriginType(), 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(otherTyped.getOriginType(), pNode, otherTyped)), returnS(constX(Boolean.FALSE, true))))
                            )
                    )
            );
        }
    }
    List<FieldNode> fList = new ArrayList<FieldNode>();
    if (includeFields) {
        fList.addAll(getInstanceNonPropertyFields(cNode));
    }
    for (FieldNode fNode : fList) {
        if (shouldSkipUndefinedAware(fNode.getName(), excludes, includes, allNames)) 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)));

    MethodNode equal = addGeneratedMethod(cNode,
            hasExistingEquals ? "_equals" : "equals",
            hasExistingEquals ? ACC_PRIVATE : ACC_PUBLIC,
            ClassHelper.boolean_TYPE,
            params(param(OBJECT_TYPE, other.getName())),
            ClassNode.EMPTY_ARRAY,
            body);
    // don't null check this: prefer false to IllegalArgumentException
    NullCheckASTTransformation.markAsProcessed(equal);
}