Polishing
This commit is contained in:
@@ -957,7 +957,7 @@ public class CodeFlow implements Opcodes {
|
|||||||
*/
|
*/
|
||||||
public static void insertOptimalLoad(MethodVisitor mv, int value) {
|
public static void insertOptimalLoad(MethodVisitor mv, int value) {
|
||||||
if (value < 6) {
|
if (value < 6) {
|
||||||
mv.visitInsn(ICONST_0+value);
|
mv.visitInsn(ICONST_0 + value);
|
||||||
}
|
}
|
||||||
else if (value < Byte.MAX_VALUE) {
|
else if (value < Byte.MAX_VALUE) {
|
||||||
mv.visitIntInsn(BIPUSH, value);
|
mv.visitIntInsn(BIPUSH, value);
|
||||||
@@ -971,15 +971,16 @@ public class CodeFlow implements Opcodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce appropriate bytecode to store a stack item in an array. The
|
* Produce appropriate bytecode to store a stack item in an array.
|
||||||
* instruction to use varies depending on whether the type
|
* <p>The instruction to use varies depending on whether the type is a
|
||||||
* is a primitive or reference type.
|
* primitive or reference type.
|
||||||
* @param mv where to insert the bytecode
|
* @param mv where to insert the bytecode
|
||||||
* @param arrayElementType the type of the array elements
|
* @param arrayComponentType the component type of the array
|
||||||
*/
|
*/
|
||||||
public static void insertArrayStore(MethodVisitor mv, String arrayElementType) {
|
public static void insertArrayStore(MethodVisitor mv, String arrayComponentType) {
|
||||||
if (arrayElementType.length() == 1) {
|
if (arrayComponentType.length() == 1) {
|
||||||
switch (arrayElementType.charAt(0)) {
|
char componentType = arrayComponentType.charAt(0);
|
||||||
|
switch (componentType) {
|
||||||
case 'B', 'Z' -> mv.visitInsn(BASTORE);
|
case 'B', 'Z' -> mv.visitInsn(BASTORE);
|
||||||
case 'I' -> mv.visitInsn(IASTORE);
|
case 'I' -> mv.visitInsn(IASTORE);
|
||||||
case 'J' -> mv.visitInsn(LASTORE);
|
case 'J' -> mv.visitInsn(LASTORE);
|
||||||
@@ -987,7 +988,7 @@ public class CodeFlow implements Opcodes {
|
|||||||
case 'D' -> mv.visitInsn(DASTORE);
|
case 'D' -> mv.visitInsn(DASTORE);
|
||||||
case 'C' -> mv.visitInsn(CASTORE);
|
case 'C' -> mv.visitInsn(CASTORE);
|
||||||
case 'S' -> mv.visitInsn(SASTORE);
|
case 'S' -> mv.visitInsn(SASTORE);
|
||||||
default -> throw new IllegalArgumentException("Unexpected array type " + arrayElementType.charAt(0));
|
default -> throw new IllegalArgumentException("Unexpected array component type " + componentType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -211,18 +211,22 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate code that handles building the argument values for the specified method.
|
* Generate code that handles building the argument values for the specified
|
||||||
* <p>This method will take into account whether the invoked method is a varargs method,
|
* {@link Member} (method or constructor).
|
||||||
* and if it is then the argument values will be appropriately packaged into an array.
|
* <p>This method takes into account whether the method or constructor was
|
||||||
|
* declared to accept varargs, and if it was then the argument values will be
|
||||||
|
* appropriately packaged into an array.
|
||||||
* @param mv the method visitor where code should be generated
|
* @param mv the method visitor where code should be generated
|
||||||
* @param cf the current codeflow
|
* @param cf the current {@link CodeFlow}
|
||||||
* @param member the method or constructor for which arguments are being set up
|
* @param member the method or constructor for which arguments are being set up
|
||||||
* @param arguments the expression nodes for the expression supplied argument values
|
* @param arguments the expression nodes for the expression supplied argument values
|
||||||
* @deprecated As of Spring Framework 6.2, in favor of
|
* @deprecated As of Spring Framework 6.2, in favor of
|
||||||
* {@link #generateCodeForArguments(MethodVisitor, CodeFlow, Executable, SpelNodeImpl[])}
|
* {@link #generateCodeForArguments(MethodVisitor, CodeFlow, Executable, SpelNodeImpl[])}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "6.2")
|
@Deprecated(since = "6.2")
|
||||||
protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Member member, SpelNodeImpl[] arguments) {
|
protected static void generateCodeForArguments(
|
||||||
|
MethodVisitor mv, CodeFlow cf, Member member, SpelNodeImpl[] arguments) {
|
||||||
|
|
||||||
if (member instanceof Executable executable) {
|
if (member instanceof Executable executable) {
|
||||||
generateCodeForArguments(mv, cf, executable, arguments);
|
generateCodeForArguments(mv, cf, executable, arguments);
|
||||||
}
|
}
|
||||||
@@ -233,7 +237,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||||||
/**
|
/**
|
||||||
* Generate code that handles building the argument values for the specified
|
* Generate code that handles building the argument values for the specified
|
||||||
* {@link Executable} (method or constructor).
|
* {@link Executable} (method or constructor).
|
||||||
* <p>This method takes into account whether the invoked executable was
|
* <p>This method takes into account whether the method or constructor was
|
||||||
* declared to accept varargs, and if it was then the argument values will be
|
* declared to accept varargs, and if it was then the argument values will be
|
||||||
* appropriately packaged into an array.
|
* appropriately packaged into an array.
|
||||||
* @param mv the method visitor where code should be generated
|
* @param mv the method visitor where code should be generated
|
||||||
@@ -244,52 +248,56 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||||||
* values
|
* values
|
||||||
* @since 6.2
|
* @since 6.2
|
||||||
*/
|
*/
|
||||||
protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Executable executable, SpelNodeImpl[] arguments) {
|
protected static void generateCodeForArguments(
|
||||||
|
MethodVisitor mv, CodeFlow cf, Executable executable, SpelNodeImpl[] arguments) {
|
||||||
|
|
||||||
Class<?>[] parameterTypes = executable.getParameterTypes();
|
Class<?>[] parameterTypes = executable.getParameterTypes();
|
||||||
String[] paramDescriptors = CodeFlow.toDescriptors(parameterTypes);
|
String[] parameterDescriptors = CodeFlow.toDescriptors(parameterTypes);
|
||||||
|
int parameterCount = parameterTypes.length;
|
||||||
|
|
||||||
if (executable.isVarArgs()) {
|
if (executable.isVarArgs()) {
|
||||||
// The final parameter may or may not need packaging into an array, or nothing may
|
// The final parameter may or may not need packaging into an array, or nothing may
|
||||||
// have been passed to satisfy the varargs and so something needs to be built.
|
// have been passed to satisfy the varargs which means something needs to be built.
|
||||||
int p = 0; // Current supplied argument being processed
|
|
||||||
int childCount = arguments.length;
|
|
||||||
|
|
||||||
// Fulfill all the parameter requirements except the last one
|
int varargsIndex = parameterCount - 1;
|
||||||
for (p = 0; p < paramDescriptors.length - 1; p++) {
|
int argumentCount = arguments.length;
|
||||||
cf.generateCodeForArgument(mv, arguments[p], paramDescriptors[p]);
|
int p = 0; // Current supplied argument being processed
|
||||||
|
|
||||||
|
// Fulfill all the parameter requirements except the last one (the varargs array).
|
||||||
|
for (p = 0; p < varargsIndex; p++) {
|
||||||
|
cf.generateCodeForArgument(mv, arguments[p], parameterDescriptors[p]);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpelNodeImpl lastChild = (childCount == 0 ? null : arguments[childCount - 1]);
|
SpelNodeImpl lastArgument = (argumentCount != 0 ? arguments[argumentCount - 1] : null);
|
||||||
ClassLoader classLoader = executable.getDeclaringClass().getClassLoader();
|
ClassLoader classLoader = executable.getDeclaringClass().getClassLoader();
|
||||||
Class<?> lastChildType = (lastChild != null ?
|
Class<?> lastArgumentType = (lastArgument != null ?
|
||||||
loadClassForExitDescriptor(lastChild.getExitDescriptor(), classLoader) : null);
|
loadClassForExitDescriptor(lastArgument.getExitDescriptor(), classLoader) : null);
|
||||||
Class<?> lastParameterType = parameterTypes[parameterTypes.length - 1];
|
Class<?> lastParameterType = parameterTypes[varargsIndex];
|
||||||
|
|
||||||
// Determine if the final passed argument is already suitably packaged in array
|
// Determine if the final passed argument is already suitably packaged in array
|
||||||
// form to be passed to the method
|
// form to be passed to the method.
|
||||||
if (lastChild != null && lastChildType != null && lastParameterType.isAssignableFrom(lastChildType)) {
|
if (lastArgument != null && lastArgumentType != null && lastParameterType.isAssignableFrom(lastArgumentType)) {
|
||||||
cf.generateCodeForArgument(mv, lastChild, paramDescriptors[p]);
|
cf.generateCodeForArgument(mv, lastArgument, parameterDescriptors[p]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
String arrayType = paramDescriptors[paramDescriptors.length - 1];
|
String arrayComponentType = parameterDescriptors[varargsIndex];
|
||||||
arrayType = arrayType.substring(1); // trim the leading '[', may leave other '['
|
// Trim the leading '[', potentially leaving other '[' characters.
|
||||||
// build array big enough to hold remaining arguments
|
arrayComponentType = arrayComponentType.substring(1);
|
||||||
CodeFlow.insertNewArrayCode(mv, childCount - p, arrayType);
|
// Build array big enough to hold remaining arguments.
|
||||||
// Package up the remaining arguments into the array
|
CodeFlow.insertNewArrayCode(mv, argumentCount - p, arrayComponentType);
|
||||||
int arrayindex = 0;
|
// Package up the remaining arguments into the array.
|
||||||
while (p < childCount) {
|
int arrayIndex = 0;
|
||||||
SpelNodeImpl child = arguments[p];
|
while (p < argumentCount) {
|
||||||
mv.visitInsn(DUP);
|
mv.visitInsn(DUP);
|
||||||
CodeFlow.insertOptimalLoad(mv, arrayindex++);
|
CodeFlow.insertOptimalLoad(mv, arrayIndex++);
|
||||||
cf.generateCodeForArgument(mv, child, arrayType);
|
cf.generateCodeForArgument(mv, arguments[p++], arrayComponentType);
|
||||||
CodeFlow.insertArrayStore(mv, arrayType);
|
CodeFlow.insertArrayStore(mv, arrayComponentType);
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < paramDescriptors.length;i++) {
|
for (int i = 0; i < parameterCount; i++) {
|
||||||
cf.generateCodeForArgument(mv, arguments[i], paramDescriptors[i]);
|
cf.generateCodeForArgument(mv, arguments[i], parameterDescriptors[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,8 +316,10 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask an argument to generate its bytecode and then follow it up
|
* Generate bytecode that loads the supplied argument onto the stack.
|
||||||
* with any boxing/unboxing/checkcasting to ensure it matches the expected parameter descriptor.
|
* <p>This method also performs any boxing, unboxing, or check-casting
|
||||||
|
* necessary to ensure that the type of the argument on the stack matches the
|
||||||
|
* supplied {@code paramDesc}.
|
||||||
* @deprecated As of Spring Framework 6.2, in favor of
|
* @deprecated As of Spring Framework 6.2, in favor of
|
||||||
* {@link CodeFlow#generateCodeForArgument(MethodVisitor, SpelNode, String)}
|
* {@link CodeFlow#generateCodeForArgument(MethodVisitor, SpelNode, String)}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2642,14 +2642,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
assertThat(expression.getValue(context)).isEqualTo(20);
|
assertThat(expression.getValue(context)).isEqualTo(20);
|
||||||
|
|
||||||
|
|
||||||
expression = parser.parseExpression("#appendChar('abc'.charAt(0),'abc'.charAt(1))");
|
expression = parser.parseExpression("#appendChar('abc'.charAt(0),'abc'.charAt(1))");
|
||||||
assertThat(expression.getValue(context)).isEqualTo("ab");
|
assertThat(expression.getValue(context)).isEqualTo("ab");
|
||||||
assertThat(((SpelExpression) expression).getAST().isCompilable()).isTrue();
|
assertThat(((SpelExpression) expression).getAST().isCompilable()).isTrue();
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
assertThat(expression.getValue(context)).isEqualTo("ab");
|
assertThat(expression.getValue(context)).isEqualTo("ab");
|
||||||
|
|
||||||
|
|
||||||
expression = parser.parseExpression("#append4('a','b','c')");
|
expression = parser.parseExpression("#append4('a','b','c')");
|
||||||
assertThat(expression.getValue(context).toString()).isEqualTo("a::bc");
|
assertThat(expression.getValue(context).toString()).isEqualTo("a::bc");
|
||||||
assertThat(((SpelExpression) expression).getAST().isCompilable()).isTrue();
|
assertThat(((SpelExpression) expression).getAST().isCompilable()).isTrue();
|
||||||
@@ -3259,7 +3257,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||||||
assertThat(b).isTrue();
|
assertThat(b).isTrue();
|
||||||
assertThat(aa.gotComparedTo).isEqualTo(bb);
|
assertThat(aa.gotComparedTo).isEqualTo(bb);
|
||||||
|
|
||||||
|
|
||||||
List<String> ls = new ArrayList<>();
|
List<String> ls = new ArrayList<>();
|
||||||
ls.add("foo");
|
ls.add("foo");
|
||||||
StandardEvaluationContext context = new StandardEvaluationContext(ls);
|
StandardEvaluationContext context = new StandardEvaluationContext(ls);
|
||||||
@@ -4682,7 +4679,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||||||
assertThat(expression.getValue(Boolean.class)).isNull();
|
assertThat(expression.getValue(Boolean.class)).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test variants of using T(...) and static/non-static method/property/field references.
|
* Test variants of using T(...) and static/non-static method/property/field references.
|
||||||
*/
|
*/
|
||||||
@@ -4775,7 +4771,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||||||
assertThat(expression.getValue(StaticsHelper.sh)).isEqualTo("mb");
|
assertThat(expression.getValue(StaticsHelper.sh)).isEqualTo("mb");
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
assertThat(expression.getValue(StaticsHelper.sh)).isEqualTo("mb");
|
assertThat(expression.getValue(StaticsHelper.sh)).isEqualTo("mb");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -4863,86 +4858,89 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
|||||||
context = new StandardEvaluationContext(new Object[] {person.getAge()});
|
context = new StandardEvaluationContext(new Object[] {person.getAge()});
|
||||||
context.setVariable("it", person);
|
context.setVariable("it", person);
|
||||||
assertThat(ex.getValue(context, Boolean.class)).isTrue();
|
assertThat(ex.getValue(context, Boolean.class)).isTrue();
|
||||||
assertThat(ex.getValue(context, Boolean.class)).isTrue();
|
|
||||||
|
|
||||||
PersonInOtherPackage person2 = new PersonInOtherPackage(1);
|
PersonInOtherPackage person2 = new PersonInOtherPackage(1);
|
||||||
ex = parser.parseRaw("#it?.age.equals([0])");
|
ex = parser.parseRaw("#it?.age.equals([0])");
|
||||||
context = new StandardEvaluationContext(new Object[] {person2.getAge()});
|
context = new StandardEvaluationContext(new Object[] {person2.getAge()});
|
||||||
context.setVariable("it", person2);
|
context.setVariable("it", person2);
|
||||||
assertThat(ex.getValue(context, Boolean.class)).isTrue();
|
assertThat(ex.getValue(context, Boolean.class)).isTrue();
|
||||||
assertThat(ex.getValue(context, Boolean.class)).isTrue();
|
|
||||||
|
|
||||||
ex = parser.parseRaw("#it?.age.equals([0])");
|
ex = parser.parseRaw("#it?.age.equals([0])");
|
||||||
context = new StandardEvaluationContext(new Object[] {person2.getAge()});
|
context = new StandardEvaluationContext(new Object[] {person2.getAge()});
|
||||||
context.setVariable("it", person2);
|
context.setVariable("it", person2);
|
||||||
assertThat((Boolean) ex.getValue(context)).isTrue();
|
assertThat((Boolean) ex.getValue(context)).isTrue();
|
||||||
assertThat((Boolean) ex.getValue(context)).isTrue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void constructorReference() {
|
void constructorReference() {
|
||||||
// simple ctor
|
// simple constructor
|
||||||
expression = parser.parseExpression("new String('123')");
|
expression = parser.parseExpression("new String('123')");
|
||||||
assertThat(expression.getValue()).isEqualTo("123");
|
assertThat(expression.getValue()).isEqualTo("123");
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
assertThat(expression.getValue()).isEqualTo("123");
|
assertThat(expression.getValue()).isEqualTo("123");
|
||||||
|
|
||||||
String testclass8 = "org.springframework.expression.spel.SpelCompilationCoverageTests$TestClass8";
|
String testclass8 = TestClass8.class.getName();
|
||||||
// multi arg ctor that includes primitives
|
Object result;
|
||||||
|
|
||||||
|
// multi arg constructor that includes primitives
|
||||||
expression = parser.parseExpression("new " + testclass8 + "(42,'123',4.0d,true)");
|
expression = parser.parseExpression("new " + testclass8 + "(42,'123',4.0d,true)");
|
||||||
assertThat(expression.getValue().getClass().getName()).isEqualTo(testclass8);
|
result = expression.getValue();
|
||||||
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
Object o = expression.getValue();
|
result = expression.getValue();
|
||||||
assertThat(o.getClass().getName()).isEqualTo(testclass8);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
TestClass8 tc8 = (TestClass8) o;
|
TestClass8 tc8 = (TestClass8) result;
|
||||||
assertThat(tc8.i).isEqualTo(42);
|
assertThat(tc8.i).isEqualTo(42);
|
||||||
assertThat(tc8.s).isEqualTo("123");
|
assertThat(tc8.s).isEqualTo("123");
|
||||||
assertThat(tc8.d).isCloseTo(4.0d, within(0.5d));
|
assertThat(tc8.d).isCloseTo(4.0d, within(0.5d));
|
||||||
|
|
||||||
assertThat(tc8.z).isTrue();
|
assertThat(tc8.z).isTrue();
|
||||||
|
|
||||||
// no-arg ctor
|
// no-arg constructor
|
||||||
expression = parser.parseExpression("new " + testclass8 + "()");
|
expression = parser.parseExpression("new " + testclass8 + "()");
|
||||||
assertThat(expression.getValue().getClass().getName()).isEqualTo(testclass8);
|
result = expression.getValue();
|
||||||
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
o = expression.getValue();
|
result = expression.getValue();
|
||||||
assertThat(o.getClass().getName()).isEqualTo(testclass8);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
|
|
||||||
// pass primitive to reference type ctor
|
// pass primitive to reference type constructor
|
||||||
expression = parser.parseExpression("new " + testclass8 + "(42)");
|
expression = parser.parseExpression("new " + testclass8 + "(42)");
|
||||||
assertThat(expression.getValue().getClass().getName()).isEqualTo(testclass8);
|
result = expression.getValue();
|
||||||
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
o = expression.getValue();
|
result = expression.getValue();
|
||||||
assertThat(o.getClass().getName()).isEqualTo(testclass8);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
tc8 = (TestClass8) o;
|
tc8 = (TestClass8) result;
|
||||||
assertThat(tc8.i).isEqualTo(42);
|
assertThat(tc8.i).isEqualTo(42);
|
||||||
|
|
||||||
// varargs
|
// varargs
|
||||||
expression = parser.parseExpression("new " + testclass8 + "(#root)");
|
expression = parser.parseExpression("new " + testclass8 + "(#root)");
|
||||||
Object[] objectArray = { "a", "b", "c" };
|
Object[] objectArray = { "a", "b", "c" };
|
||||||
o = expression.getValue(objectArray);
|
result = expression.getValue(objectArray);
|
||||||
assertThat(o).isExactlyInstanceOf(TestClass8.class);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
o = expression.getValue(objectArray);
|
result = expression.getValue(objectArray);
|
||||||
assertThat(o).isExactlyInstanceOf(TestClass8.class);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
tc8 = (TestClass8) o;
|
tc8 = (TestClass8) result;
|
||||||
assertThat(tc8.args).containsExactly("a", "b", "c");
|
assertThat(tc8.args).containsExactly("a", "b", "c");
|
||||||
|
|
||||||
// varargs with argument component type that is a subtype of the varargs component type.
|
// varargs with argument component type that is a subtype of the varargs component type.
|
||||||
expression = parser.parseExpression("new " + testclass8 + "(#root)");
|
expression = parser.parseExpression("new " + testclass8 + "(#root)");
|
||||||
String[] stringArray = { "a", "b", "c" };
|
String[] stringArray = { "a", "b", "c" };
|
||||||
o = expression.getValue(stringArray);
|
result = expression.getValue(stringArray);
|
||||||
assertThat(o).isExactlyInstanceOf(TestClass8.class);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
assertCanCompile(expression);
|
assertCanCompile(expression);
|
||||||
o = expression.getValue(stringArray);
|
result = expression.getValue(stringArray);
|
||||||
assertThat(o).isExactlyInstanceOf(TestClass8.class);
|
assertThat(result).isExactlyInstanceOf(TestClass8.class);
|
||||||
tc8 = (TestClass8) o;
|
tc8 = (TestClass8) result;
|
||||||
assertThat(tc8.args).containsExactly("a", "b", "c");
|
assertThat(tc8.args).containsExactly("a", "b", "c");
|
||||||
|
|
||||||
// private class, can't compile it
|
// private class, can't compile it
|
||||||
String testclass9 = "org.springframework.expression.spel.SpelCompilationCoverageTests$TestClass9";
|
String testclass9 = TestClass9.class.getName();
|
||||||
expression = parser.parseExpression("new " + testclass9 + "(42)");
|
expression = parser.parseExpression("new " + testclass9 + "(42)");
|
||||||
assertThat(expression.getValue().getClass().getName()).isEqualTo(testclass9);
|
result = expression.getValue();
|
||||||
|
assertThat(result).isExactlyInstanceOf(TestClass9.class);
|
||||||
assertCannotCompile(expression);
|
assertCannotCompile(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user