aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorReinier Zwitserloot <reinier@tipit.to>2009-06-23 21:58:04 +0200
committerReinier Zwitserloot <reinier@tipit.to>2009-06-23 21:58:04 +0200
commit6210df32d073d0cd07682271e03fa0634de2adfa (patch)
treec71fb6e575e814c2c82027a075bb3290d349c770 /src
parentd27fd01b2b981740a08b497716c0cc065e29fab6 (diff)
downloadlombok-6210df32d073d0cd07682271e03fa0634de2adfa.tar.gz
lombok-6210df32d073d0cd07682271e03fa0634de2adfa.tar.bz2
lombok-6210df32d073d0cd07682271e03fa0634de2adfa.zip
@Data's generation of the equals() method now works!
Diffstat (limited to 'src')
-rw-r--r--src/lombok/eclipse/handlers/HandleData.java100
1 files changed, 95 insertions, 5 deletions
diff --git a/src/lombok/eclipse/handlers/HandleData.java b/src/lombok/eclipse/handlers/HandleData.java
index 65072ab1..06d7c9a9 100644
--- a/src/lombok/eclipse/handlers/HandleData.java
+++ b/src/lombok/eclipse/handlers/HandleData.java
@@ -5,8 +5,12 @@ import static lombok.eclipse.handlers.PKG.*;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import lombok.AccessLevel;
import lombok.Data;
@@ -25,6 +29,7 @@ import org.eclipse.jdt.internal.compiler.ast.Assignment;
import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
import org.eclipse.jdt.internal.compiler.ast.CastExpression;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
@@ -33,12 +38,14 @@ import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
@@ -50,6 +57,8 @@ import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
@@ -105,6 +114,11 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
}
}
+ if ( methodExists("equals", typeNode) == MethodExistsResult.NOT_EXISTS ) {
+ MethodDeclaration equals = createEquals(typeNode, nodesForEquality, ast);
+ injectMethod(typeNode, equals);
+ }
+
//TODO generate hashCode, equals.
return false;
}
@@ -225,6 +239,9 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
return constructor;
}
+ private static final Set<String> BUILT_IN_TYPES = Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(
+ "byte", "short", "int", "long", "char", "boolean", "double", "float")));
+
private MethodDeclaration createEquals(Node type, Collection<Node> fields, ASTNode pos) {
long p = (long)pos.sourceStart << 32 | pos.sourceEnd;
MethodDeclaration method = new MethodDeclaration(
@@ -281,20 +298,75 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
char[] otherN = "other".toCharArray();
- //TODO fix generics raw type warnings by inserting Wildcards.
- /* MyType other = (MyType) o; */ {
+
+ TypeDeclaration typeDecl = (TypeDeclaration)type.get();
+ /* MyType<?> other = (MyType<?>) o; */ {
if ( !fields.isEmpty() ) {
LocalDeclaration other = new LocalDeclaration(otherN, 0, 0);
+ char[] typeName = typeDecl.name;
+ Expression targetType;
+ if ( typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0 ) {
+ targetType = new SingleNameReference(((TypeDeclaration)type.get()).name, 0);
+ other.type = new SingleTypeReference(typeName, 0);
+ } else {
+ TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length];
+ for ( int i = 0 ; i < typeArgs.length ; i++ ) typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
+ targetType = new ParameterizedSingleTypeReference(typeName, typeArgs, 0, 0);
+ other.type = new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs), 0, 0);
+ }
other.initialization = new CastExpression(
new SingleNameReference(new char[] { 'o' }, 0),
- new SingleNameReference(((TypeDeclaration)type.get()).name, 0));
+ targetType);
+ statements.add(other);
}
}
for ( Node field : fields ) {
FieldDeclaration f = (FieldDeclaration) field.get();
- //compare if primitive, write per-primitive special code, otherwise use == null ? other == null ? .equals(other).
- //TODO I LEFT IT HERE
+ char[] token = f.type.getLastToken();
+ if ( f.type.dimensions() == 0 && token != null ) {
+ if ( Arrays.equals(TypeConstants.FLOAT, token) ) {
+ statements.add(generateCompareFloatOrDouble(otherN, "Float".toCharArray(), f.name));
+ } else if ( Arrays.equals(TypeConstants.DOUBLE, token) ) {
+ statements.add(generateCompareFloatOrDouble(otherN, "Double".toCharArray(), f.name));
+ } else if ( BUILT_IN_TYPES.contains(new String(token)) ) {
+ EqualExpression fieldsNotEqual = new EqualExpression(
+ new SingleNameReference(f.name, 0),
+ generateQualifiedNameRef(otherN, f.name),
+ OperatorIds.NOT_EQUAL);
+ ReturnStatement returnStatement = new ReturnStatement(new FalseLiteral(0, 0), 0, 0);
+ statements.add(new IfStatement(fieldsNotEqual, returnStatement, 0, 0));
+ } else /* objects */ {
+ EqualExpression fieldIsNull = new EqualExpression(
+ new SingleNameReference(f.name, 0),
+ new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+ EqualExpression otherFieldIsntNull = new EqualExpression(
+ generateQualifiedNameRef(otherN, f.name),
+ new NullLiteral(0, 0), OperatorIds.NOT_EQUAL);
+ MessageSend equalsCall = new MessageSend();
+ equalsCall.receiver = new SingleNameReference(f.name, 0);
+ equalsCall.selector = "equals".toCharArray();
+ equalsCall.arguments = new Expression[] { generateQualifiedNameRef(otherN, f.name) };
+ UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT);
+ ConditionalExpression fullEquals = new ConditionalExpression(fieldIsNull, otherFieldIsntNull, fieldsNotEqual);
+ ReturnStatement returnStatement = new ReturnStatement(new FalseLiteral(0, 0), 0, 0);
+ statements.add(new IfStatement(fullEquals, returnStatement, 0, 0));
+ }
+ } else if ( f.type.dimensions() > 0 && token != null ) {
+ MessageSend arraysEqualCall = new MessageSend();
+ arraysEqualCall.receiver = generateQualifiedNameRef(TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
+ if ( f.type.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token)) ) {
+ arraysEqualCall.selector = "deepEquals".toCharArray();
+ } else {
+ arraysEqualCall.selector = "equals".toCharArray();
+ }
+ arraysEqualCall.arguments = new Expression[] {
+ new SingleNameReference(f.name, 0),
+ generateQualifiedNameRef(otherN, f.name) };
+ UnaryExpression arraysNotEqual = new UnaryExpression(arraysEqualCall, OperatorIds.NOT);
+ ReturnStatement returnStatement = new ReturnStatement(new FalseLiteral(0, 0), 0, 0);
+ statements.add(new IfStatement(arraysNotEqual, returnStatement, 0, 0));
+ }
}
/* return true; */ {
@@ -304,6 +376,24 @@ public class HandleData implements EclipseAnnotationHandler<Data> {
return method;
}
+ private IfStatement generateCompareFloatOrDouble(char[] otherN, char[] floatOrDouble, char[] fieldName) {
+ /* if ( Float.compare(fieldName, other.fieldName) != 0 ) return false */
+ MessageSend floatCompare = new MessageSend();
+ floatCompare.receiver = generateQualifiedNameRef(TypeConstants.JAVA, TypeConstants.LANG, floatOrDouble);
+ floatCompare.selector = "compare".toCharArray();
+ floatCompare.arguments = new Expression[] {
+ new SingleNameReference(fieldName, 0),
+ generateQualifiedNameRef(otherN, fieldName)
+ };
+ EqualExpression ifFloatCompareIsNot0 = new EqualExpression(floatCompare, new IntLiteral(new char[] {'0'}, 0, 0), OperatorIds.NOT_EQUAL);
+ ReturnStatement returnFalse = new ReturnStatement(new FalseLiteral(0, 0), 0, 0);
+ return new IfStatement(ifFloatCompareIsNot0, returnFalse, 0, 0);
+ }
+
+ private QualifiedNameReference generateQualifiedNameRef(char[]... varNames) {
+ return new QualifiedNameReference(varNames, new long[varNames.length], 0, 0);
+ }
+
private MethodDeclaration createHashCode(Node type, Collection<Node> fields, ASTNode pos) {
//booleans: conditionalexpression that bounces between 1231 and 1237.
//longs: (int) (lng ^ (lng >>> 32));