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 {
* default: false
*/
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 excludes = List.from(ann.exclude());
List includes = List.from(ann.of());
JavacNode typeNode = annotationNode.up();
-
+ List onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam=", annotationNode);
checkForBogusFieldNames(typeNode, annotation);
Boolean callSuper = ann.callSuper();
@@ -109,7 +109,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler excludes, List includes,
- Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess) {
+ Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List 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 fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source) {
+ public JCMethodDecl createEquals(JavacNode typeNode, List fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List onParam) {
JavacTreeMaker maker = typeNode.getTreeMaker();
JCClassDecl type = (JCClassDecl) typeNode.get();
@@ -379,7 +379,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler statements = new ListBuffer();
- final List params = List.of(maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER), oName, objectType, null));
+ final List 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 JavacAnnotationHandlernil(), params, List.nil(), body, null), source, typeNode.getContext());
}
- public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source) {
+ public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List onParam) {
/* public boolean canEqual(final java.lang.Object other) {
* return other instanceof Outer.Inner.MyType;
* }
@@ -510,7 +510,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler params = List.of(maker.VarDef(maker.Modifiers(flags), otherName, objectType, null));
+ List params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null));
JCBlock body = maker.Block(0, List.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