@ -2958,6 +2958,103 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
assertTrue ( expression . getValue ( Boolean . class ) ) ;
assertTrue ( expression . getValue ( Boolean . class ) ) ;
}
}
/ * *
* Test variants of using T ( . . . ) and static / non - static method / property / field references .
* /
@Test
public void constructorReference_SPR13781 ( ) {
// Static field access on a T() referenced type
expression = parser . parseExpression ( "T(java.util.Locale).ENGLISH" ) ;
assertEquals ( "en" , expression . getValue ( ) . toString ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "en" , expression . getValue ( ) . toString ( ) ) ;
// The actual expression from the bug report. It fails if the ENGLISH reference fails
// to pop the type reference for Locale off the stack (if it isn't popped then
// toLowerCase() will be called with a Locale parameter). In this situation the
// code generation for ENGLISH should notice there is something on the stack that
// is not required and pop it off.
expression = parser . parseExpression ( "#userId.toString().toLowerCase(T(java.util.Locale).ENGLISH)" ) ;
StandardEvaluationContext context =
new StandardEvaluationContext ( ) ;
context . setVariable ( "userId" , "RoDnEy" ) ;
assertEquals ( "rodney" , expression . getValue ( context ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "rodney" , expression . getValue ( context ) ) ;
// Property access on a class object
expression = parser . parseExpression ( "T(String).name" ) ;
assertEquals ( "java.lang.String" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "java.lang.String" , expression . getValue ( ) ) ;
// Now the type reference isn't on the stack, and needs loading
context = new StandardEvaluationContext ( String . class ) ;
expression = parser . parseExpression ( "name" ) ;
assertEquals ( "java.lang.String" , expression . getValue ( context ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "java.lang.String" , expression . getValue ( context ) ) ;
expression = parser . parseExpression ( "T(String).getName()" ) ;
assertEquals ( "java.lang.String" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "java.lang.String" , expression . getValue ( ) ) ;
// These tests below verify that the chain of static accesses (either method/property or field)
// leave the right thing on top of the stack for processing by any outer consuming code.
// Here the consuming code is the String.valueOf() function. If the wrong thing were on
// the stack (for example if the compiled code for static methods wasn't popping the
// previous thing off the stack) the valueOf() would operate on the wrong value.
String shclass = StaticsHelper . class . getName ( ) ;
// Basic chain: property access then method access
expression = parser . parseExpression ( "T(String).valueOf(T(String).name.valueOf(1))" ) ;
assertEquals ( "1" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "1" , expression . getValue ( ) ) ;
// chain of statics ending with static method
expression = parser . parseExpression ( "T(String).valueOf(T(" + shclass + ").methoda().methoda().methodb())" ) ;
assertEquals ( "mb" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "mb" , expression . getValue ( ) ) ;
// chain of statics ending with static field
expression = parser . parseExpression ( "T(String).valueOf(T(" + shclass + ").fielda.fielda.fieldb)" ) ;
assertEquals ( "fb" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "fb" , expression . getValue ( ) ) ;
// chain of statics ending with static property access
expression = parser . parseExpression ( "T(String).valueOf(T(" + shclass + ").propertya.propertya.propertyb)" ) ;
assertEquals ( "pb" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "pb" , expression . getValue ( ) ) ;
// variety chain
expression = parser . parseExpression ( "T(String).valueOf(T(" + shclass + ").fielda.methoda().propertya.fieldb)" ) ;
assertEquals ( "fb" , expression . getValue ( ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "fb" , expression . getValue ( ) ) ;
expression = parser . parseExpression ( "T(String).valueOf(fielda.fieldb)" ) ;
assertEquals ( "fb" , expression . getValue ( StaticsHelper . sh ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "fb" , expression . getValue ( StaticsHelper . sh ) ) ;
expression = parser . parseExpression ( "T(String).valueOf(propertya.propertyb)" ) ;
assertEquals ( "pb" , expression . getValue ( StaticsHelper . sh ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "pb" , expression . getValue ( StaticsHelper . sh ) ) ;
expression = parser . parseExpression ( "T(String).valueOf(methoda().methodb())" ) ;
assertEquals ( "mb" , expression . getValue ( StaticsHelper . sh ) ) ;
assertCanCompile ( expression ) ;
assertEquals ( "mb" , expression . getValue ( StaticsHelper . sh ) ) ;
}
@Test
@Test
public void constructorReference_SPR12326 ( ) {
public void constructorReference_SPR12326 ( ) {
String type = this . getClass ( ) . getName ( ) ;
String type = this . getClass ( ) . getName ( ) ;
@ -5341,4 +5438,29 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
}
}
}
}
public static class StaticsHelper {
static StaticsHelper sh = new StaticsHelper ( ) ;
public static StaticsHelper methoda ( ) {
return sh ;
}
public static String methodb ( ) {
return "mb" ;
}
public static StaticsHelper getPropertya ( ) {
return sh ;
}
public static String getPropertyb ( ) {
return "pb" ;
}
public static StaticsHelper fielda = sh ;
public static String fieldb = "fb" ;
public String toString ( ) {
return "sh" ;
}
}
}
}