25
25
import java .util .Optional ;
26
26
27
27
import graphql .schema .DataFetchingEnvironment ;
28
+ import kotlin .jvm .JvmClassMappingKt ;
29
+ import kotlin .reflect .KClass ;
30
+ import kotlin .reflect .KFunction ;
31
+ import kotlin .reflect .KParameter ;
32
+ import kotlin .reflect .KType ;
33
+ import kotlin .reflect .full .KClasses ;
34
+ import kotlin .reflect .jvm .KCallablesJvm ;
35
+ import kotlin .reflect .jvm .ReflectJvmMapping ;
28
36
import org .jspecify .annotations .Nullable ;
29
37
30
38
import org .springframework .beans .BeanInstantiationException ;
37
45
import org .springframework .beans .TypeMismatchException ;
38
46
import org .springframework .core .CollectionFactory ;
39
47
import org .springframework .core .Conventions ;
48
+ import org .springframework .core .KotlinDetector ;
40
49
import org .springframework .core .MethodParameter ;
41
50
import org .springframework .core .ResolvableType ;
42
51
import org .springframework .core .convert .ConversionService ;
@@ -301,7 +310,7 @@ private Map<?, Object> bindMapToMap(
301
310
Map <String , Object > dataToBind = new HashMap <>(rawMap );
302
311
@ Nullable String [] paramNames = BeanUtils .getParameterNames (constructor );
303
312
Class <?>[] paramTypes = constructor .getParameterTypes ();
304
- @ Nullable Object [] constructorArguments = new Object [paramTypes .length ];
313
+ @ Nullable Object [] constructorArguments = new Object [paramNames .length ];
305
314
306
315
for (int i = 0 ; i < paramNames .length ; i ++) {
307
316
String name = paramNames [i ];
@@ -328,6 +337,9 @@ private Map<?, Object> bindMapToMap(
328
337
constructorArguments [i ] = bindRawValue (
329
338
name , rawValue , isNotPresent , targetType , paramTypes [i ], bindingResult );
330
339
}
340
+ if (KotlinDetector .isKotlinReflectPresent () && KotlinDetector .isKotlinType (constructor .getDeclaringClass ())) {
341
+ KotlinDelegate .rebindKotlinArguments (constructorArguments , constructor );
342
+ }
331
343
332
344
Object target ;
333
345
try {
@@ -553,4 +565,37 @@ void rejectArgumentValue(
553
565
}
554
566
}
555
567
568
+ // remove in favor of https://github.com/spring-projects/spring-framework/issues/33630
569
+ private static final class KotlinDelegate {
570
+
571
+ public static void rebindKotlinArguments (@ Nullable Object [] arguments , Constructor <?> constructor ) {
572
+ KFunction <?> function = ReflectJvmMapping .getKotlinFunction (constructor );
573
+ if (function == null ) {
574
+ return ;
575
+ }
576
+ int index = 0 ;
577
+ for (KParameter parameter : function .getParameters ()) {
578
+ switch (parameter .getKind ()) {
579
+ case VALUE , EXTENSION_RECEIVER -> {
580
+ Object rawValue = arguments [index ];
581
+ if (!(parameter .isOptional () && rawValue == null )) {
582
+ KType type = parameter .getType ();
583
+ if (!(type .isMarkedNullable () && rawValue == null ) && type .getClassifier () instanceof KClass <?> kClass
584
+ && KotlinDetector .isInlineClass (JvmClassMappingKt .getJavaClass (kClass ))) {
585
+ KFunction <?> argConstructor = KClasses .getPrimaryConstructor (kClass );
586
+ if (argConstructor != null ) {
587
+ if (!KCallablesJvm .isAccessible (argConstructor )) {
588
+ KCallablesJvm .setAccessible (argConstructor , true );
589
+ }
590
+ arguments [index ] = argConstructor .call (rawValue );
591
+ }
592
+ }
593
+ }
594
+ }
595
+ }
596
+ index ++;
597
+ }
598
+ }
599
+ }
600
+
556
601
}
0 commit comments