Merge branch '7.0.x'

This commit is contained in:
Sam Brannen
2026-04-12 14:29:42 +02:00
2 changed files with 47 additions and 57 deletions
@@ -151,12 +151,14 @@ class EvaluationTests extends AbstractExpressionTests {
@Test
void elvisOperator() {
evaluate("'Andy'?:'Dave'", "Andy", String.class);
evaluate("null?:'Dave'", "Dave", String.class);
evaluate("3?:1", 3, Integer.class);
evaluate("(2*3)?:1*10", 6, Integer.class);
evaluate("null?:2*10", 20, Integer.class);
evaluate("(null?:1)*10", 10, Integer.class);
evaluate("'Andy' ?: 'Dave'", "Andy", String.class);
evaluate("null ?: 'Dave'", "Dave", String.class);
evaluate("3 ?: 1", 3, Integer.class);
evaluate("(2 * 3) ?: 1 * 10", 6, Integer.class);
evaluate("null ?: 2 * 10", 20, Integer.class);
evaluate("(null ?: 1) * 10", 10, Integer.class);
evaluate("3 ?: #var = 5", 3, Integer.class);
evaluate("null ?: #var = 5", 5, Integer.class);
}
@Test
@@ -721,59 +723,41 @@ class EvaluationTests extends AbstractExpressionTests {
class TernaryOperatorTests {
@Test
void ternaryOperator01() {
evaluate("2>4?1:2", 2, Integer.class);
void ternaryExpressionWithNullConditionType() {
// cannot convert null to boolean
evaluateAndCheckError("null ? 0 : 1", SpelMessage.TYPE_CONVERSION_ERROR);
}
@Test
void ternaryOperator02() {
evaluate("'abc'=='abc'?1:2", 1, Integer.class);
}
@Test
void ternaryOperator03() {
void ternaryExpressionWithInvalidConditionType() {
// cannot convert String to boolean
evaluateAndCheckError("'hello'?1:2", SpelMessage.TYPE_CONVERSION_ERROR);
evaluateAndCheckError("'hello' ? 1 : 2", SpelMessage.TYPE_CONVERSION_ERROR);
}
@Test
void ternaryOperator04() {
Expression e = parser.parseExpression("1>2?3:4");
assertThat(e.isWritable(context)).isFalse();
void ternaryExpressionIsNotWritable() {
Expression exp = parser.parseExpression("1 > 2 ? 3 : 4");
assertThat(exp.isWritable(context)).isFalse();
}
@Test
void ternaryOperator05() {
evaluate("1>2?#var=4:#var=5", 5, Integer.class);
evaluate("3?:#var=5", 3, Integer.class);
evaluate("null?:#var=5", 5, Integer.class);
evaluate("2>4?(3>2?true:false):(5<3?true:false)", false, Boolean.class);
void ternaryExpressions() {
evaluate("2 > 4 ? 1 : 2", 2, Integer.class);
evaluate("'abc' == 'abc' ? 1 : 2", 1, Integer.class);
evaluate("1 > 2 ? #var = 4 : #var = 5", 5, Integer.class);
evaluate("2 > 4 ? (3 > 2 ? true : false) : (5 < 3 ? true : false)", false, Boolean.class);
}
@Test
void ternaryOperator06() {
evaluate("3?:#var=5", 3, Integer.class);
evaluate("null?:#var=5", 5, Integer.class);
evaluate("2>4?(3>2?true:false):(5<3?true:false)", false, Boolean.class);
}
@Test
void ternaryExpressionWithImplicitGrouping() {
void ternaryExpressionsWithImplicitGrouping() {
evaluate("4 % 2 == 0 ? 2 : 3 * 10", 2, Integer.class);
evaluate("4 % 2 == 1 ? 2 : 3 * 10", 30, Integer.class);
}
@Test
void ternaryExpressionWithExplicitGrouping() {
void ternaryExpressionsWithExplicitGrouping() {
evaluate("((4 % 2 == 0) ? 2 : 1) * 10", 20, Integer.class);
}
@Test
void ternaryOperatorWithNullValue() {
assertThatExceptionOfType(EvaluationException.class)
.isThrownBy(parser.parseExpression("null ? 0 : 1")::getValue);
}
}
@Nested
@@ -2056,12 +2056,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
@Test
void ternary() {
Expression expression = parser.parseExpression("true?'a':'b'");
expression = parser.parseExpression("true?'a':'b'");
String resultI = expression.getValue(String.class);
assertCanCompile(expression);
String resultC = expression.getValue(String.class);
assertThat(resultI).isEqualTo("a");
assertThat(resultC).isEqualTo("a");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
expression = parser.parseExpression("false?'a':'b'");
resultI = expression.getValue(String.class);
@@ -2069,11 +2070,13 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
resultC = expression.getValue(String.class);
assertThat(resultI).isEqualTo("b");
assertThat(resultC).isEqualTo("b");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
expression = parser.parseExpression("false?1:'b'");
// All literals so we can do this straight away
assertCanCompile(expression);
assertThat(expression.getValue()).isEqualTo("b");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
boolean root = true;
expression = parser.parseExpression("(#root and true)?T(Integer).valueOf(1):T(Long).valueOf(3L)");
@@ -2083,21 +2086,25 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
assertThat(expression.getValue(root)).isEqualTo(3L);
assertCanCompile(expression);
assertThat(expression.getValue(root)).isEqualTo(3L);
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
root = true;
assertThat(expression.getValue(root)).isEqualTo(1);
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
}
@Test
void ternaryWithBooleanReturn_SPR12271() {
@Test // gh-16876
void ternaryWithBooleanWrapperCondition() {
expression = parser.parseExpression("T(Boolean).TRUE?'abc':'def'");
assertThat(expression.getValue()).isEqualTo("abc");
assertCanCompile(expression);
assertThat(expression.getValue()).isEqualTo("abc");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
expression = parser.parseExpression("T(Boolean).FALSE?'abc':'def'");
assertThat(expression.getValue()).isEqualTo("def");
assertCanCompile(expression);
assertThat(expression.getValue()).isEqualTo("def");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
}
@Test
@@ -2289,31 +2296,30 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
@Test
void elvis() {
Expression expression = parser.parseExpression("'a'?:'b'");
String resultI = expression.getValue(String.class);
expression = parser.parseExpression("'a' ?: 'b'");
assertThat(expression.getValue(String.class)).isEqualTo("a");
assertCanCompile(expression);
String resultC = expression.getValue(String.class);
assertThat(resultI).isEqualTo("a");
assertThat(resultC).isEqualTo("a");
assertThat(expression.getValue(String.class)).isEqualTo("a");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
expression = parser.parseExpression("null?:'a'");
resultI = expression.getValue(String.class);
expression = parser.parseExpression("null ?: 'a'");
assertThat(expression.getValue(String.class)).isEqualTo("a");
assertCanCompile(expression);
resultC = expression.getValue(String.class);
assertThat(resultI).isEqualTo("a");
assertThat(resultC).isEqualTo("a");
assertThat(expression.getValue(String.class)).isEqualTo("a");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
String s = "abc";
expression = parser.parseExpression("#root?:'b'");
String root = "abc";
expression = parser.parseExpression("#root ?: 'b'");
assertCannotCompile(expression);
resultI = expression.getValue(s, String.class);
assertThat(resultI).isEqualTo("abc");
assertThat(expression.getValue(root, String.class)).isEqualTo("abc");
assertCanCompile(expression);
assertThat(expression.getValue(root, String.class)).isEqualTo("abc");
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
}
public static String concat(String a, String b) {
return a+b;
return a + b;
}
public static String concat2(Object... args) {