1515import static org .junit .platform .commons .support .ModifierSupport .isNotStatic ;
1616import static org .junit .platform .commons .support .ReflectionSupport .findMethods ;
1717import static org .junit .platform .commons .support .ReflectionSupport .invokeMethod ;
18+ import static org .junit .platform .commons .support .conversion .FallbackStringToObjectConverter .DeprecationStatus .EXCLUDE_DEPRECATED ;
19+ import static org .junit .platform .commons .support .conversion .FallbackStringToObjectConverter .DeprecationStatus .INCLUDE_DEPRECATED ;
1820import static org .junit .platform .commons .util .ReflectionUtils .findConstructors ;
1921import static org .junit .platform .commons .util .ReflectionUtils .newInstance ;
2022
3234/**
3335 * {@code FallbackStringToObjectConverter} is a {@link StringToObjectConverter}
3436 * that provides a fallback conversion strategy for converting from a
35- * {@link String} to a given target type by invoking a static factory method
36- * or factory constructor defined in the target type.
37+ * {@link String} or {@link CharSequence} to a given target type by invoking a
38+ * static factory method or factory constructor defined in the target type.
3739 *
3840 * <h2>Search Algorithm</h2>
3941 *
@@ -92,12 +94,29 @@ public boolean canConvertTo(Class<?> targetType) {
9294 private static Function <String , @ Nullable Object > findFactoryExecutable (Class <?> targetType ) {
9395 return factoryExecutableCache .computeIfAbsent (targetType , type -> {
9496 // First, search for exact String argument matches.
95- Function <String , @ Nullable Object > factory = findFactoryExecutable (type , String .class );
97+ var factory = findFactoryMethodExecutable (type , String .class , INCLUDE_DEPRECATED );
98+ if (factory != null ) {
99+ return factory ;
100+ }
101+ factory = findFactoryConstructorExecutable (type , String .class );
96102 if (factory != null ) {
97103 return factory ;
98104 }
99105 // Second, fall back to CharSequence argument matches.
100- factory = findFactoryExecutable (type , CharSequence .class );
106+ factory = findFactoryMethodExecutable (type , CharSequence .class , INCLUDE_DEPRECATED );
107+ if (factory != null ) {
108+ return factory ;
109+ }
110+ factory = findFactoryConstructorExecutable (type , CharSequence .class );
111+ if (factory != null ) {
112+ return factory ;
113+ }
114+ // Third, try factory methods again, but exclude deprecated methods
115+ factory = findFactoryMethodExecutable (type , String .class , EXCLUDE_DEPRECATED );
116+ if (factory != null ) {
117+ return factory ;
118+ }
119+ factory = findFactoryMethodExecutable (type , CharSequence .class , EXCLUDE_DEPRECATED );
101120 if (factory != null ) {
102121 return factory ;
103122 }
@@ -106,23 +125,28 @@ public boolean canConvertTo(Class<?> targetType) {
106125 });
107126 }
108127
109- private static @ Nullable Function <String , @ Nullable Object > findFactoryExecutable (Class <?> targetType ,
110- Class <?> parameterType ) {
111-
112- Method factoryMethod = findFactoryMethod (targetType , parameterType );
128+ private static @ Nullable Function <String , @ Nullable Object > findFactoryMethodExecutable (Class <?> targetType ,
129+ Class <?> parameterType , DeprecationStatus deprecationStatus ) {
130+ Method factoryMethod = findFactoryMethod (targetType , parameterType , deprecationStatus );
113131 if (factoryMethod != null ) {
114132 return source -> invokeMethod (factoryMethod , null , source );
115133 }
134+ return null ;
135+ }
136+
137+ private static @ Nullable Function <String , @ Nullable Object > findFactoryConstructorExecutable (Class <?> targetType ,
138+ Class <?> parameterType ) {
116139 Constructor <?> constructor = findFactoryConstructor (targetType , parameterType );
117140 if (constructor != null ) {
118141 return source -> newInstance (constructor , source );
119142 }
120143 return null ;
121144 }
122145
123- private static @ Nullable Method findFactoryMethod (Class <?> targetType , Class <?> parameterType ) {
124- List <Method > factoryMethods = findMethods (targetType , new IsFactoryMethod (targetType , parameterType ),
125- BOTTOM_UP );
146+ private static @ Nullable Method findFactoryMethod (Class <?> targetType , Class <?> parameterType ,
147+ DeprecationStatus deprecationStatus ) {
148+ var isFactoryMethod = new IsFactoryMethod (targetType , parameterType , deprecationStatus );
149+ List <Method > factoryMethods = findMethods (targetType , isFactoryMethod , BOTTOM_UP );
126150 if (factoryMethods .size () == 1 ) {
127151 return factoryMethods .get (0 );
128152 }
@@ -138,12 +162,17 @@ public boolean canConvertTo(Class<?> targetType) {
138162 return null ;
139163 }
140164
165+ enum DeprecationStatus {
166+ INCLUDE_DEPRECATED , EXCLUDE_DEPRECATED
167+ }
168+
141169 /**
142170 * {@link Predicate} that determines if the {@link Method} supplied to
143171 * {@link #test(Method)} is a non-private static factory method for the
144172 * supplied {@link #targetType} and {@link #parameterType}.
145173 */
146- record IsFactoryMethod (Class <?> targetType , Class <?> parameterType ) implements Predicate <Method > {
174+ record IsFactoryMethod (Class <?> targetType , Class <?> parameterType , DeprecationStatus deprecationStatus )
175+ implements Predicate <Method > {
147176
148177 @ Override
149178 public boolean test (Method method ) {
@@ -154,6 +183,10 @@ public boolean test(Method method) {
154183 if (isNotStatic (method )) {
155184 return false ;
156185 }
186+ if (deprecationStatus == DeprecationStatus .EXCLUDE_DEPRECATED
187+ && method .getAnnotation (Deprecated .class ) != null ) {
188+ return false ;
189+ }
157190 return isFactoryCandidate (method , this .parameterType );
158191 }
159192 }
0 commit comments