aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java85
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java5
2 files changed, 63 insertions, 27 deletions
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index ee049f1f..b2d64f05 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -167,9 +167,13 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
}
}
+ boolean needsCanEqual = false;
switch (methodExists("equals", typeNode)) {
case NOT_EXISTS:
- JCMethodDecl method = createEquals(typeNode, nodesForEquality, callSuper, useFieldsDirectly);
+ boolean isFinal = (((JCClassDecl)typeNode.get()).mods.flags & Flags.FINAL) != 0;
+ needsCanEqual = !isFinal || !isDirectDescendantOfObject;
+
+ JCMethodDecl method = createEquals(typeNode, nodesForEquality, callSuper, useFieldsDirectly, needsCanEqual);
injectMethod(typeNode, method);
break;
case EXISTS_BY_LOMBOK:
@@ -182,6 +186,18 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
break;
}
+ if (needsCanEqual) {
+ switch (methodExists("canEqual", typeNode)) {
+ case NOT_EXISTS:
+ JCMethodDecl method = createCanEqual(typeNode);
+ injectMethod(typeNode, method);
+ break;
+ case EXISTS_BY_LOMBOK:
+ case EXISTS_BY_USER:
+ default:
+ break;
+ }
+ }
switch (methodExists("hashCode", typeNode)) {
case NOT_EXISTS:
JCMethodDecl method = createHashCode(typeNode, nodesForEquality, callSuper, useFieldsDirectly);
@@ -196,7 +212,6 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
}
break;
}
-
return true;
}
@@ -314,7 +329,7 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
return maker.TypeCast(maker.TypeIdent(TypeTags.INT), xorBits);
}
- private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, boolean useFieldsDirectly) {
+ private JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, boolean useFieldsDirectly, boolean needsCanEqual) {
TreeMaker maker = typeNode.getTreeMaker();
JCClassDecl type = (JCClassDecl) typeNode.get();
@@ -335,27 +350,9 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
maker.Ident(thisName)), returnBool(maker, true), null));
}
- /* if (o == null) return false; */ {
- statements = statements.append(maker.If(maker.Binary(JCTree.EQ, maker.Ident(oName),
- maker.Literal(TypeTags.BOT, null)), returnBool(maker, false), null));
- }
-
- /* if (o.getClass() != this.getClass()) return false; */ {
- Name getClass = typeNode.toName("getClass");
- List<JCExpression> exprNil = List.nil();
- JCExpression oGetClass = maker.Apply(exprNil, maker.Select(maker.Ident(oName), getClass), exprNil);
- JCExpression thisGetClass = maker.Apply(exprNil, maker.Select(maker.Ident(thisName), getClass), exprNil);
- statements = statements.append(
- maker.If(maker.Binary(JCTree.NE, oGetClass, thisGetClass), returnBool(maker, false), null));
- }
-
- /* if (!super.equals(o)) return false; */
- if (callSuper) {
- JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
- maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")),
- List.<JCExpression>of(maker.Ident(oName)));
- JCUnary superNotEqual = maker.Unary(JCTree.NOT, callToSuper);
- statements = statements.append(maker.If(superNotEqual, returnBool(maker, false), null));
+ /* if (!(o instanceof MyType) return false; */ {
+ JCUnary notInstanceOf = maker.Unary(JCTree.NOT, maker.TypeTest(maker.Ident(oName), maker.Ident(type.name)));
+ statements = statements.append(maker.If(notInstanceOf, returnBool(maker, false), null));
}
/* MyType<?> other = (MyType<?>) o; */ {
@@ -379,6 +376,25 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName))));
}
+ /* if (!other.canEqual(this)) return false; */ {
+ if (needsCanEqual) {
+ List<JCExpression> exprNil = List.nil();
+ JCExpression equalityCheck = maker.Apply(exprNil,
+ maker.Select(maker.Ident(otherName), typeNode.toName("canEqual")),
+ List.<JCExpression>of(maker.Ident(thisName)));
+ statements = statements.append(maker.If(maker.Unary(JCTree.NOT, equalityCheck), returnBool(maker, false), null));
+ }
+ }
+
+ /* if (!super.equals(o)) return false; */
+ if (callSuper) {
+ JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
+ maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")),
+ List.<JCExpression>of(maker.Ident(oName)));
+ JCUnary superNotEqual = maker.Unary(JCTree.NOT, callToSuper);
+ statements = statements.append(maker.If(superNotEqual, returnBool(maker, false), null));
+ }
+
for (JavacNode fieldNode : fields) {
JCExpression fType = getFieldType(fieldNode, useFieldsDirectly);
JCExpression thisFieldAccessor = createFieldAccessor(maker, fieldNode, useFieldsDirectly);
@@ -428,6 +444,27 @@ public class HandleEqualsAndHashCode implements JavacAnnotationHandler<EqualsAnd
JCBlock body = maker.Block(0, statements);
return maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null);
}
+
+ private JCMethodDecl createCanEqual(JavacNode typeNode) {
+ /* public boolean canEquals(final java.lang.Object other) {
+ * return other instanceof MyType;
+ * }
+ */
+ TreeMaker maker = typeNode.getTreeMaker();
+ JCClassDecl type = (JCClassDecl) typeNode.get();
+
+ JCModifiers mods = maker.Modifiers(Flags.PUBLIC, List.<JCAnnotation>nil());
+ JCExpression returnType = maker.TypeIdent(TypeTags.BOOLEAN);
+ Name canEqualName = typeNode.toName("canEqual");
+ JCExpression objectType = chainDots(maker, typeNode, "java", "lang", "Object");
+ Name otherName = typeNode.toName("other");
+ List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(Flags.FINAL), otherName, objectType, null));
+
+ JCBlock body = maker.Block(0, List.<JCStatement>of(
+ maker.Return(maker.TypeTest(maker.Ident(otherName), maker.Ident(type.name)))));
+
+ return maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null);
+ }
private JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField,
TreeMaker maker, JavacNode node, boolean isDouble) {
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
index eef6fd9a..14687e32 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
@@ -163,7 +163,7 @@ public class PatchFixes {
} else return;
try {
- LocalDeclaration.class.getDeclaredField("$initCopy").set(variableDecl, init);
+ if (initCopyField != null) initCopyField.set(variableDecl, init);
} catch (Exception e) {
e.printStackTrace(System.out);
// In ecj mode this field isn't there and we don't need the copy anyway, so, we ignore the exception.
@@ -176,7 +176,7 @@ public class PatchFixes {
try {
initCopyField = LocalDeclaration.class.getDeclaredField("$initCopy");
} catch (Throwable t) {
- //ignore - no $generatedBy exists when running in ecj.
+ //ignore - no $initCopy exists when running in ecj.
}
}
@@ -191,7 +191,6 @@ public class PatchFixes {
if (init == null && initCopyField != null) {
try {
init = (Expression) initCopyField.get(local);
- System.out.println("copy = " + init);
} catch (Exception e) {
throw new RuntimeException(e);
}