Fix option type parsing

- In `CommandRegistration` add `ResolvableType` for `OptionSpec` giving
  more spesific handling of a type.
- In `CommandParser` handle source and target types so that we
  have generics with `List`, `Set` and arrays working better.
- In `HandlerMethodArgumentResolver` add better handling for
  `ConversionService` for generic types.
- In `StandardMethodTargetRegistrar` add better types via `ResolvableType`
  now that `CommandRegistration` support it.
- In `OptionConversionCommands` remove converter from `String` to `Set` as
  now things should work as is if generic in a `Set` has a converter.
- Fixes #694
This commit is contained in:
Janne Valkealahti
2023-04-01 15:33:46 +01:00
parent 77b136f53f
commit 041cb30eb0
9 changed files with 390 additions and 30 deletions

View File

@@ -16,6 +16,7 @@
package org.springframework.shell.standard;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -141,8 +142,9 @@ public class StandardMethodTargetRegistrar implements MethodTargetRegistrar, App
if (!longNames.isEmpty() || !shortNames.isEmpty()) {
log.debug("Registering longNames='{}' shortNames='{}'", longNames, shortNames);
Class<?> parameterType = mp.getParameterType();
Type genericParameterType = mp.getGenericParameterType();
OptionSpec optionSpec = builder.withOption()
.type(parameterType)
.type(genericParameterType)
.longNames(longNames.toArray(new String[0]))
.shortNames(shortNames.toArray(new Character[0]))
.position(mp.getParameterIndex())

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017-2022 the original author or authors.
* Copyright 2017-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
package org.springframework.shell.standard;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
@@ -500,4 +501,31 @@ public class StandardMethodTargetRegistrarTests {
public void foo1(@ShellOption("x") boolean arg1) {
}
}
@Test
void OptionWithCustomType() {
applicationContext = new AnnotationConfigApplicationContext(OptionWithCustomType.class);
registrar.setApplicationContext(applicationContext);
registrar.register(catalog);
assertThat(catalog.getRegistrations().get("foo1")).isNotNull();
assertThat(catalog.getRegistrations().get("foo1")).satisfies(reg -> {
assertThat(reg.getOptions().get(0)).satisfies(option -> {
assertThat(option.getType().getGeneric(0).getType()).isEqualTo(Pojo.class);
});
});
}
@ShellComponent
public static class OptionWithCustomType {
@ShellMethod(value = "foo1", prefix = "-")
public void foo1(@ShellOption Set<Pojo> arg1) {
}
}
public static class Pojo {
}
}