org.codehaus.groovy.ast.PropertyNode Java Examples

The following examples show how to use org.codehaus.groovy.ast.PropertyNode. 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: BindableASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
private void addListenerToClass(SourceUnit source, ClassNode classNode) {
    if (needsPropertyChangeSupport(classNode, source)) {
        addPropertyChangeSupport(classNode);
    }
    for (PropertyNode propertyNode : classNode.getProperties()) {
        FieldNode field = propertyNode.getField();
        // look to see if per-field handlers will catch this one...
        if (hasBindableAnnotation(field)
            || ((field.getModifiers() & Opcodes.ACC_FINAL) != 0)
            || field.isStatic()
            || VetoableASTTransformation.hasVetoableAnnotation(field))
        {
            // explicitly labeled properties are already handled,
            // don't transform final properties
            // don't transform static properties
            // VetoableASTTransformation will handle both @Bindable and @Vetoable
            continue;
        }
        createListenerSetter(classNode, propertyNode);
    }
}
 
Example #2
Source File: ImmutablePropertyHandler.java    From groovy with Apache License 2.0 6 votes vote down vote up
protected Statement createConstructorStatement(AbstractASTTransformation xform, ClassNode cNode, PropertyNode pNode, Parameter namedArgsMap) {
    final List<String> knownImmutableClasses = ImmutablePropertyUtils.getKnownImmutableClasses(xform, cNode);
    final List<String> knownImmutables = ImmutablePropertyUtils.getKnownImmutables(xform, cNode);
    FieldNode fNode = pNode.getField();
    final ClassNode fType = fNode.getType();
    Statement statement;
    boolean shouldNullCheck = NullCheckASTTransformation.hasIncludeGenerated(cNode);
    if (ImmutablePropertyUtils.isKnownImmutableType(fType, knownImmutableClasses) || isKnownImmutable(pNode.getName(), knownImmutables)) {
        statement = createConstructorStatementDefault(fNode, namedArgsMap, shouldNullCheck);
    } else if (fType.isArray() || implementsCloneable(fType)) {
        statement = createConstructorStatementArrayOrCloneable(fNode, namedArgsMap, shouldNullCheck);
    } else if (derivesFromDate(fType)) {
        statement = createConstructorStatementDate(fNode, namedArgsMap, shouldNullCheck);
    } else if (isOrImplements(fType, COLLECTION_TYPE) || fType.isDerivedFrom(COLLECTION_TYPE) || isOrImplements(fType, MAP_TYPE) || fType.isDerivedFrom(MAP_TYPE)) {
        statement = createConstructorStatementCollection(fNode, namedArgsMap, shouldNullCheck);
    } else if (fType.isResolved()) {
        xform.addError(ImmutablePropertyUtils.createErrorMessage(cNode.getName(), fNode.getName(), fType.getName(), "compiling"), fNode);
        statement = EmptyStatement.INSTANCE;
    } else {
        statement = createConstructorStatementGuarded(fNode, namedArgsMap, knownImmutables, knownImmutableClasses, shouldNullCheck);
    }
    return statement;
}
 
Example #3
Source File: RenameProvider.java    From groovy-language-server with Apache License 2.0 6 votes vote down vote up
private TextEdit createTextEditToRenamePropertyNode(PropertyNode propNode, String newName, String text,
		Range range) {
	// the AST doesn't give us access to the name location, so we
	// need to find it manually
	Pattern propPattern = Pattern.compile("\\b" + propNode.getName() + "\\b");
	Matcher propMatcher = propPattern.matcher(text);
	if (!propMatcher.find()) {
		// couldn't find the name!
		return null;
	}

	Position start = range.getStart();
	Position end = range.getEnd();
	end.setCharacter(start.getCharacter() + propMatcher.end());
	start.setCharacter(start.getCharacter() + propMatcher.start());

	TextEdit textEdit = new TextEdit();
	textEdit.setRange(range);
	textEdit.setNewText(newName);
	return textEdit;
}
 
Example #4
Source File: ImmutablePropertyHandler.java    From groovy with Apache License 2.0 6 votes vote down vote up
@Override
public Statement createPropGetter(PropertyNode pNode) {
    FieldNode fNode = pNode.getField();
    BlockStatement body = new BlockStatement();
    final ClassNode fieldType = fNode.getType();
    final Statement statement;
    if (fieldType.isArray() || implementsCloneable(fieldType)) {
        statement = createGetterBodyArrayOrCloneable(fNode);
    } else if (derivesFromDate(fieldType)) {
        statement = createGetterBodyDate(fNode);
    } else {
        statement = createGetterBodyDefault(fNode);
    }
    body.addStatement(statement);
    return body;
}
 
Example #5
Source File: BeanUtils.java    From groovy with Apache License 2.0 6 votes vote down vote up
private static List<PropertyNode> getAllProperties(ClassNode origType, ClassNode type, Set<String> names, boolean includeSuperProperties, boolean includeStatic, boolean includePseudoGetters, boolean includePseudoSetters, boolean superFirst) {
    // TODO add generics support so this can be used for @EAHC
    if (type == null) {
        return new ArrayList<PropertyNode>();
    }
    List<PropertyNode> result = new ArrayList<PropertyNode>();
    if (superFirst && includeSuperProperties) {
        result.addAll(getAllProperties(origType, type.getSuperClass(), names, includeSuperProperties, includeStatic, includePseudoGetters, includePseudoSetters, superFirst));
    }
    addExplicitProperties(type, result, names, includeStatic);
    addPseudoProperties(origType, type, result, names, includeStatic, includePseudoGetters, includePseudoSetters);
    if (!superFirst && includeSuperProperties) {
        result.addAll(getAllProperties(origType, type.getSuperClass(), names, includeSuperProperties, includeStatic, includePseudoGetters, includePseudoSetters, superFirst));
    }
    return result;
}
 
Example #6
Source File: ImmutableASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
static boolean isSpecialNamedArgCase(List<PropertyNode> list, boolean checkSize) {
    if (checkSize && list.size() != 1) return false;
    if (list.size() == 0) return false;
    ClassNode firstParamType = list.get(0).getField().getType();
    if (firstParamType.equals(ClassHelper.MAP_TYPE)) {
        return true;
    }
    ClassNode candidate = HMAP_TYPE;
    while (candidate != null) {
        if (candidate.equals(firstParamType)) {
            return true;
        }
        candidate = candidate.getSuperClass();
    }
    return false;
}
 
Example #7
Source File: ClassCompletionVerifier.java    From groovy with Apache License 2.0 6 votes vote down vote up
private void checkDuplicateProperties(PropertyNode node) {
    ClassNode cn = node.getDeclaringClass();
    String name = node.getName();
    String getterName = "get" + capitalize(name);
    if (Character.isUpperCase(name.charAt(0))) {
        for (PropertyNode propNode : cn.getProperties()) {
            String otherName = propNode.getField().getName();
            String otherGetterName = "get" + capitalize(otherName);
            if (node != propNode && getterName.equals(otherGetterName)) {
                String msg = "The field " + name + " and " + otherName + " on the class " +
                        cn.getName() + " will result in duplicate JavaBean properties, which is not allowed";
                addError(msg, node);
            }
        }
    }
}
 
Example #8
Source File: Verifier.java    From groovy with Apache License 2.0 6 votes vote down vote up
private static ASTNode sourceOf(MethodNode methodNode) {
    if (methodNode.getLineNumber() < 1) {
        ClassNode declaringClass = methodNode.getDeclaringClass();
        if (methodNode.isSynthetic()) {
            String propertyName = getPropertyName(methodNode);
            if (propertyName != null) {
                PropertyNode propertyNode = declaringClass.getProperty(propertyName);
                if (propertyNode != null && propertyNode.getLineNumber() > 0) {
                    return propertyNode;
                }
            }
        }
        return declaringClass;
    }
    return methodNode;
}
 
Example #9
Source File: BeanUtils.java    From groovy with Apache License 2.0 6 votes vote down vote up
private static void addIfMissing(ClassNode cNode, List<PropertyNode> result, Set<String> names, MethodNode mNode, ClassNode returnType, String propName, Statement getter, Statement setter) {
    if (cNode.getProperty(propName) != null) return;
    if (names.contains(propName)) {
        for (PropertyNode pn : result) {
            if (pn.getName().equals(propName) && getter != null && pn.getGetterBlock() == null) {
                pn.setGetterBlock(getter);
            }
            if (pn.getName().equals(propName) && setter != null && pn.getSetterBlock() == null) {
                pn.setSetterBlock(setter);
            }
        }
    } else {
        result.add(new PropertyNode(propName, mNode.getModifiers(), returnType, cNode, null, getter, setter));
        names.add(propName);
    }
}
 
Example #10
Source File: LazyASTTransformation.java    From groovy with Apache License 2.0 6 votes vote down vote up
static void visitField(ErrorCollecting xform, AnnotationNode node, FieldNode fieldNode) {
    final Expression soft = node.getMember("soft");
    final Expression init = getInitExpr(xform, fieldNode);

    String backingFieldName = "$" + fieldNode.getName();
    fieldNode.rename(backingFieldName);
    fieldNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC | (fieldNode.getModifiers() & (~(ACC_PUBLIC | ACC_PROTECTED))));
    PropertyNode pNode = fieldNode.getDeclaringClass().getProperty(backingFieldName);
    if (pNode != null) {
        fieldNode.getDeclaringClass().getProperties().remove(pNode);
    }

    if (soft instanceof ConstantExpression && ((ConstantExpression) soft).getValue().equals(true)) {
        createSoft(fieldNode, init);
    } else {
        create(fieldNode, init);
        // @Lazy not meaningful with primitive so convert to wrapper if needed
        if (ClassHelper.isPrimitiveType(fieldNode.getType())) {
            fieldNode.setType(ClassHelper.getWrapper(fieldNode.getType()));
        }
    }
}
 
Example #11
Source File: GroovyLanguageServerUtils.java    From groovy-language-server with Apache License 2.0 6 votes vote down vote up
public static SymbolKind astNodeToSymbolKind(ASTNode node) {
	if (node instanceof ClassNode) {
		ClassNode classNode = (ClassNode) node;
		if (classNode.isInterface()) {
			return SymbolKind.Interface;
		} else if (classNode.isEnum()) {
			return SymbolKind.Enum;
		}
		return SymbolKind.Class;
	} else if (node instanceof MethodNode) {
		return SymbolKind.Method;
	} else if (node instanceof Variable) {
		if (node instanceof FieldNode || node instanceof PropertyNode) {
			return SymbolKind.Field;
		}
		return SymbolKind.Variable;
	}
	return SymbolKind.Property;
}
 
Example #12
Source File: GroovyLanguageServerUtils.java    From groovy-language-server with Apache License 2.0 6 votes vote down vote up
public static CompletionItemKind astNodeToCompletionItemKind(ASTNode node) {
	if (node instanceof ClassNode) {
		ClassNode classNode = (ClassNode) node;
		if (classNode.isInterface()) {
			return CompletionItemKind.Interface;
		} else if (classNode.isEnum()) {
			return CompletionItemKind.Enum;
		}
		return CompletionItemKind.Class;
	} else if (node instanceof MethodNode) {
		return CompletionItemKind.Method;
	} else if (node instanceof Variable) {
		if (node instanceof FieldNode || node instanceof PropertyNode) {
			return CompletionItemKind.Field;
		}
		return CompletionItemKind.Variable;
	}
	return CompletionItemKind.Property;
}
 
Example #13
Source File: NamedVariantASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private boolean processDelegateParam(final MethodNode mNode, final Parameter mapParam, final ArgumentListExpression args, final List<String> propNames, final Parameter fromParam) {
    if (isInnerClass(fromParam.getType())) {
        if (mNode.isStatic()) {
            addError("Error during " + NAMED_VARIANT + " processing. Delegate type '" + fromParam.getType().getNameWithoutPackage() + "' is an inner class which is not supported.", mNode);
            return false;
        }
    }

    Set<String> names = new HashSet<>();
    List<PropertyNode> props = getAllProperties(names, fromParam.getType(), true, false, false, true, false, true);
    for (String next : names) {
        if (hasDuplicates(mNode, propNames, next)) return false;
    }
    List<MapEntryExpression> entries = new ArrayList<>();
    for (PropertyNode pNode : props) {
        String name = pNode.getName();
        // create entry [name: __namedArgs.getOrDefault('name', initialValue)]
        Expression defaultValue = Optional.ofNullable(pNode.getInitialExpression()).orElseGet(() -> getDefaultExpression(pNode.getType()));
        entries.add(entryX(constX(name), callX(varX(mapParam), "getOrDefault", args(constX(name), defaultValue))));
        // create annotation @NamedParam(value='name', type=DelegateType)
        AnnotationNode namedParam = new AnnotationNode(NAMED_PARAM_TYPE);
        namedParam.addMember("value", constX(name));
        namedParam.addMember("type", classX(pNode.getType()));
        mapParam.addAnnotation(namedParam);
    }
    Expression delegateMap = mapX(entries);
    args.addExpression(castX(fromParam.getType(), delegateMap));
    return true;
}
 
Example #14
Source File: LegacyHashMapPropertyHandler.java    From groovy with Apache License 2.0 5 votes vote down vote up
@Override
public Statement createPropInit(AbstractASTTransformation xform, AnnotationNode anno, ClassNode cNode, PropertyNode pNode, Parameter namedArgsMap) {
    FieldNode fNode = pNode.getField();
    if (fNode.isFinal() && fNode.isStatic()) return null;
    if (fNode.isFinal() && fNode.getInitialExpression() != null) {
        return checkFinalArgNotOverridden(cNode, fNode);
    }
    return createLegacyConstructorStatementMapSpecial(fNode);
}
 
Example #15
Source File: DefaultPropertyHandler.java    From groovy with Apache License 2.0 5 votes vote down vote up
@Override
public boolean validateProperties(AbstractASTTransformation xform, BlockStatement body, ClassNode cNode, List<PropertyNode> props) {
    if (xform instanceof MapConstructorASTTransformation) {
        body.addStatement(ifS(equalsNullX(varX("args")), assignS(varX("args"), new MapExpression())));
        body.addStatement(stmt(callX(IMMUTABLE_XFORM_TYPE, "checkPropNames", args("this", "args"))));
    }
    return super.validateProperties(xform, body, cNode, props);
}
 
Example #16
Source File: LegacyHashMapPropertyHandler.java    From groovy with Apache License 2.0 5 votes vote down vote up
@Override
public boolean validateProperties(AbstractASTTransformation xform, BlockStatement body, ClassNode cNode, List<PropertyNode> props) {
    if (!(props.size() == 1 && props.get(0).getType().equals(HMAP_TYPE))) {
        xform.addError("Error during " + xform.getAnnotationName() + " processing. Property handler " + getClass().getName() + " only accepts a single HashMap property", props.size() == 1 ? props.get(0) : cNode);
        return false;
    }
    return true;
}
 
Example #17
Source File: GeneralUtils.java    From groovy with Apache License 2.0 5 votes vote down vote up
public static List<String> getInstancePropertyNames(final ClassNode cNode) {
    List<PropertyNode> pList = BeanUtils.getAllProperties(cNode, false, false, true);
    List<String> result = new ArrayList<>(pList.size());
    for (PropertyNode pNode : pList) {
        result.add(pNode.getName());
    }
    return result;
}
 
Example #18
Source File: ImmutableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static void adjustPropertyForImmutability(PropertyNode pNode, List<PropertyNode> newNodes, PropertyHandler handler) {
    final FieldNode fNode = pNode.getField();
    fNode.setModifiers((pNode.getModifiers() & (~ACC_PUBLIC)) | ACC_FINAL | ACC_PRIVATE);
    pNode.setSetterBlock(null);
    Statement getter = handler.createPropGetter(pNode);
    if (getter != null) {
        pNode.setGetterBlock(getter);
    }
    newNodes.add(pNode);
}
 
Example #19
Source File: GeneralUtils.java    From groovy with Apache License 2.0 5 votes vote down vote up
public static List<PropertyNode> getAllProperties(final ClassNode type) {
    ClassNode node = type;
    List<PropertyNode> result = new ArrayList<>();
    while (node != null) {
        result.addAll(node.getProperties());
        node = node.getSuperClass();
    }
    return result;
}
 
Example #20
Source File: ImmutableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static void createCopyWith(final ClassNode cNode, final List<PropertyNode> pList) {
    BlockStatement body = new BlockStatement();
    body.addStatement(ifS(
            orX(
                    equalsNullX(varX("map", ClassHelper.MAP_TYPE)),
                    eqX(callX(varX("map", HMAP_TYPE), "size"), constX(0))
            ),
            returnS(varX("this", cNode))
    ));
    body.addStatement(declS(localVarX("dirty", ClassHelper.boolean_TYPE), ConstantExpression.PRIM_FALSE));
    body.addStatement(declS(localVarX("construct", HMAP_TYPE), ctorX(HMAP_TYPE)));

    // Check for each property
    for (final PropertyNode pNode : pList) {
        body.addStatement(createCheckForProperty(pNode));
    }

    body.addStatement(returnS(ternaryX(
            isTrueX(varX("dirty", ClassHelper.boolean_TYPE)),
            ctorX(cNode, args(varX("construct", HMAP_TYPE))),
            varX("this", cNode)
    )));

    final ClassNode clonedNode = cNode.getPlainNodeReference();

    addGeneratedMethod(cNode, COPY_WITH_METHOD,
            ACC_PUBLIC | ACC_FINAL,
            clonedNode,
            params(new Parameter(new ClassNode(Map.class), "map")),
            null,
            body);
}
 
Example #21
Source File: EqualsAndHashCodeASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static BinaryExpression bothSelfRecursivePropertyX(PropertyNode pNode, Expression other) {
    String getterName = getGetterName(pNode);
    Expression selfGetter = callThisX(getterName);
    Expression otherGetter = callX(other, getterName);
    return andX(
            sameX(selfGetter, varX("this")),
            sameX(otherGetter, other)
    );
}
 
Example #22
Source File: EqualsAndHashCodeASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static BinaryExpression differentSelfRecursivePropertyX(PropertyNode pNode, Expression other) {
    String getterName = getGetterName(pNode);
    Expression selfGetter = callThisX(getterName);
    Expression otherGetter = callX(other, getterName);
    return orX(
            andX(sameX(selfGetter, varX("this")), notX(sameX(otherGetter, other))),
            andX(notX(sameX(selfGetter, varX("this"))), sameX(otherGetter, other))
    );
}
 
Example #23
Source File: ImmutableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
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);
}
 
Example #24
Source File: TraitComposer.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static boolean isExistingProperty(final String methodName, final ClassNode cNode, final Parameter[] params) {
    String propertyName = methodName;
    boolean getter = false;
    if (methodName.startsWith("get")) {
        propertyName = propertyName.substring(3);
        getter = true;
    } else if (methodName.startsWith("is")) {
        propertyName = propertyName.substring(2);
        getter = true;
    } else if (methodName.startsWith("set")) {
        propertyName = propertyName.substring(3);
    } else {
        return false;
    }
    if (getter && params.length>0) {
        return false;
    }
    if (!getter && params.length!=1) {
        return false;
    }
    if (propertyName.length()==0) {
        return false;
    }
    propertyName = MetaClassHelper.convertPropertyName(propertyName);
    PropertyNode pNode = cNode.getProperty(propertyName);
    return pNode != null;
}
 
Example #25
Source File: GeneralUtils.java    From groovy with Apache License 2.0 5 votes vote down vote up
public static List<FieldNode> getSuperPropertyFields(final ClassNode cNode) {
    List<FieldNode> result;
    if (cNode == ClassHelper.OBJECT_TYPE) {
        result = new ArrayList<>();
    } else {
        result = getSuperPropertyFields(cNode.getSuperClass());
    }
    for (PropertyNode pNode : cNode.getProperties()) {
        if (!pNode.isStatic()) {
            result.add(pNode.getField());
        }
    }
    return result;
}
 
Example #26
Source File: UnionTypeClassNode.java    From groovy with Apache License 2.0 5 votes vote down vote up
@Override
public List<PropertyNode> getProperties() {
    List<PropertyNode> nodes = new LinkedList<PropertyNode>();
    for (ClassNode delegate : delegates) {
        List<PropertyNode> properties = delegate.getProperties();
        if (properties != null) nodes.addAll(properties);
    }
    return nodes;
}
 
Example #27
Source File: BuilderASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
protected List<PropertyInfo> getPropertyInfoFromClassNode(BuilderASTTransformation transform, AnnotationNode anno, ClassNode cNode, List<String> includes, List<String> excludes, boolean allNames, boolean allProperties) {
    List<PropertyInfo> props = new ArrayList<PropertyInfo>();
    List<String> seen = new ArrayList<String>();
    for (PropertyNode pNode : BeanUtils.getAllProperties(cNode, false, false, allProperties)) {
        if (shouldSkip(pNode.getName(), excludes, includes, allNames)) continue;
        props.add(new PropertyInfo(pNode.getName(), pNode.getType()));
        seen.add(pNode.getName());
    }
    for (FieldNode fNode : getFields(transform, anno, cNode)) {
        if (seen.contains(fNode.getName()) || shouldSkip(fNode.getName(), excludes, includes, allNames)) continue;
        props.add(new PropertyInfo(fNode.getName(), fNode.getType()));
    }
    return props;
}
 
Example #28
Source File: SortableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
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;
}
 
Example #29
Source File: SortableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private void checkComparable(PropertyNode pNode) {
    if (pNode.getType().implementsInterface(COMPARABLE_TYPE) || isPrimitiveType(pNode.getType()) || hasAnnotation(pNode.getType(), MY_TYPE)) {
        return;
    }
    addError("Error during " + MY_TYPE_NAME + " processing: property '" +
            pNode.getName() + "' must be Comparable", pNode);
}
 
Example #30
Source File: SortableASTTransformation.java    From groovy with Apache License 2.0 5 votes vote down vote up
private static Statement createCompareMethodBody(PropertyNode property, boolean reversed) {
    String propName = property.getName();
    return block(
            // if (arg0 == arg1) return 0;
            ifS(eqX(varX(ARG0), varX(ARG1)), returnS(constX(0))),
            // if (arg0 != null && arg1 == null) return -1;
            ifS(andX(notNullX(varX(ARG0)), equalsNullX(varX(ARG1))), returnS(constX(-1))),
            // if (arg0 == null && arg1 != null) return 1;
            ifS(andX(equalsNullX(varX(ARG0)), notNullX(varX(ARG1))), returnS(constX(1))),
            // return arg0.prop <=> arg1.prop;
            returnS(compareExpr(propX(varX(ARG0), propName), propX(varX(ARG1), propName), reversed))
    );
}