public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; if (!checkNotInterface(cNode, MY_TYPE_NAME)) return; boolean callSuper = memberHasValue(anno, "callSuper", true); boolean cacheHashCode = memberHasValue(anno, "cache", true); boolean useCanEqual = !memberHasValue(anno, "useCanEqual", false); if (callSuper && cNode.getSuperClass().getName().equals("java.lang.Object")) { addError("Error during " + MY_TYPE_NAME + " processing: callSuper=true but '" + cNode.getName() + "' has no super class.", anno); } boolean includeFields = memberHasValue(anno, "includeFields", true); List<String> excludes = getMemberStringList(anno, "excludes"); List<String> includes = getMemberStringList(anno, "includes"); final boolean allNames = memberHasValue(anno, "allNames", true); final boolean allProperties = memberHasValue(anno, "allProperties", true); if (!checkIncludeExcludeUndefinedAware(anno, excludes, includes, MY_TYPE_NAME)) return; if (!checkPropertyList(cNode, includes, "includes", anno, MY_TYPE_NAME, includeFields)) return; if (!checkPropertyList(cNode, excludes, "excludes", anno, MY_TYPE_NAME, includeFields)) return; createHashCode(cNode, cacheHashCode, includeFields, callSuper, excludes, includes, allNames, allProperties); createEquals(cNode, includeFields, callSuper, useCanEqual, excludes, includes, allNames, allProperties); } }
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; checkNotInterface(cNode, MY_TYPE_NAME); boolean callSuper = memberHasValue(anno, "callSuper", true); boolean useCanEqual = !memberHasValue(anno, "useCanEqual", false); if (callSuper && cNode.getSuperClass().getName().equals("java.lang.Object")) { addError("Error during " + MY_TYPE_NAME + " processing: callSuper=true but '" + cNode.getName() + "' has no super class.", anno); } boolean includeFields = memberHasValue(anno, "includeFields", true); List<String> excludes = tokenize((String) getMemberValue(anno, "excludes")); List<String> includes = tokenize((String) getMemberValue(anno, "includes")); if (hasAnnotation(cNode, CanonicalASTTransformation.MY_TYPE)) { AnnotationNode canonical = cNode.getAnnotations(CanonicalASTTransformation.MY_TYPE).get(0); if (excludes == null || excludes.isEmpty()) excludes = tokenize((String) getMemberValue(canonical, "excludes")); if (includes == null || includes.isEmpty()) includes = tokenize((String) getMemberValue(canonical, "includes")); } if (includes != null && !includes.isEmpty() && excludes != null && !excludes.isEmpty()) { addError("Error during " + MY_TYPE_NAME + " processing: Only one of 'includes' and 'excludes' should be supplied not both.", anno); } createHashCode(cNode, false, includeFields, callSuper, excludes, includes); createEquals(cNode, includeFields, callSuper, useCanEqual, excludes, includes); } }
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); 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 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)))) 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))))) ));
createHashCode(cNode, true, false, false, null, null); createEquals(cNode, false, false, false, null, null); if (!hasAnnotation(cNode, ToStringASTTransformation.MY_TYPE)) { createToString(cNode, false, false, null, null, false);
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes) { if (useCanEqual) createCanEqual(cNode); if (shouldSkip(pNode.getName(), excludes, includes)) continue; body.addStatement(returnFalseIfPropertyNotEqual(pNode, otherTyped)); if (shouldSkip(fNode.getName(), excludes, includes)) continue; body.addStatement(returnFalseIfFieldNotEqual(fNode, otherTyped));
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes, boolean allNames) { createEquals(cNode, includeFields, callSuper, useCanEqual, excludes, includes, allNames,false); }
public static void createHashCode(ClassNode cNode, boolean cacheResult, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes) { createHashCode(cNode, cacheResult, includeFields, callSuper, excludes, includes, false); }
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); }
public void visit(ASTNode[] nodes, SourceUnit source) { init(nodes, source); AnnotatedNode parent = (AnnotatedNode) nodes[1]; AnnotationNode anno = (AnnotationNode) nodes[0]; if (!MY_TYPE.equals(anno.getClassNode())) return; if (parent instanceof ClassNode) { ClassNode cNode = (ClassNode) parent; // TODO remove - let other validation steps pick this up if (hasAnnotation(cNode, ImmutableASTTransformation.MY_TYPE)) { addError(MY_TYPE_NAME + " class '" + cNode.getName() + "' can't also be " + ImmutableASTTransformation.MY_TYPE_NAME, parent); } checkNotInterface(cNode, MY_TYPE_NAME); List<String> excludes = tokenize((String) getMemberValue(anno, "excludes")); List<String> includes = tokenize((String) getMemberValue(anno, "includes")); if (includes != null && !includes.isEmpty() && excludes != null && !excludes.isEmpty()) { addError("Error during " + MY_TYPE_NAME + " processing: Only one of 'includes' and 'excludes' should be supplied not both.", anno); } if (!hasAnnotation(cNode, TupleConstructorASTTransformation.MY_TYPE)) { createConstructor(cNode, false, true, false, false, false, false, excludes, includes); } if (!hasAnnotation(cNode, EqualsAndHashCodeASTTransformation.MY_TYPE)) { createHashCode(cNode, false, false, false, excludes, includes); createEquals(cNode, false, false, true, excludes, includes); } if (!hasAnnotation(cNode, ToStringASTTransformation.MY_TYPE)) { createToString(cNode, false, false, excludes, includes, false); } } }
public static void createEquals(ClassNode cNode, boolean includeFields, boolean callSuper, boolean useCanEqual, List<String> excludes, List<String> includes) { createEquals(cNode, includeFields, callSuper, useCanEqual, excludes, includes, false); }
public static void createHashCode(ClassNode cNode, boolean cacheResult, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes, boolean allNames) { createHashCode(cNode, cacheResult, includeFields, callSuper, excludes, includes, allNames,false); }
public static void createHashCode(ClassNode cNode, boolean cacheResult, boolean includeFields, boolean callSuper, List<String> excludes, List<String> includes) { // 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 = new VariableExpression(hashField); body.addStatement(new IfStatement( isZeroExpr(hash), calculateHashStatements(cNode, hash, includeFields, callSuper, excludes, includes), new EmptyStatement() )); body.addStatement(new ReturnStatement(hash)); } else { body.addStatement(calculateHashStatements(cNode, null, includeFields, callSuper, excludes, includes)); } cNode.addMethod(new MethodNode(hasExistingHashCode ? "_hashCode" : "hashCode", hasExistingHashCode ? ACC_PRIVATE : ACC_PUBLIC, ClassHelper.int_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, body)); }