/** Give 2 clones! */ private Expression longToIntForHashCode(Expression ref1, Expression ref2, ASTNode source) { int pS = source.sourceStart, pE = source.sourceEnd; /* (int)(ref >>> 32 ^ ref) */ IntLiteral int32 = new IntLiteral("32".toCharArray(), pS, pE); Eclipse.setGeneratedBy(int32, source); BinaryExpression higherBits = new BinaryExpression(ref1, int32, OperatorIds.UNSIGNED_RIGHT_SHIFT); Eclipse.setGeneratedBy(higherBits, source); BinaryExpression xorParts = new BinaryExpression(ref2, higherBits, OperatorIds.XOR); Eclipse.setGeneratedBy(xorParts, source); TypeReference intRef = TypeReference.baseTypeReference(TypeIds.T_int, 0); intRef.sourceStart = pS; intRef.sourceEnd = pE; Eclipse.setGeneratedBy(intRef, source); CastExpression expr = new CastExpression(xorParts, intRef); expr.sourceStart = pS; expr.sourceEnd = pE; Eclipse.setGeneratedBy(expr, source); return expr; }
private MethodDeclaration createEquals( EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual) { int pS = source.sourceStart; int pE = source.sourceEnd; long p = (long) pS << 32 | pE; TypeDeclaration typeDecl = (TypeDeclaration) type.get(); MethodDeclaration method = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); Eclipse.setGeneratedBy(method, source); method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC); method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0); method.returnType.sourceStart = pS; method.returnType.sourceEnd = pE; Eclipse.setGeneratedBy(method.returnType, source); method.annotations = new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)}; method.selector = "equals".toCharArray(); method.thrownExceptions = null; method.typeParameters = null; method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; TypeReference objectRef = new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {p, p, p}); Eclipse.setGeneratedBy(objectRef, source); method.arguments = new Argument[] {new Argument(new char[] {'o'}, 0, objectRef, Modifier.FINAL)}; method.arguments[0].sourceStart = pS; method.arguments[0].sourceEnd = pE; Eclipse.setGeneratedBy(method.arguments[0], source); List<Statement> statements = new ArrayList<Statement>(); /* if (o == this) return true; */ { SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p); Eclipse.setGeneratedBy(oRef, source); ThisReference thisRef = new ThisReference(pS, pE); Eclipse.setGeneratedBy(thisRef, source); EqualExpression otherEqualsThis = new EqualExpression(oRef, thisRef, OperatorIds.EQUAL_EQUAL); Eclipse.setGeneratedBy(otherEqualsThis, source); TrueLiteral trueLiteral = new TrueLiteral(pS, pE); Eclipse.setGeneratedBy(trueLiteral, source); ReturnStatement returnTrue = new ReturnStatement(trueLiteral, pS, pE); Eclipse.setGeneratedBy(returnTrue, source); IfStatement ifOtherEqualsThis = new IfStatement(otherEqualsThis, returnTrue, pS, pE); Eclipse.setGeneratedBy(ifOtherEqualsThis, source); statements.add(ifOtherEqualsThis); } /* if (!(o instanceof MyType) return false; */ { SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p); Eclipse.setGeneratedBy(oRef, source); SingleTypeReference typeReference = new SingleTypeReference(typeDecl.name, p); Eclipse.setGeneratedBy(typeReference, source); InstanceOfExpression instanceOf = new InstanceOfExpression(oRef, typeReference); instanceOf.sourceStart = pS; instanceOf.sourceEnd = pE; Eclipse.setGeneratedBy(instanceOf, source); Expression notInstanceOf = new UnaryExpression(instanceOf, OperatorIds.NOT); Eclipse.setGeneratedBy(notInstanceOf, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); Eclipse.setGeneratedBy(returnFalse, source); IfStatement ifNotInstanceOf = new IfStatement(notInstanceOf, returnFalse, pS, pE); Eclipse.setGeneratedBy(ifNotInstanceOf, source); statements.add(ifNotInstanceOf); } char[] otherName = "other".toCharArray(); /* MyType<?> other = (MyType<?>) o; */ { if (!fields.isEmpty() || needsCanEqual) { LocalDeclaration other = new LocalDeclaration(otherName, pS, pE); other.modifiers |= ClassFileConstants.AccFinal; Eclipse.setGeneratedBy(other, source); char[] typeName = typeDecl.name; Expression targetType; if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) { targetType = new SingleNameReference(((TypeDeclaration) type.get()).name, p); Eclipse.setGeneratedBy(targetType, source); other.type = new SingleTypeReference(typeName, p); Eclipse.setGeneratedBy(other.type, source); } else { TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length]; for (int i = 0; i < typeArgs.length; i++) { typeArgs[i] = new Wildcard(Wildcard.UNBOUND); typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE; Eclipse.setGeneratedBy(typeArgs[i], source); } targetType = new ParameterizedSingleTypeReference(typeName, typeArgs, 0, p); Eclipse.setGeneratedBy(targetType, source); other.type = new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs, source), 0, p); Eclipse.setGeneratedBy(other.type, source); } NameReference oRef = new SingleNameReference(new char[] {'o'}, p); Eclipse.setGeneratedBy(oRef, source); other.initialization = new CastExpression(oRef, targetType); Eclipse.setGeneratedBy(other.initialization, source); statements.add(other); } } /* if (!other.canEqual((java.lang.Object) this)) return false; */ { if (needsCanEqual) { MessageSend otherCanEqual = new MessageSend(); otherCanEqual.sourceStart = pS; otherCanEqual.sourceEnd = pE; Eclipse.setGeneratedBy(otherCanEqual, source); otherCanEqual.receiver = new SingleNameReference(otherName, p); Eclipse.setGeneratedBy(otherCanEqual.receiver, source); otherCanEqual.selector = "canEqual".toCharArray(); ThisReference thisReference = new ThisReference(pS, pE); Eclipse.setGeneratedBy(thisReference, source); CastExpression castThisRef = new CastExpression( thisReference, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT)); Eclipse.setGeneratedBy(castThisRef, source); castThisRef.sourceStart = pS; castThisRef.sourceEnd = pE; otherCanEqual.arguments = new Expression[] {castThisRef}; Expression notOtherCanEqual = new UnaryExpression(otherCanEqual, OperatorIds.NOT); Eclipse.setGeneratedBy(notOtherCanEqual, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); Eclipse.setGeneratedBy(returnFalse, source); IfStatement ifNotCanEqual = new IfStatement(notOtherCanEqual, returnFalse, pS, pE); Eclipse.setGeneratedBy(ifNotCanEqual, source); statements.add(ifNotCanEqual); } } /* if (!super.equals(o)) return false; */ if (callSuper) { MessageSend callToSuper = new MessageSend(); callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE; Eclipse.setGeneratedBy(callToSuper, source); callToSuper.receiver = new SuperReference(pS, pE); Eclipse.setGeneratedBy(callToSuper.receiver, source); callToSuper.selector = "equals".toCharArray(); SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p); Eclipse.setGeneratedBy(oRef, source); callToSuper.arguments = new Expression[] {oRef}; Expression superNotEqual = new UnaryExpression(callToSuper, OperatorIds.NOT); Eclipse.setGeneratedBy(superNotEqual, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE); Eclipse.setGeneratedBy(returnFalse, source); IfStatement ifSuperEquals = new IfStatement(superNotEqual, returnFalse, pS, pE); Eclipse.setGeneratedBy(ifSuperEquals, source); statements.add(ifSuperEquals); } for (EclipseNode field : fields) { TypeReference fType = getFieldType(field, fieldAccess); char[] token = fType.getLastToken(); Expression thisFieldAccessor = createFieldAccessor(field, fieldAccess, source); Expression otherFieldAccessor = createFieldAccessor(field, fieldAccess, source, otherName); if (fType.dimensions() == 0 && token != null) { if (Arrays.equals(TypeConstants.FLOAT, token)) { statements.add( generateCompareFloatOrDouble( thisFieldAccessor, otherFieldAccessor, "Float".toCharArray(), source)); } else if (Arrays.equals(TypeConstants.DOUBLE, token)) { statements.add( generateCompareFloatOrDouble( thisFieldAccessor, otherFieldAccessor, "Double".toCharArray(), source)); } else if (BUILT_IN_TYPES.contains(new String(token))) { EqualExpression fieldsNotEqual = new EqualExpression(thisFieldAccessor, otherFieldAccessor, OperatorIds.NOT_EQUAL); Eclipse.setGeneratedBy(fieldsNotEqual, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE); Eclipse.setGeneratedBy(returnStatement, source); IfStatement ifStatement = new IfStatement(fieldsNotEqual, returnStatement, pS, pE); Eclipse.setGeneratedBy(ifStatement, source); statements.add(ifStatement); } else /* objects */ { NullLiteral nullLiteral = new NullLiteral(pS, pE); Eclipse.setGeneratedBy(nullLiteral, source); EqualExpression fieldIsNull = new EqualExpression(thisFieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL); nullLiteral = new NullLiteral(pS, pE); Eclipse.setGeneratedBy(nullLiteral, source); EqualExpression otherFieldIsntNull = new EqualExpression(otherFieldAccessor, nullLiteral, OperatorIds.NOT_EQUAL); MessageSend equalsCall = new MessageSend(); equalsCall.sourceStart = pS; equalsCall.sourceEnd = pE; Eclipse.setGeneratedBy(equalsCall, source); equalsCall.receiver = createFieldAccessor(field, fieldAccess, source); equalsCall.selector = "equals".toCharArray(); Expression equalsArg = createFieldAccessor(field, fieldAccess, source, otherName); CastExpression castEqualsArg = new CastExpression( equalsArg, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT)); Eclipse.setGeneratedBy(castEqualsArg, source); castEqualsArg.sourceStart = pS; castEqualsArg.sourceEnd = pE; equalsCall.arguments = new Expression[] {castEqualsArg}; UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT); fieldsNotEqual.sourceStart = pS; fieldsNotEqual.sourceEnd = pE; Eclipse.setGeneratedBy(fieldsNotEqual, source); ConditionalExpression fullEquals = new ConditionalExpression(fieldIsNull, otherFieldIsntNull, fieldsNotEqual); fullEquals.sourceStart = pS; fullEquals.sourceEnd = pE; Eclipse.setGeneratedBy(fullEquals, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE); Eclipse.setGeneratedBy(returnStatement, source); IfStatement ifStatement = new IfStatement(fullEquals, returnStatement, pS, pE); Eclipse.setGeneratedBy(ifStatement, source); statements.add(ifStatement); } } else if (fType.dimensions() > 0 && token != null) { MessageSend arraysEqualCall = new MessageSend(); arraysEqualCall.sourceStart = pS; arraysEqualCall.sourceEnd = pE; Eclipse.setGeneratedBy(arraysEqualCall, source); arraysEqualCall.receiver = generateQualifiedNameRef( source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) { arraysEqualCall.selector = "deepEquals".toCharArray(); } else { arraysEqualCall.selector = "equals".toCharArray(); } arraysEqualCall.arguments = new Expression[] {thisFieldAccessor, otherFieldAccessor}; UnaryExpression arraysNotEqual = new UnaryExpression(arraysEqualCall, OperatorIds.NOT); arraysNotEqual.sourceStart = pS; arraysNotEqual.sourceEnd = pE; Eclipse.setGeneratedBy(arraysNotEqual, source); FalseLiteral falseLiteral = new FalseLiteral(pS, pE); Eclipse.setGeneratedBy(falseLiteral, source); ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE); Eclipse.setGeneratedBy(returnStatement, source); IfStatement ifStatement = new IfStatement(arraysNotEqual, returnStatement, pS, pE); Eclipse.setGeneratedBy(ifStatement, source); statements.add(ifStatement); } } /* return true; */ { TrueLiteral trueLiteral = new TrueLiteral(pS, pE); Eclipse.setGeneratedBy(trueLiteral, source); ReturnStatement returnStatement = new ReturnStatement(trueLiteral, pS, pE); Eclipse.setGeneratedBy(returnStatement, source); statements.add(returnStatement); } method.statements = statements.toArray(new Statement[statements.size()]); return method; }