From 6473e0863f3c816d3a981aa90628db65f5f9ea3a Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Thu, 22 Jun 2023 12:29:18 +0200 Subject: [PATCH] Establish the notion of annotation instance equivalence The `AnnotationInstance.equals()` method provides _equality_. Two annotation instances are equal if, among others, they have identical annotation target. This is often not necessary. Therefore, this commit adds the `equivalentTo()` method, which provides _equivalence_. Two annotation instances are equivalent if they have the same name (the same annotation type) and the same members. No attention is paid to the annotation target. --- .../org/jboss/jandex/AnnotationInstance.java | 29 +++++++++-- .../java/org/jboss/jandex/FieldInternal.java | 1 - .../java/org/jboss/jandex/MethodInternal.java | 1 - .../org/jboss/jandex/ParameterizedType.java | 1 - .../jboss/jandex/RecordComponentInternal.java | 1 - .../java/org/jboss/jandex/TypeVariable.java | 1 - .../jandex/test/AnnotationInstanceTest.java | 52 +++++++++++++++++++ 7 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java diff --git a/core/src/main/java/org/jboss/jandex/AnnotationInstance.java b/core/src/main/java/org/jboss/jandex/AnnotationInstance.java index b4c8521b..57f95ca7 100644 --- a/core/src/main/java/org/jboss/jandex/AnnotationInstance.java +++ b/core/src/main/java/org/jboss/jandex/AnnotationInstance.java @@ -426,8 +426,8 @@ public String toString() { return toString(true); } - // runtime visibility is ignored for the purpose of equality and hash code, because - // the annotation type identity (the name) already includes that information + // runtime visibility is ignored for the purpose of equality, hash code and equivalence, + // because the annotation type identity (the name) already includes that information /** * Returns whether this annotation instance is equal to another instance. @@ -435,8 +435,8 @@ public String toString() { * and they share the exact same {@code AnnotationTarget} instance. The latter restriction * may be softened in future versions. * - * @param o the annotation instance to compare to. - * @return true if equal, false if not + * @param o the annotation instance to compare to + * @return {@code true} if equal, {@code false} if not * * @see Object#equals(Object) */ @@ -465,4 +465,25 @@ public int hashCode() { return result; } + + /** + * Returns whether this annotation instance is equivalent to the {@code other} annotation + * instance. Two annotation instances are equivalent if their names and members are equal. + * No attention is paid to the annotation target. + * + * @param other the annotation instance to compare to + * @return {@code true} if equivalent, {@code false} if not + * + * @see #equals(Object) + */ + public boolean equivalentTo(AnnotationInstance other) { + if (this == other) { + return true; + } + if (other == null) { + return false; + } + + return name.equals(other.name) && Arrays.equals(values, other.values); + } } diff --git a/core/src/main/java/org/jboss/jandex/FieldInternal.java b/core/src/main/java/org/jboss/jandex/FieldInternal.java index 1f94b915..dbd9ca1d 100644 --- a/core/src/main/java/org/jboss/jandex/FieldInternal.java +++ b/core/src/main/java/org/jboss/jandex/FieldInternal.java @@ -19,7 +19,6 @@ package org.jboss.jandex; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; diff --git a/core/src/main/java/org/jboss/jandex/MethodInternal.java b/core/src/main/java/org/jboss/jandex/MethodInternal.java index 2b1c2fe8..55970e1d 100644 --- a/core/src/main/java/org/jboss/jandex/MethodInternal.java +++ b/core/src/main/java/org/jboss/jandex/MethodInternal.java @@ -18,7 +18,6 @@ package org.jboss.jandex; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; diff --git a/core/src/main/java/org/jboss/jandex/ParameterizedType.java b/core/src/main/java/org/jboss/jandex/ParameterizedType.java index 5887f743..18ba4a94 100644 --- a/core/src/main/java/org/jboss/jandex/ParameterizedType.java +++ b/core/src/main/java/org/jboss/jandex/ParameterizedType.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; diff --git a/core/src/main/java/org/jboss/jandex/RecordComponentInternal.java b/core/src/main/java/org/jboss/jandex/RecordComponentInternal.java index f213977a..56c7da45 100644 --- a/core/src/main/java/org/jboss/jandex/RecordComponentInternal.java +++ b/core/src/main/java/org/jboss/jandex/RecordComponentInternal.java @@ -19,7 +19,6 @@ package org.jboss.jandex; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; diff --git a/core/src/main/java/org/jboss/jandex/TypeVariable.java b/core/src/main/java/org/jboss/jandex/TypeVariable.java index eec6e03d..9cbc4350 100644 --- a/core/src/main/java/org/jboss/jandex/TypeVariable.java +++ b/core/src/main/java/org/jboss/jandex/TypeVariable.java @@ -19,7 +19,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; diff --git a/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java b/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java new file mode 100644 index 00000000..da858755 --- /dev/null +++ b/core/src/test/java/org/jboss/jandex/test/AnnotationInstanceTest.java @@ -0,0 +1,52 @@ +package org.jboss.jandex.test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.Index; +import org.jboss.jandex.test.util.IndexingUtil; +import org.junit.jupiter.api.Test; + +public class AnnotationInstanceTest { + @MyAnnotation("foo") + static class Foo { + } + + @MyAnnotation("foo") + static class Foo2 { + } + + @MyAnnotation("bar") + static class Bar { + } + + @Test + public void equalityEquivalence() throws IOException { + Index index = Index.of(Foo.class, Foo2.class, Bar.class); + testEqualityEquivalence(index); + testEqualityEquivalence(IndexingUtil.roundtrip(index)); + } + + private void testEqualityEquivalence(Index index) { + AnnotationInstance foo = index.getClassByName(Foo.class).declaredAnnotation(MyAnnotation.DOT_NAME); + AnnotationInstance foo2 = index.getClassByName(Foo2.class).declaredAnnotation(MyAnnotation.DOT_NAME); + AnnotationInstance bar = index.getClassByName(Bar.class).declaredAnnotation(MyAnnotation.DOT_NAME); + + assertNotNull(foo); + assertNotNull(foo2); + assertNotNull(bar); + + assertNotEquals(foo, foo2); + assertNotEquals(foo, bar); + assertNotEquals(foo2, bar); + + assertTrue(foo.equivalentTo(foo2)); + assertFalse(foo.equivalentTo(bar)); + assertFalse(foo2.equivalentTo(bar)); + } +}