Provide more context when the code of a value cannot be generated
Closes gh-29118
This commit is contained in:
parent
c72c2ffc26
commit
2d4f308cc1
|
|
@ -85,7 +85,30 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||||
CodeBlock generateCode(@Nullable Object value) {
|
CodeBlock generateCode(@Nullable Object value) {
|
||||||
ResolvableType type = (value != null) ? ResolvableType.forInstance(value)
|
ResolvableType type = (value != null) ? ResolvableType.forInstance(value)
|
||||||
: ResolvableType.NONE;
|
: ResolvableType.NONE;
|
||||||
return generateCode(value, type);
|
try {
|
||||||
|
return generateCode(value, type);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException(buildErrorMessage(value, type), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodeBlock generateCodeForElement(@Nullable Object value, ResolvableType type) {
|
||||||
|
try {
|
||||||
|
return generateCode(value, type);
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException(buildErrorMessage(value, type), ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildErrorMessage(@Nullable Object value, ResolvableType type) {
|
||||||
|
StringBuilder message = new StringBuilder("Failed to generate code for '");
|
||||||
|
message.append(value).append("'");
|
||||||
|
if (type != ResolvableType.NONE) {
|
||||||
|
message.append(" with type ").append(type);
|
||||||
|
}
|
||||||
|
return message.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CodeBlock generateCode(@Nullable Object value, ResolvableType type) {
|
private CodeBlock generateCode(@Nullable Object value, ResolvableType type) {
|
||||||
|
|
@ -98,8 +121,7 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException("Code generation does not support " + type);
|
||||||
"'type' " + type + " must be supported for instance code generation");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -304,7 +326,7 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Object element = iterator.next();
|
Object element = iterator.next();
|
||||||
code.add("$L", BeanDefinitionPropertyValueCodeGenerator.this
|
code.add("$L", BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(element, elementType));
|
.generateCodeForElement(element, elementType));
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
code.add(", ");
|
code.add(", ");
|
||||||
}
|
}
|
||||||
|
|
@ -371,9 +393,9 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||||
Entry<?, ?> entry = iterator.next();
|
Entry<?, ?> entry = iterator.next();
|
||||||
code.add("$T.entry($L,$L)", Map.class,
|
code.add("$T.entry($L,$L)", Map.class,
|
||||||
BeanDefinitionPropertyValueCodeGenerator.this
|
BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(entry.getKey(), keyType),
|
.generateCodeForElement(entry.getKey(), keyType),
|
||||||
BeanDefinitionPropertyValueCodeGenerator.this
|
BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(entry.getValue(), valueType));
|
.generateCodeForElement(entry.getValue(), valueType));
|
||||||
if (iterator.hasNext()) {
|
if (iterator.hasNext()) {
|
||||||
code.add(", ");
|
code.add(", ");
|
||||||
}
|
}
|
||||||
|
|
@ -457,9 +479,9 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Entry<K, V> entry = iterator.next();
|
Entry<K, V> entry = iterator.next();
|
||||||
CodeBlock keyCode = BeanDefinitionPropertyValueCodeGenerator.this
|
CodeBlock keyCode = BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(entry.getKey(), keyType);
|
.generateCodeForElement(entry.getKey(), keyType);
|
||||||
CodeBlock valueCode = BeanDefinitionPropertyValueCodeGenerator.this
|
CodeBlock valueCode = BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(entry.getValue(), valueType);
|
.generateCodeForElement(entry.getValue(), valueType);
|
||||||
if (!useOfEntries) {
|
if (!useOfEntries) {
|
||||||
code.add("$L, $L", keyCode, valueCode);
|
code.add("$L, $L", keyCode, valueCode);
|
||||||
}
|
}
|
||||||
|
|
@ -490,9 +512,9 @@ class BeanDefinitionPropertyValueCodeGenerator {
|
||||||
LinkedHashMap.class, map.size());
|
LinkedHashMap.class, map.size());
|
||||||
map.forEach((key, value) -> method.addStatement("map.put($L, $L)",
|
map.forEach((key, value) -> method.addStatement("map.put($L, $L)",
|
||||||
BeanDefinitionPropertyValueCodeGenerator.this
|
BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(key, keyType),
|
.generateCodeForElement(key, keyType),
|
||||||
BeanDefinitionPropertyValueCodeGenerator.this
|
BeanDefinitionPropertyValueCodeGenerator.this
|
||||||
.generateCode(value, valueType)));
|
.generateCodeForElement(value, valueType)));
|
||||||
method.addStatement("return map");
|
method.addStatement("return map");
|
||||||
});
|
});
|
||||||
return CodeBlock.of("$L()", generatedMethod.getName());
|
return CodeBlock.of("$L()", generatedMethod.getName());
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ import org.springframework.javapoet.MethodSpec;
|
||||||
import org.springframework.javapoet.ParameterizedTypeName;
|
import org.springframework.javapoet.ParameterizedTypeName;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link BeanDefinitionPropertyValueCodeGenerator}.
|
* Tests for {@link BeanDefinitionPropertyValueCodeGenerator}.
|
||||||
|
|
@ -492,4 +493,48 @@ class BeanDefinitionPropertyValueCodeGeneratorTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
static class ExceptionTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void generateWhenUnsupportedDataTypeThrowsException() {
|
||||||
|
SampleValue sampleValue = new SampleValue("one");
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> generateCode(sampleValue))
|
||||||
|
.withMessageContaining("Failed to generate code for")
|
||||||
|
.withMessageContaining(sampleValue.toString())
|
||||||
|
.withMessageContaining(SampleValue.class.getName())
|
||||||
|
.havingCause()
|
||||||
|
.withMessageContaining("Code generation does not support")
|
||||||
|
.withMessageContaining(SampleValue.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void generateWhenListOfUnsupportedElement() {
|
||||||
|
SampleValue one = new SampleValue("one");
|
||||||
|
SampleValue two = new SampleValue("two");
|
||||||
|
List<SampleValue> list = List.of(one, two);
|
||||||
|
assertThatIllegalArgumentException().isThrownBy(() -> generateCode(list))
|
||||||
|
.withMessageContaining("Failed to generate code for")
|
||||||
|
.withMessageContaining(list.toString())
|
||||||
|
.withMessageContaining(list.getClass().getName())
|
||||||
|
.havingCause()
|
||||||
|
.withMessageContaining("Failed to generate code for")
|
||||||
|
.withMessageContaining(one.toString())
|
||||||
|
.withMessageContaining("?")
|
||||||
|
.havingCause()
|
||||||
|
.withMessageContaining("Code generation does not support ?");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateCode(Object value) {
|
||||||
|
TestGenerationContext context = new TestGenerationContext();
|
||||||
|
GeneratedClass generatedClass = context.getGeneratedClasses()
|
||||||
|
.addForFeature("Test", type -> {});
|
||||||
|
new BeanDefinitionPropertyValueCodeGenerator(generatedClass.getMethods())
|
||||||
|
.generateCode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
record SampleValue(String name) {}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue