diff options
4 files changed, 82 insertions, 10 deletions
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java index 60ed9e7a..de9c43ba 100644 --- a/src/core/lombok/EqualsAndHashCode.java +++ b/src/core/lombok/EqualsAndHashCode.java @@ -61,4 +61,19 @@ public @interface EqualsAndHashCode { * <strong>default: false</strong> */ boolean doNotUseGetters() default false; + + /** + * Any annotations listed here are put on the generated parameter of {@code equals} and {@code canEqual}. The syntax for this feature is: {@code @EqualsAndHashCode(onParam=@__({@AnnotationsGoHere}))} + * This is useful to add for example a {@code Nullable} annotation. + */ + AnyAnnotation[] onParam() default @AnyAnnotation; + + /** + * Placeholder annotation to enable the placement of annotations on the generated code. + * @deprecated Don't use this annotation, ever - Read the documentation. + */ + @Deprecated + @Retention(RetentionPolicy.SOURCE) + @Target({}) + @interface AnyAnnotation {} } diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java index 05244f3b..e62b0555 100644 --- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java +++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java @@ -94,7 +94,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas List<String> excludes = List.from(ann.exclude()); List<String> includes = List.from(ann.of()); JavacNode typeNode = annotationNode.up(); - + List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam=", annotationNode); checkForBogusFieldNames(typeNode, annotation); Boolean callSuper = ann.callSuper(); @@ -109,7 +109,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas FieldAccess fieldAccess = ann.doNotUseGetters() ? FieldAccess.PREFER_FIELD : FieldAccess.GETTER; - generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess); + generateMethods(typeNode, annotationNode, excludes, includes, callSuper, true, fieldAccess, onParam); } public void generateEqualsAndHashCodeForType(JavacNode typeNode, JavacNode source) { @@ -118,11 +118,11 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas return; } - generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER); + generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER, null); } public void generateMethods(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes, - Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) { + Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<JCAnnotation> onParam) { boolean notAClass = true; if (typeNode.get() instanceof JCClassDecl) { long flags = ((JCClassDecl)typeNode.get()).mods.flags; @@ -210,11 +210,11 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas //fallthrough } - JCMethodDecl equalsMethod = createEquals(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, needsCanEqual, source.get()); + JCMethodDecl equalsMethod = createEquals(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, needsCanEqual, source.get(), onParam); injectMethod(typeNode, equalsMethod); if (needsCanEqual && canEqualExists == MemberExistsResult.NOT_EXISTS) { - JCMethodDecl canEqualMethod = createCanEqual(typeNode, source.get()); + JCMethodDecl canEqualMethod = createCanEqual(typeNode, source.get(), onParam); injectMethod(typeNode, canEqualMethod); } @@ -363,7 +363,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas return chain; } - public JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source) { + public JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List<JCAnnotation> onParam) { JavacTreeMaker maker = typeNode.getTreeMaker(); JCClassDecl type = (JCClassDecl) typeNode.get(); @@ -379,7 +379,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext()); ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); - final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER), oName, objectType, null)); + final List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER, onParam), oName, objectType, null)); /* if (o == this) return true; */ { statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName), @@ -497,7 +497,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext()); } - public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source) { + public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) { /* public boolean canEqual(final java.lang.Object other) { * return other instanceof Outer.Inner.MyType; * } @@ -510,7 +510,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas JCExpression objectType = genJavaLangTypeRef(typeNode, "Object"); Name otherName = typeNode.toName("other"); long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext()); - List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags), otherName, objectType, null)); + List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null)); JCBlock body = maker.Block(0, List.<JCStatement>of( maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode))))); diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java new file mode 100644 index 00000000..2052b0b0 --- /dev/null +++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java @@ -0,0 +1,46 @@ +@interface Nullable { +} + +class EqualsAndHashCode { + int x; + boolean[] y; + Object[] z; + String a; + String b; + @java.lang.Override + @java.lang.SuppressWarnings("all") + public boolean equals(@Nullable final java.lang.Object o) { + if (o == this) return true; + if (!(o instanceof EqualsAndHashCode)) return false; + final EqualsAndHashCode other = (EqualsAndHashCode)o; + if (!other.canEqual((java.lang.Object)this)) return false; + if (this.x != other.x) return false; + if (!java.util.Arrays.equals(this.y, other.y)) return false; + if (!java.util.Arrays.deepEquals(this.z, other.z)) return false; + final java.lang.Object this$a = this.a; + final java.lang.Object other$a = other.a; + if (this$a == null ? other$a != null : !this$a.equals(other$a)) return false; + final java.lang.Object this$b = this.b; + final java.lang.Object other$b = other.b; + if (this$b == null ? other$b != null : !this$b.equals(other$b)) return false; + return true; + } + @java.lang.SuppressWarnings("all") + protected boolean canEqual(@Nullable final java.lang.Object other) { + return other instanceof EqualsAndHashCode; + } + @java.lang.Override + @java.lang.SuppressWarnings("all") + public int hashCode() { + final int PRIME = 59; + int result = 1; + result = result * PRIME + this.x; + result = result * PRIME + java.util.Arrays.hashCode(this.y); + result = result * PRIME + java.util.Arrays.deepHashCode(this.z); + final java.lang.Object $a = this.a; + result = result * PRIME + ($a == null ? 0 : $a.hashCode()); + final java.lang.Object $b = this.b; + result = result * PRIME + ($b == null ? 0 : $b.hashCode()); + return result; + } +}
\ No newline at end of file diff --git a/test/transform/resource/before/EqualsAndHashCodeWithOnParam.java b/test/transform/resource/before/EqualsAndHashCodeWithOnParam.java new file mode 100644 index 00000000..160dfdc6 --- /dev/null +++ b/test/transform/resource/before/EqualsAndHashCodeWithOnParam.java @@ -0,0 +1,11 @@ +@interface Nullable { +} + +@lombok.EqualsAndHashCode(onParam=@_{@Nullable}) +class EqualsAndHashCodeWithOnParam { + int x; + boolean[] y; + Object[] z; + String a; + String b; +}
\ No newline at end of file |