Merge branch '5.3.x'
# Conflicts: # spring-core/src/main/java/org/springframework/core/annotation/SynthesizedMergedAnnotationInvocationHandler.java # src/eclipse/org.eclipse.jdt.ui.prefs
This commit is contained in:
commit
5ae9217271
|
|
@ -177,7 +177,7 @@ final class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation> i
|
|||
private String annotationToString() {
|
||||
String string = this.string;
|
||||
if (string == null) {
|
||||
StringBuilder builder = new StringBuilder("@").append(this.type.getName()).append('(');
|
||||
StringBuilder builder = new StringBuilder("@").append(getName(this.type)).append('(');
|
||||
for (int i = 0; i < this.attributes.size(); i++) {
|
||||
Method attribute = this.attributes.get(i);
|
||||
if (i > 0) {
|
||||
|
|
@ -194,15 +194,43 @@ final class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation> i
|
|||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method currently does not address the following issues which we may
|
||||
* choose to address at a later point in time.
|
||||
*
|
||||
* <ul>
|
||||
* <li>non-ASCII, non-visible, and non-printable characters within a character
|
||||
* or String literal are not escaped.</li>
|
||||
* <li>formatting for float and double values does not take into account whether
|
||||
* a value is not a number (NaN) or infinite.</li>
|
||||
* </ul>
|
||||
* @param value the attribute value to format
|
||||
* @return the formatted string representation
|
||||
*/
|
||||
private String toString(Object value) {
|
||||
if (value instanceof String str) {
|
||||
return '"' + str + '"';
|
||||
}
|
||||
if (value instanceof Character) {
|
||||
return '\'' + value.toString() + '\'';
|
||||
}
|
||||
if (value instanceof Byte) {
|
||||
return String.format("(byte) 0x%02X", value);
|
||||
}
|
||||
if (value instanceof Long longValue) {
|
||||
return Long.toString(longValue) + 'L';
|
||||
}
|
||||
if (value instanceof Float floatValue) {
|
||||
return Float.toString(floatValue) + 'f';
|
||||
}
|
||||
if (value instanceof Double doubleValue) {
|
||||
return Double.toString(doubleValue) + 'd';
|
||||
}
|
||||
if (value instanceof Enum<?> e) {
|
||||
return e.name();
|
||||
}
|
||||
if (value instanceof Class<?> clazz) {
|
||||
return clazz.getName() + ".class";
|
||||
return getName(clazz) + ".class";
|
||||
}
|
||||
if (value.getClass().isArray()) {
|
||||
StringBuilder builder = new StringBuilder("{");
|
||||
|
|
@ -277,6 +305,11 @@ final class SynthesizedMergedAnnotationInvocationHandler<A extends Annotation> i
|
|||
return (A) Proxy.newProxyInstance(classLoader, interfaces, handler);
|
||||
}
|
||||
|
||||
private static String getName(Class<?> clazz) {
|
||||
String canonicalName = clazz.getCanonicalName();
|
||||
return (canonicalName != null ? canonicalName : clazz.getName());
|
||||
}
|
||||
|
||||
|
||||
private static boolean isVisible(ClassLoader classLoader, Class<?> interfaceClass) {
|
||||
if (classLoader == interfaceClass.getClassLoader()) {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import java.util.stream.Stream;
|
|||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.MergedAnnotation.Adapt;
|
||||
|
|
@ -1883,15 +1884,44 @@ class MergedAnnotationsTests {
|
|||
|
||||
// Formatting common to Spring and JDK 9+
|
||||
assertThat(string)
|
||||
.startsWith("@" + RequestMapping.class.getName() + "(")
|
||||
.contains("value={\"/test\"}", "path={\"/test\"}", "name=\"bar\"", "clazz=java.lang.Object.class")
|
||||
.contains("value={\"/test\"}", "path={\"/test\"}", "name=\"bar\"", "ch='X'", "chars={'X'}")
|
||||
.endsWith(")");
|
||||
|
||||
if (webMapping instanceof SynthesizedAnnotation) {
|
||||
assertThat(string).as("Spring uses Enum#name()").contains("method={GET, POST}");
|
||||
assertThat(string).as("Spring formatting")
|
||||
.startsWith("@org.springframework.core.annotation.MergedAnnotationsTests.RequestMapping(")
|
||||
.contains("method={GET, POST}",
|
||||
"clazz=org.springframework.core.annotation.MergedAnnotationsTests.RequestMethod.class",
|
||||
"classes={int[][].class, org.springframework.core.annotation.MergedAnnotationsTests.RequestMethod[].class}",
|
||||
"byteValue=(byte) 0xFF", "bytes={(byte) 0xFF}",
|
||||
"shortValue=9876", "shorts={9876}",
|
||||
"longValue=42L", "longs={42L}",
|
||||
"floatValue=3.14f", "floats={3.14f}",
|
||||
"doubleValue=99.999d", "doubles={99.999d}"
|
||||
);
|
||||
}
|
||||
else {
|
||||
assertThat(string).as("JDK uses Enum#toString()").contains("method={method: get, method: post}");
|
||||
assertThat(string).as("JDK 9-18 formatting")
|
||||
.startsWith("@org.springframework.core.annotation.MergedAnnotationsTests$RequestMapping(")
|
||||
.contains("method={method: get, method: post}",
|
||||
"clazz=org.springframework.core.annotation.MergedAnnotationsTests$RequestMethod.class",
|
||||
"classes={int[][].class, org.springframework.core.annotation.MergedAnnotationsTests$RequestMethod[].class}",
|
||||
"shortValue=9876", "shorts={9876}",
|
||||
"floatValue=3.14f", "floats={3.14f}",
|
||||
"doubleValue=99.999", "doubles={99.999}"
|
||||
);
|
||||
if (JRE.currentVersion().ordinal() < JRE.JAVA_14.ordinal()) {
|
||||
assertThat(string).as("JDK 9-13 formatting")
|
||||
.contains("longValue=42", "longs={42}",
|
||||
"byteValue=-1", "bytes={-1}"
|
||||
);
|
||||
}
|
||||
else {
|
||||
assertThat(string).as("JDK 14+ formatting")
|
||||
.contains("longValue=42L", "longs={42L}",
|
||||
"byteValue=(byte)0xff", "bytes={(byte)0xff}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2985,8 +3015,29 @@ class MergedAnnotationsTests {
|
|||
|
||||
RequestMethod[] method() default {};
|
||||
|
||||
// clazz is only used for testing annotation toString() implementations
|
||||
Class<?> clazz() default Object.class;
|
||||
// ---------------------------------------------------------------------
|
||||
// All remaining attributes declare default values that are used solely
|
||||
// for the purpose of testing the toString() implementations for annotations.
|
||||
Class<?> clazz() default RequestMethod.class;
|
||||
Class<?>[] classes() default {int[][].class, RequestMethod[].class};
|
||||
|
||||
char ch() default 'X';
|
||||
char[] chars() default {'X'};
|
||||
|
||||
byte byteValue() default (byte) 0xFF;
|
||||
byte[] bytes() default {(byte) 0xFF};
|
||||
|
||||
short shortValue() default 9876;
|
||||
short[] shorts() default {9876};
|
||||
|
||||
long longValue() default 42L;
|
||||
long[] longs() default {42L};
|
||||
|
||||
float floatValue() default 3.14F;
|
||||
float[] floats() default {3.14F};
|
||||
|
||||
double doubleValue() default 99.999D;
|
||||
double[] doubles() default {99.999D};
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -72,8 +72,8 @@ class BootstrapUtilsTests {
|
|||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
resolveTestContextBootstrapper(bootstrapContext))
|
||||
.withMessageContaining("Configuration error: found multiple declarations of @BootstrapWith")
|
||||
.withMessageContaining(FooBootstrapper.class.getName())
|
||||
.withMessageContaining(BarBootstrapper.class.getName());
|
||||
.withMessageContaining(FooBootstrapper.class.getCanonicalName())
|
||||
.withMessageContaining(BarBootstrapper.class.getCanonicalName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue