Browse Source

Retain null-safe syntax in AST representation of selection & projection

Prior to this commit, SpEL's CompoundExpression omitted the null-safe
syntax in AST string representations of the selection and projection
operators.

To address this, this commit implements isNullSafe() in Projection and
Selection.

Closes gh-32515
pull/32864/head
Sam Brannen 2 years ago
parent
commit
52b8c71dcd
  1. 9
      spring-expression/src/main/java/org/springframework/expression/spel/ast/Projection.java
  2. 9
      spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java
  3. 44
      spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java

9
spring-expression/src/main/java/org/springframework/expression/spel/ast/Projection.java

@ -52,6 +52,15 @@ public class Projection extends SpelNodeImpl { @@ -52,6 +52,15 @@ public class Projection extends SpelNodeImpl {
}
/**
* Does this node represent a null-safe projection operation?
* @since 6.1.6
*/
@Override
public final boolean isNullSafe() {
return this.nullSafe;
}
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
return getValueRef(state).getValue();

9
spring-expression/src/main/java/org/springframework/expression/spel/ast/Selection.java

@ -78,6 +78,15 @@ public class Selection extends SpelNodeImpl { @@ -78,6 +78,15 @@ public class Selection extends SpelNodeImpl {
}
/**
* Does this node represent a null-safe selection operation?
* @since 6.1.6
*/
@Override
public final boolean isNullSafe() {
return this.nullSafe;
}
@Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
return getValueRef(state).getValue();

44
spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java

@ -44,9 +44,24 @@ class ParsingTests { @@ -44,9 +44,24 @@ class ParsingTests {
@Test
void compoundExpressions() {
parseCheck("#var1.methodOne().methodTwo(42)");
parseCheck("#func1().methodOne().methodTwo(42)");
parseCheck("#func2('enigma').methodOne().methodTwo(42)");
parseCheck("property1.property2.methodOne()");
parseCheck("property1[0].property2['key'].methodOne()");
parseCheck("property1.methodOne('enigma').methodTwo(42)");
parseCheck("property1.methodOne().property2.methodTwo()");
parseCheck("property1[0].property2['key'].methodTwo()");
parseCheck("property1[0][1].property2['key'][42].methodTwo()");
// null-safe variants
parseCheck("#var1?.methodOne()?.methodTwo(42)");
parseCheck("#func1()?.methodOne()?.methodTwo(42)");
parseCheck("#func2('enigma')?.methodOne()?.methodTwo(42)");
parseCheck("property1?.property2?.methodOne()");
parseCheck("property1?.methodOne('enigma')?.methodTwo(42)");
parseCheck("property1?.methodOne()?.property2?.methodTwo()");
parseCheck("property1[0]?.property2['key']?.methodTwo()");
parseCheck("property1[0][1]?.property2['key'][42]?.methodTwo()");
}
@Test
@ -132,25 +147,34 @@ class ParsingTests { @@ -132,25 +147,34 @@ class ParsingTests {
@Test
void projection() {
parseCheck("{1,2,3,4,5,6,7,8,9,10}.![#isEven()]");
parseCheck("{1,2,3}.![#isEven()]");
// null-safe variant
parseCheck("{1,2,3}?.![#isEven()]");
}
@Test
void selection() {
parseCheck("{1,2,3,4,5,6,7,8,9,10}.?[#isEven(#this) == 'y']",
"{1,2,3,4,5,6,7,8,9,10}.?[(#isEven(#this) == 'y')]");
parseCheck("{1,2,3}.?[#isEven(#this)]");
// null-safe variant
parseCheck("{1,2,3}?.?[#isEven(#this)]");
}
@Test
void selectionFirst() {
parseCheck("{1,2,3,4,5,6,7,8,9,10}.^[#isEven(#this) == 'y']",
"{1,2,3,4,5,6,7,8,9,10}.^[(#isEven(#this) == 'y')]");
void selectFirst() {
parseCheck("{1,2,3}.^[#isEven(#this)]");
// null-safe variant
parseCheck("{1,2,3}?.^[#isEven(#this)]");
}
@Test
void selectionLast() {
parseCheck("{1,2,3,4,5,6,7,8,9,10}.$[#isEven(#this) == 'y']",
"{1,2,3,4,5,6,7,8,9,10}.$[(#isEven(#this) == 'y')]");
void selectLast() {
parseCheck("{1,2,3}.$[#isEven(#this)]");
// null-safe variant
parseCheck("{1,2,3}?.$[#isEven(#this)]");
}
}

Loading…
Cancel
Save