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
29
37
import org .springframework .beans .BeanInstantiationException ;
30
38
import org .springframework .beans .BeanUtils ;
36
44
import org .springframework .beans .TypeMismatchException ;
37
45
import org .springframework .core .CollectionFactory ;
38
46
import org .springframework .core .Conventions ;
47
+ import org .springframework .core .KotlinDetector ;
39
48
import org .springframework .core .MethodParameter ;
40
49
import org .springframework .core .ResolvableType ;
41
50
import org .springframework .core .convert .ConversionService ;
@@ -280,7 +289,7 @@ private Object bindViaConstructorAndSetters(Constructor<?> constructor,
280
289
Map <String , Object > dataToBind = new HashMap <>(rawMap );
281
290
String [] paramNames = BeanUtils .getParameterNames (constructor );
282
291
Class <?>[] paramTypes = constructor .getParameterTypes ();
283
- Object [] constructorArguments = new Object [paramTypes .length ];
292
+ Object [] constructorArguments = new Object [paramNames .length ];
284
293
285
294
for (int i = 0 ; i < paramNames .length ; i ++) {
286
295
String name = paramNames [i ];
@@ -290,8 +299,12 @@ private Object bindViaConstructorAndSetters(Constructor<?> constructor,
290
299
291
300
constructorArguments [i ] = bindRawValue (
292
301
name , dataToBind .get (name ), !dataToBind .containsKey (name ), targetType , paramTypes [i ], bindingResult );
302
+
293
303
dataToBind .remove (name );
294
304
}
305
+ if (KotlinDetector .isKotlinReflectPresent () && KotlinDetector .isKotlinType (constructor .getDeclaringClass ())) {
306
+ KotlinDelegate .rebindKotlinArguments (constructorArguments , constructor );
307
+ }
295
308
296
309
Object target ;
297
310
try {
@@ -419,4 +432,37 @@ void rejectArgumentValue(
419
432
}
420
433
}
421
434
435
+ // remove in favor of https://github.com/spring-projects/spring-framework/issues/33630
436
+ private static final class KotlinDelegate {
437
+
438
+ public static void rebindKotlinArguments (Object [] arguments , Constructor <?> constructor ) {
439
+ KFunction <?> function = ReflectJvmMapping .getKotlinFunction (constructor );
440
+ if (function == null ) {
441
+ return ;
442
+ }
443
+ int index = 0 ;
444
+ for (KParameter parameter : function .getParameters ()) {
445
+ switch (parameter .getKind ()) {
446
+ case VALUE , EXTENSION_RECEIVER -> {
447
+ Object rawValue = arguments [index ];
448
+ if (!(parameter .isOptional () && rawValue == null )) {
449
+ KType type = parameter .getType ();
450
+ if (!(type .isMarkedNullable () && rawValue == null ) && type .getClassifier () instanceof KClass <?> kClass
451
+ && KotlinDetector .isInlineClass (JvmClassMappingKt .getJavaClass (kClass ))) {
452
+ KFunction <?> argConstructor = KClasses .getPrimaryConstructor (kClass );
453
+ if (argConstructor != null ) {
454
+ if (!KCallablesJvm .isAccessible (argConstructor )) {
455
+ KCallablesJvm .setAccessible (argConstructor , true );
456
+ }
457
+ arguments [index ] = argConstructor .call (rawValue );
458
+ }
459
+ }
460
+ }
461
+ }
462
+ }
463
+ index ++;
464
+ }
465
+ }
466
+ }
467
+
422
468
}
0 commit comments