Before this commit the object that #this would refer to in
nested expressions within projection/selection clauses was always
the root context object. This was incorrect as it should be the
element being projected/selected over. This commit introduces
a scope root context object which is set upon entering a new
scope (like when entering a projection or selection). Any
object. With this change this kind of expression now behaves:
where #this is the element of list1. Unqualified references
are also resolved against this scope root context object.
Issues: SPR-10417, SPR-12035, SPR-13055
This change provides support for map[NEW], map[new], map[T]
and map[t]. Prior to this change the 'new' and 't' had to
be quoted because they were keywords in SpEL for a constructor
reference and type reference respectively.
Issue: SPR-11783
Prior to this change the SpEL compiler would not compile mathematical
expressions where the operands were of differing types (e.g. int
and double). This required the expression writer to do the conversion
in the expression text. For example:
T(Integer).valueOf(someInt).doubleValue()/35d
With this commit the restriction is lifted and it is more like Java
so that you can simply do someInt/35d. The mathematical operators
affected are divide/plus/minus/multiply and modulus. This change
involved removing some guards so that the exitTypeDescriptor (the
trigger for whether compilation is allowed) is set more frequently
and enhancing bytecode generation to perform more sophisticated
conversion/coercion automatically.
Issue: SPR-12789
Without this change when the operands to an == are a mix of a
reference type and a primitive, the failure to box the primitive
would result in a verifyerror when the compiled code is loaded.
Issue: SPR-12557
Without this change the plus operator would fail to
include a CHECKCAST in generated bytecode when it
was compiled in cases where one of the operands
has a runtime type of String but a statically
declared type that was not String (i.e. Object).
Issue: SPR-12426
Before this change isWritable() could return true
for a badly formed expression. That is because the
decision about whether something is writable was made
based on the node type rather than whether the node
represented something that could actually be resolved
to be a real thing. This change ensures a resolution
check is done and isWritable() should only return
true if a subsequent setValue() will succeed.
Issue: SPR-10610
These changes provide more robust handling of function
reference compilation in SpEL expressions. Prior to
this change the isCompilable check was not performing
enough visibility checks on the proposed target
function, causing bytecode to be generated that
would lead to an IllegalAccessError.
The changes also bring the argument handling for
function invocation completely inline with that used
for method invocation allowing some code to be deleted.
Many new tests are also included for function
reference compilation.
Issue: SPR-12359
Building on the initial work for SPR-12326, this commit
addresses three problems:
Firstly the ReflectiveMethodResolver is modified to consider
a direct parameter match more important than a varargs match.
Also in that same type when there are a number of close
matches, the first one is taken rather than the last one.
Secondly more testcases and better support have been added
for the case of passing a single parameter to a varargs
accepting method.
Finally it is possible to set the root context object
indirectly and not pass it on getValue() calls to the
expression objects but not all variants of getValue()
were handling that. This is now fixed.
Issue: SPR-12326
The argument processing for compiling constructor references
was very basic and this fix removes that and ensures the
comprehensive logic written for method argument processing
(under SPR-12328) is now used for both method and constructor
argument handling. This fixes the reported issue and ensures
varargs constructor references can be compiled.
This also includes a couple of small fixes for the secondary
testcase reported in SPR-12326. The first is to ensure the
right root context object is used when it is passed
to getValue() indirectly through the evaluation context.
The final fix is to ensure correct boxing of primitives is
done when a method is called upon a primitive.
Issue: SPR-12326
This change introduces support for compilation of expressions
involving inline lists, string concatenation and method
invocations where the method being invoked is declared
with a varargs parameter. It also fixes a problem with
compiling existing method invocations where the target
method is on a non public type.
Issue: SPR-12328
The ternary expression node was failing to generate the
necessary unboxing bytecode when the condition part
of the expression returned a boxed Boolean rather than
a primitive boolean.
Also fixed here is an IllegalAccessError that was
seen in the same expression due to generating a
CHECKCAST bytecode for a private type.
Issue: SPR-12271
This commit introduces the ability to specify an inline map in
an expression. The syntax is similar to inline lists and of
the form: "{key:value,key2:value}". The keys can optionally
be quoted. The documentation is also updated with information
on the syntax.
Issue: SPR-9472
There is special handling for SpEL expressions involving a map
and an unquoted string literal key (e.g. mymap[key1]). SpEL does
not require key1 to be quoted. This special handling which is done
in Indexer getValueRef() was not being also done in the Indexer
generateCode() method that compiles the expression. Also fixed
a problem where the key was not being compiled in a new
sub scope. Without the new scope the key expression was failing
to reload the relevant context object when it needed it.
Issue: SPR-12045