Skip to content

Commit 52b8c71

Browse files
committed
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
1 parent f941754 commit 52b8c71

File tree

3 files changed

+52
-10
lines changed

3 files changed

+52
-10
lines changed

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

+9
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,15 @@ public Projection(boolean nullSafe, int startPos, int endPos, SpelNodeImpl expre
5252
}
5353

5454

55+
/**
56+
* Does this node represent a null-safe projection operation?
57+
* @since 6.1.6
58+
*/
59+
@Override
60+
public final boolean isNullSafe() {
61+
return this.nullSafe;
62+
}
63+
5564
@Override
5665
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
5766
return getValueRef(state).getValue();

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

+9
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ public Selection(boolean nullSafe, int variant, int startPos, int endPos, SpelNo
7878
}
7979

8080

81+
/**
82+
* Does this node represent a null-safe selection operation?
83+
* @since 6.1.6
84+
*/
85+
@Override
86+
public final boolean isNullSafe() {
87+
return this.nullSafe;
88+
}
89+
8190
@Override
8291
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
8392
return getValueRef(state).getValue();

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

+34-10
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,24 @@ class Miscellaneous {
4444

4545
@Test
4646
void compoundExpressions() {
47+
parseCheck("#var1.methodOne().methodTwo(42)");
48+
parseCheck("#func1().methodOne().methodTwo(42)");
49+
parseCheck("#func2('enigma').methodOne().methodTwo(42)");
4750
parseCheck("property1.property2.methodOne()");
48-
parseCheck("property1[0].property2['key'].methodOne()");
51+
parseCheck("property1.methodOne('enigma').methodTwo(42)");
52+
parseCheck("property1.methodOne().property2.methodTwo()");
53+
parseCheck("property1[0].property2['key'].methodTwo()");
54+
parseCheck("property1[0][1].property2['key'][42].methodTwo()");
55+
56+
// null-safe variants
57+
parseCheck("#var1?.methodOne()?.methodTwo(42)");
58+
parseCheck("#func1()?.methodOne()?.methodTwo(42)");
59+
parseCheck("#func2('enigma')?.methodOne()?.methodTwo(42)");
60+
parseCheck("property1?.property2?.methodOne()");
61+
parseCheck("property1?.methodOne('enigma')?.methodTwo(42)");
4962
parseCheck("property1?.methodOne()?.property2?.methodTwo()");
63+
parseCheck("property1[0]?.property2['key']?.methodTwo()");
64+
parseCheck("property1[0][1]?.property2['key'][42]?.methodTwo()");
5065
}
5166

5267
@Test
@@ -132,25 +147,34 @@ void indexing() {
132147

133148
@Test
134149
void projection() {
135-
parseCheck("{1,2,3,4,5,6,7,8,9,10}.![#isEven()]");
150+
parseCheck("{1,2,3}.![#isEven()]");
151+
152+
// null-safe variant
153+
parseCheck("{1,2,3}?.![#isEven()]");
136154
}
137155

138156
@Test
139157
void selection() {
140-
parseCheck("{1,2,3,4,5,6,7,8,9,10}.?[#isEven(#this) == 'y']",
141-
"{1,2,3,4,5,6,7,8,9,10}.?[(#isEven(#this) == 'y')]");
158+
parseCheck("{1,2,3}.?[#isEven(#this)]");
159+
160+
// null-safe variant
161+
parseCheck("{1,2,3}?.?[#isEven(#this)]");
142162
}
143163

144164
@Test
145-
void selectionFirst() {
146-
parseCheck("{1,2,3,4,5,6,7,8,9,10}.^[#isEven(#this) == 'y']",
147-
"{1,2,3,4,5,6,7,8,9,10}.^[(#isEven(#this) == 'y')]");
165+
void selectFirst() {
166+
parseCheck("{1,2,3}.^[#isEven(#this)]");
167+
168+
// null-safe variant
169+
parseCheck("{1,2,3}?.^[#isEven(#this)]");
148170
}
149171

150172
@Test
151-
void selectionLast() {
152-
parseCheck("{1,2,3,4,5,6,7,8,9,10}.$[#isEven(#this) == 'y']",
153-
"{1,2,3,4,5,6,7,8,9,10}.$[(#isEven(#this) == 'y')]");
173+
void selectLast() {
174+
parseCheck("{1,2,3}.$[#isEven(#this)]");
175+
176+
// null-safe variant
177+
parseCheck("{1,2,3}?.$[#isEven(#this)]");
154178
}
155179
}
156180

0 commit comments

Comments
 (0)