From 64004aefdf48ddb57e3d8ab3f4f9f3f726776571 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Fri, 22 Sep 2023 15:48:09 +0200 Subject: [PATCH] improve AnnotationInstance.hashCode() The `AnnotationInstance.equals()` method considers two annotations that are basically the same as distinct if they don't have the same `target`. However, the `AnnotationInstance.hashCode()` method does not take the `target` into account at all, which leads to hash table collisions. This commit uses the `AnnotationTarget` information to spread out the `AnnotationInstance` hash code to make collisions less likely. --- .../org/jboss/jandex/AnnotationInstance.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/jboss/jandex/AnnotationInstance.java b/src/main/java/org/jboss/jandex/AnnotationInstance.java index 147a4889..91f9b660 100644 --- a/src/main/java/org/jboss/jandex/AnnotationInstance.java +++ b/src/main/java/org/jboss/jandex/AnnotationInstance.java @@ -324,8 +324,7 @@ void setTarget(AnnotationTarget target) { /** * Returns whether or not this annotation instance is equivalent to another instance. * An annotation instance is equivalent if its name and values are equal, and it shares - * the exact same AnnotationTarget instance. The latter restriction - * may be softened in future versions. + * the exact same AnnotationTarget instance. * * @param o the annotation instance to compare to. * @return true if equal, false if not @@ -353,6 +352,36 @@ public int hashCode() { int result = name.hashCode(); result = 31 * result + Arrays.hashCode(values); + if (target != null) { + switch (target.kind()) { + case CLASS: + result = 31 * result + target.asClass().name().hashCode(); + break; + case METHOD: + result = 31 * result + target.asMethod().declaringClass().name().hashCode(); + result = 31 * result + target.asMethod().name().hashCode(); + break; + case FIELD: + result = 31 * result + target.asField().declaringClass().name().hashCode(); + result = 31 * result + target.asField().name().hashCode(); + break; + case METHOD_PARAMETER: + result = 31 * result + target.asMethodParameter().method().declaringClass().name().hashCode(); + result = 31 * result + target.asMethodParameter().method().name().hashCode(); + result = 31 * result + target.asMethodParameter().position(); + break; + case RECORD_COMPONENT: + result = 31 * result + target.asRecordComponent().declaringClass().name().hashCode(); + result = 31 * result + target.asRecordComponent().name().hashCode(); + break; + case TYPE: + if (target.asType().target() != null) { + result = 31 * result + target.asType().target().name().hashCode(); + } + break; + } + } + return result; } }