Fix code generation for null indexed argument value
This commit fixes code generation when an indexed constructor argument value is null as the method is overloaded and need the value to be cast to `Object`. Closes gh-31508
This commit is contained in:
parent
d3fba6d49b
commit
1762bf4a60
|
|
@ -174,7 +174,9 @@ class BeanDefinitionPropertiesCodeGenerator {
|
|||
Map<Integer, ValueHolder> indexedValues = constructorValues.getIndexedArgumentValues();
|
||||
if (!indexedValues.isEmpty()) {
|
||||
indexedValues.forEach((index, valueHolder) -> {
|
||||
CodeBlock valueCode = generateValue(valueHolder.getName(), valueHolder.getValue());
|
||||
Object value = valueHolder.getValue();
|
||||
CodeBlock valueCode = castIfNecessary(value == null, Object.class,
|
||||
generateValue(valueHolder.getName(), value));
|
||||
code.addStatement(
|
||||
"$L.getConstructorArgumentValues().addIndexedArgumentValue($L, $L)",
|
||||
BEAN_DEFINITION_VARIABLE, index, valueCode);
|
||||
|
|
@ -346,6 +348,20 @@ class BeanDefinitionPropertiesCodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the specified {@code valueCode} to the specified {@code castType} if
|
||||
* the {@code castNecessary} is {@code true}. Otherwise return the valueCode
|
||||
* as is.
|
||||
* @param castNecessary whether a cast is necessary
|
||||
* @param castType the type to cast to
|
||||
* @param valueCode the code for the value
|
||||
* @return the existing value or a form of {@code (CastType) valueCode} if a
|
||||
* cast is necessary
|
||||
*/
|
||||
private CodeBlock castIfNecessary(boolean castNecessary, Class<?> castType, CodeBlock valueCode) {
|
||||
return (castNecessary ? CodeBlock.of("($T) $L", castType, valueCode) : valueCode);
|
||||
}
|
||||
|
||||
static class PropertyNamesStack {
|
||||
|
||||
private static final ThreadLocal<ArrayDeque<String>> threadLocal = ThreadLocal.withInitial(ArrayDeque::new);
|
||||
|
|
|
|||
|
|
@ -235,6 +235,18 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructorArgumentValuesWhenIndexedNullValue() {
|
||||
this.beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0, (Object) null);
|
||||
compile((actual, compiled) -> {
|
||||
ConstructorArgumentValues argumentValues = actual.getConstructorArgumentValues();
|
||||
Map<Integer, ValueHolder> values = argumentValues.getIndexedArgumentValues();
|
||||
assertThat(values.get(0)).satisfies(assertValueHolder(null, null, null));
|
||||
assertThat(values).hasSize(1);
|
||||
assertThat(argumentValues.getGenericArgumentValues()).isEmpty();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void constructorArgumentValuesWhenGenericValuesWithName() {
|
||||
this.beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(String.class);
|
||||
|
|
@ -255,7 +267,9 @@ class BeanDefinitionPropertiesCodeGeneratorTests {
|
|||
});
|
||||
}
|
||||
|
||||
private Consumer<ValueHolder> assertValueHolder(Object value, @Nullable Class<?> type, @Nullable String name) {
|
||||
private Consumer<ValueHolder> assertValueHolder(
|
||||
@Nullable Object value, @Nullable Class<?> type, @Nullable String name) {
|
||||
|
||||
return valueHolder -> {
|
||||
assertThat(valueHolder.getValue()).isEqualTo(value);
|
||||
assertThat(valueHolder.getType()).isEqualTo((type != null ? type.getName() : null));
|
||||
|
|
|
|||
Loading…
Reference in New Issue