Polish SpEL Javadocs and internals
This commit is contained in:
@@ -112,6 +112,24 @@ class ParsingTests {
|
||||
parseCheck("#var1='value1'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexing() {
|
||||
parseCheck("#var[2]");
|
||||
parseCheck("person['name']");
|
||||
parseCheck("person[name]");
|
||||
parseCheck("array[2]");
|
||||
parseCheck("array[2][3]");
|
||||
parseCheck("func()[2]");
|
||||
parseCheck("#func()[2]");
|
||||
parseCheck("'abc'[2]");
|
||||
parseCheck("\"abc\"[2]", "'abc'[2]");
|
||||
parseCheck("{1,2,3}[2]");
|
||||
parseCheck("{'k':'v'}['k']");
|
||||
parseCheck("{'k':'v'}[k]");
|
||||
parseCheck("{'k1':'v1','k2':'v2'}['k2']");
|
||||
parseCheck("{'k1':'v1','k2':'v2'}[k2]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void projection() {
|
||||
parseCheck("{1,2,3,4,5,6,7,8,9,10}.![#isEven()]");
|
||||
|
||||
@@ -40,15 +40,22 @@ import org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMat
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind.CLOSE;
|
||||
import static org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind.EXACT;
|
||||
import static org.springframework.expression.spel.support.ReflectionHelper.ArgumentsMatchKind.REQUIRES_CONVERSION;
|
||||
|
||||
/**
|
||||
* Tests for reflection helper code.
|
||||
* Tests for {@link ReflectionHelper}, {@link SpelUtilities}, {@link TypedValue},
|
||||
* {@link ReflectivePropertyAccessor}, ...
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
|
||||
private final StandardTypeConverter tc = new StandardTypeConverter();
|
||||
|
||||
|
||||
@Test
|
||||
void utilities() throws ParseException {
|
||||
SpelExpression expr = (SpelExpression)parser.parseExpression("3+4+5+6+7-2");
|
||||
@@ -100,44 +107,38 @@ class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
|
||||
@Test
|
||||
void reflectionHelperCompareArguments_ExactMatching() {
|
||||
StandardTypeConverter tc = new StandardTypeConverter();
|
||||
|
||||
// Calling foo(String) with (String) is exact match
|
||||
checkMatch(new Class<?>[] {String.class}, new Class<?>[] {String.class}, tc, ReflectionHelper.ArgumentsMatchKind.EXACT);
|
||||
checkMatch(new Class<?>[] {String.class}, new Class<?>[] {String.class}, tc, EXACT);
|
||||
|
||||
// Calling foo(String,Integer) with (String,Integer) is exact match
|
||||
checkMatch(new Class<?>[] {String.class, Integer.class}, new Class<?>[] {String.class, Integer.class}, tc, ArgumentsMatchKind.EXACT);
|
||||
checkMatch(new Class<?>[] {String.class, Integer.class}, new Class<?>[] {String.class, Integer.class}, tc, EXACT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void reflectionHelperCompareArguments_CloseMatching() {
|
||||
StandardTypeConverter tc = new StandardTypeConverter();
|
||||
|
||||
// Calling foo(List) with (ArrayList) is close match (no conversion required)
|
||||
checkMatch(new Class<?>[] {ArrayList.class}, new Class<?>[] {List.class}, tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatch(new Class<?>[] {ArrayList.class}, new Class<?>[] {List.class}, tc, CLOSE);
|
||||
|
||||
// Passing (Sub,String) on call to foo(Super,String) is close match
|
||||
checkMatch(new Class<?>[] {Sub.class, String.class}, new Class<?>[] {Super.class, String.class}, tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatch(new Class<?>[] {Sub.class, String.class}, new Class<?>[] {Super.class, String.class}, tc, CLOSE);
|
||||
|
||||
// Passing (String,Sub) on call to foo(String,Super) is close match
|
||||
checkMatch(new Class<?>[] {String.class, Sub.class}, new Class<?>[] {String.class, Super.class}, tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatch(new Class<?>[] {String.class, Sub.class}, new Class<?>[] {String.class, Super.class}, tc, CLOSE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void reflectionHelperCompareArguments_RequiresConversionMatching() {
|
||||
StandardTypeConverter tc = new StandardTypeConverter();
|
||||
|
||||
void reflectionHelperCompareArguments_CloseMatching_WithAutoBoxing() {
|
||||
// Calling foo(String,int) with (String,Integer) requires boxing conversion of argument one
|
||||
checkMatch(new Class<?>[] {String.class, int.class}, new Class<?>[] {String.class,Integer.class},tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatch(new Class<?>[] {String.class, int.class}, new Class<?>[] {String.class, Integer.class},tc, CLOSE);
|
||||
|
||||
// Passing (int,String) on call to foo(Integer,String) requires boxing conversion of argument zero
|
||||
checkMatch(new Class<?>[] {int.class, String.class}, new Class<?>[] {Integer.class, String.class},tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatch(new Class<?>[] {int.class, String.class}, new Class<?>[] {Integer.class, String.class},tc, CLOSE);
|
||||
|
||||
// Passing (int,Sub) on call to foo(Integer,Super) requires boxing conversion of argument zero
|
||||
checkMatch(new Class<?>[] {int.class, Sub.class}, new Class<?>[] {Integer.class, Super.class}, tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatch(new Class<?>[] {int.class, Sub.class}, new Class<?>[] {Integer.class, Super.class}, tc, CLOSE);
|
||||
|
||||
// Passing (int,Sub,boolean) on call to foo(Integer,Super,Boolean) requires boxing conversion of arguments zero and two
|
||||
// TODO checkMatch(new Class<?>[] {int.class, Sub.class, boolean.class}, new Class<?>[] {Integer.class, Super.class, Boolean.class}, tc, ArgsMatchKind.REQUIRES_CONVERSION);
|
||||
checkMatch(new Class<?>[] {int.class, Sub.class, boolean.class}, new Class<?>[] {Integer.class, Super.class, Boolean.class}, tc, CLOSE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -149,59 +150,56 @@ class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void reflectionHelperCompareArguments_Varargs_ExactMatching() {
|
||||
StandardTypeConverter tc = new StandardTypeConverter();
|
||||
|
||||
void reflectionHelperCompareArguments_Varargs() {
|
||||
// Passing (String[]) on call to (String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {String[].class}, new Class<?>[] {String[].class}, tc, ArgumentsMatchKind.EXACT);
|
||||
checkMatchVarargs(new Class<?>[] {String[].class}, new Class<?>[] {String[].class}, tc, EXACT);
|
||||
|
||||
// Passing (Integer, String[]) on call to (Integer, String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {Integer.class, String[].class}, new Class<?>[] {Integer.class, String[].class}, tc, ArgumentsMatchKind.EXACT);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, String[].class}, new Class<?>[] {Integer.class, String[].class}, tc, EXACT);
|
||||
|
||||
// Passing (String, Integer, String[]) on call to (String, String, String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {String.class, Integer.class, String[].class}, new Class<?>[] {String.class,Integer.class, String[].class}, tc, ArgumentsMatchKind.EXACT);
|
||||
checkMatchVarargs(new Class<?>[] {String.class, Integer.class, String[].class}, new Class<?>[] {String.class,Integer.class, String[].class}, tc, EXACT);
|
||||
|
||||
// Passing (Sub, String[]) on call to (Super, String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {Sub.class, String[].class}, new Class<?>[] {Super.class,String[].class}, tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatchVarargs(new Class<?>[] {Sub.class, String[].class}, new Class<?>[] {Super.class,String[].class}, tc, CLOSE);
|
||||
|
||||
// Passing (Integer, String[]) on call to (String, String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {Integer.class, String[].class}, new Class<?>[] {String.class, String[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, String[].class}, new Class<?>[] {String.class, String[].class}, tc, REQUIRES_CONVERSION);
|
||||
|
||||
// Passing (Integer, Sub, String[]) on call to (String, Super, String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {Integer.class, Sub.class, String[].class}, new Class<?>[] {String.class, Super.class, String[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, Sub.class, String[].class}, new Class<?>[] {String.class, Super.class, String[].class}, tc, REQUIRES_CONVERSION);
|
||||
|
||||
// Passing (String) on call to (String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {String.class}, new Class<?>[] {String[].class}, tc, ArgumentsMatchKind.EXACT);
|
||||
checkMatchVarargs(new Class<?>[] {String.class}, new Class<?>[] {String[].class}, tc, EXACT);
|
||||
|
||||
// Passing (Integer,String) on call to (Integer,String[]) is exact match
|
||||
checkMatch2(new Class<?>[] {Integer.class, String.class}, new Class<?>[] {Integer.class, String[].class}, tc, ArgumentsMatchKind.EXACT);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, String.class}, new Class<?>[] {Integer.class, String[].class}, tc, EXACT);
|
||||
|
||||
// Passing (String) on call to (Integer[]) is conversion match (String to Integer)
|
||||
checkMatch2(new Class<?>[] {String.class}, new Class<?>[] {Integer[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
|
||||
checkMatchVarargs(new Class<?>[] {String.class}, new Class<?>[] {Integer[].class}, tc, REQUIRES_CONVERSION);
|
||||
|
||||
// Passing (Sub) on call to (Super[]) is close match
|
||||
checkMatch2(new Class<?>[] {Sub.class}, new Class<?>[] {Super[].class}, tc, ArgumentsMatchKind.CLOSE);
|
||||
checkMatchVarargs(new Class<?>[] {Sub.class}, new Class<?>[] {Super[].class}, tc, CLOSE);
|
||||
|
||||
// Passing (Super) on call to (Sub[]) is not a match
|
||||
checkMatch2(new Class<?>[] {Super.class}, new Class<?>[] {Sub[].class}, tc, null);
|
||||
checkMatchVarargs(new Class<?>[] {Super.class}, new Class<?>[] {Sub[].class}, tc, null);
|
||||
|
||||
checkMatch2(new Class<?>[] {Unconvertable.class, String.class}, new Class<?>[] {Sub.class, Super[].class}, tc, null);
|
||||
checkMatchVarargs(new Class<?>[] {Unconvertable.class, String.class}, new Class<?>[] {Sub.class, Super[].class}, tc, null);
|
||||
|
||||
checkMatch2(new Class<?>[] {Integer.class, Integer.class, String.class}, new Class<?>[] {String.class, String.class, Super[].class}, tc, null);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, Integer.class, String.class}, new Class<?>[] {String.class, String.class, Super[].class}, tc, null);
|
||||
|
||||
checkMatch2(new Class<?>[] {Unconvertable.class, String.class}, new Class<?>[] {Sub.class, Super[].class}, tc, null);
|
||||
checkMatchVarargs(new Class<?>[] {Unconvertable.class, String.class}, new Class<?>[] {Sub.class, Super[].class}, tc, null);
|
||||
|
||||
checkMatch2(new Class<?>[] {Integer.class, Integer.class, String.class}, new Class<?>[] {String.class, String.class, Super[].class}, tc, null);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, Integer.class, String.class}, new Class<?>[] {String.class, String.class, Super[].class}, tc, null);
|
||||
|
||||
checkMatch2(new Class<?>[] {Integer.class, Integer.class, Sub.class}, new Class<?>[] {String.class, String.class, Super[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, Integer.class, Sub.class}, new Class<?>[] {String.class, String.class, Super[].class}, tc, REQUIRES_CONVERSION);
|
||||
|
||||
checkMatch2(new Class<?>[] {Integer.class, Integer.class, Integer.class}, new Class<?>[] {Integer.class, String[].class}, tc, ArgumentsMatchKind.REQUIRES_CONVERSION);
|
||||
checkMatchVarargs(new Class<?>[] {Integer.class, Integer.class, Integer.class}, new Class<?>[] {Integer.class, String[].class}, tc, REQUIRES_CONVERSION);
|
||||
// what happens on (Integer,String) passed to (Integer[]) ?
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertArguments() throws Exception {
|
||||
StandardTypeConverter tc = new StandardTypeConverter();
|
||||
Method oneArg = TestInterface.class.getMethod("oneArg", String.class);
|
||||
Method twoArg = TestInterface.class.getMethod("twoArg", String.class, String[].class);
|
||||
|
||||
@@ -227,8 +225,7 @@ class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void convertArguments2() throws Exception {
|
||||
StandardTypeConverter tc = new StandardTypeConverter();
|
||||
void convertAllArguments() throws Exception {
|
||||
Method oneArg = TestInterface.class.getMethod("oneArg", String.class);
|
||||
Method twoArg = TestInterface.class.getMethod("twoArg", String.class, String[].class);
|
||||
|
||||
@@ -254,7 +251,7 @@ class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void setupArguments() {
|
||||
void setupArgumentsForVarargsInvocation() {
|
||||
Object[] newArray = ReflectionHelper.setupArgumentsForVarargsInvocation(
|
||||
new Class<?>[] {String[].class}, "a", "b", "c");
|
||||
|
||||
@@ -402,21 +399,21 @@ class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
assertThat(matchInfo).as("Should not be a null match").isNotNull();
|
||||
}
|
||||
|
||||
if (expectedMatchKind == ArgumentsMatchKind.EXACT) {
|
||||
if (expectedMatchKind == EXACT) {
|
||||
assertThat(matchInfo.isExactMatch()).isTrue();
|
||||
}
|
||||
else if (expectedMatchKind == ArgumentsMatchKind.CLOSE) {
|
||||
else if (expectedMatchKind == CLOSE) {
|
||||
assertThat(matchInfo.isCloseMatch()).isTrue();
|
||||
}
|
||||
else if (expectedMatchKind == ArgumentsMatchKind.REQUIRES_CONVERSION) {
|
||||
else if (expectedMatchKind == REQUIRES_CONVERSION) {
|
||||
assertThat(matchInfo.isMatchRequiringConversion()).as("expected to be a match requiring conversion, but was " + matchInfo).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to validate the match returned from a compareArguments call.
|
||||
* Used to validate the match returned from a compareArgumentsVarargs call.
|
||||
*/
|
||||
private static void checkMatch2(Class<?>[] inputTypes, Class<?>[] expectedTypes,
|
||||
private static void checkMatchVarargs(Class<?>[] inputTypes, Class<?>[] expectedTypes,
|
||||
StandardTypeConverter typeConverter, ArgumentsMatchKind expectedMatchKind) {
|
||||
|
||||
ReflectionHelper.ArgumentsMatchInfo matchInfo =
|
||||
@@ -438,14 +435,10 @@ class ReflectionHelperTests extends AbstractExpressionTests {
|
||||
private static void checkArguments(Object[] args, Object... expected) {
|
||||
assertThat(args).hasSize(expected.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
checkArgument(expected[i], args[i]);
|
||||
assertThat(args[i]).isEqualTo(expected[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkArgument(Object expected, Object actual) {
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
private static List<TypeDescriptor> typeDescriptors(Class<?>... types) {
|
||||
return Arrays.stream(types).map(TypeDescriptor::valueOf).toList();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user