Use canonical names in error messages in annotation processing

Prior to this commit, we invoked `Class.getName()` when building error
messages during annotation processing, resulting in exceptions like the
following which use binary names for nested types and arrays.

  Attribute 'chars' in annotation
  org.springframework.core.annotation.AnnotationUtilsTests$CharsContainer
  should be compatible with [C but a [I value was returned

This commit switches to canonical names in error messages in annotation
processing, resulting in improved such errors messages such as the
following.

  Attribute 'chars' in annotation
  org.springframework.core.annotation.AnnotationUtilsTests.CharsContainer
  should be compatible with char[] but a int[] value was returned

In addition, this commit introduces a new getCanonicalName(Class) method
in ClassUtils, which has effectively been extracted from the following
classes where this functionality was previously duplicated.

- AttributeMethods
- SynthesizedMergedAnnotationInvocationHandler
- TypeDescriptor
- DefaultRetryPolicy
- ReflectiveIndexAccessor

Closes gh-36607
This commit is contained in:
Sam Brannen
2026-04-06 17:34:54 +02:00
parent 31d9fe5f41
commit 6062363738
21 changed files with 143 additions and 113 deletions
@@ -20,6 +20,8 @@ import java.util.Objects;
import org.jspecify.annotations.Nullable;
import org.springframework.util.ClassUtils;
/**
* Reference to a Java method, identified by its owner class and the method name.
*
@@ -43,7 +45,7 @@ public final class MethodReference {
}
public static MethodReference of(Class<?> klass, String methodName) {
return new MethodReference(klass.getCanonicalName(), methodName);
return new MethodReference(ClassUtils.getCanonicalName(klass), methodName);
}
/**
@@ -25,6 +25,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.TypeReference;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Record of an invocation of a method relevant to {@link org.springframework.aot.hint.RuntimeHints}.
@@ -181,7 +182,7 @@ public final class RecordedInvocation {
else {
Class<?> instanceType = (getInstance() instanceof Class<?> clazz) ? clazz : getInstance().getClass();
return "<%s> invocation of <%s> on type <%s> with arguments %s".formatted(
getHintType().hintClassName(), getMethodReference(), instanceType.getCanonicalName(), getArguments());
getHintType().hintClassName(), getMethodReference(), ClassUtils.getCanonicalName(instanceType), getArguments());
}
}