Commit Graph

765 Commits

Author SHA1 Message Date
Sam Brannen
153d1bc923 Support Collection target types in custom IndexAccessors
Prior to this commit, an IndexAccessor could not provide support for a
Collection target type, since the built-in support for indexing into a
Collection in SpEL's Indexer took precedence.

This commit allows an IndexAccessor to support custom Collection target
types by separating the built-in List and Collection support and
applying the built-in Collection support after custom index accessors
have been applied.

Closes gh-32736
2024-05-01 16:12:04 +03:00
Sam Brannen
4e6591e1a9 Polishing 2024-05-01 16:12:04 +03:00
Sam Brannen
35c183d634 Introduce ReflectiveIndexAccessor in SpEL
This commit introduces ReflectiveIndexAccessor for the Spring
Expression Language (SpEL) which is somewhat analogous to the
ReflectivePropertyAccessor implementation of PropertyAccessor.

ReflectiveIndexAccessor is a flexible IndexAccessor implementation that
uses reflection to read from and optionally write to an indexed
structure of a target object. ReflectiveIndexAccessor also implements
CompilableIndexAccessor in order to support compilation to bytecode for
read access.

For example, the following creates a read-write IndexAccessor for a
FruitMap type that is indexed by Color, including built-in support for
compilation to bytecode for read access.

IndexAccessor indexAccessor = new ReflectiveIndexAccessor(
    FruitMap.class, Color.class, "getFruit", "setFruit");

Closes gh-32714
2024-04-30 16:26:11 +03:00
Sam Brannen
9b85c93b6b Polishing 2024-04-29 16:17:38 +03:00
Sam Brannen
fc3dddac9c Polishing 2024-04-28 11:43:14 +03:00
Sam Brannen
27d2200058 Introduce CompilableIndexAccessor SPI in SpEL
This commit introduces a new CompilableIndexAccessor SPI for the Spring
Expression Language (SpEL) which allows an IndexAccessor to support
compilation to bytecode for operations that read an index.

This analogous to the CompilablePropertyAccessor SPI.

This commit also includes a prototype for a general purpose
ReflectiveIndexAccessor in the tests.

Closes gh-32613
2024-04-26 12:19:10 +03:00
Sam Brannen
0b5800ae39 Introduce generateCodeForArgument() in CodeFlow
Closes gh-32708
2024-04-25 15:12:21 +03:00
Sam Brannen
25fd5659cb Polishing 2024-04-25 15:10:00 +03:00
Sam Brannen
de9ce800bf Polishing 2024-04-25 14:00:35 +03:00
Sam Brannen
8f579b3144 Make SpelNode compilation aware
In order to make SpelNode compilation aware, this method moves the
declaration of isCompilable() and generateCode(...) from SpelNodeImpl
to SpelNode.

Closes gh-32707
2024-04-25 13:47:57 +03:00
Sam Brannen
14689256c4 Support String index type in custom IndexAccessor
Closes gh-32706
2024-04-25 12:17:13 +03:00
Sam Brannen
a3d3bc0a1f Polishing 2024-04-25 12:14:23 +03:00
Sam Brannen
a986374da7 Use records to track cached state in Indexer 2024-04-25 11:51:11 +03:00
Sam Brannen
aaf33100d9 Add IndexAccessor support to SpEL's SimpleEvaluationContext
Closes gh-32702
2024-04-24 16:19:39 +03:00
Sam Brannen
1e4275a0f9 Implement optional get<list>() methods in EvaluationContext as default methods 2024-04-24 15:54:05 +03:00
Sam Brannen
33fbd7141d Make AstUtils package-private
AstUtils was never intended to be a public utility class.
2024-04-24 15:44:02 +03:00
Sam Brannen
461d7a82f6 Avoid redefining getSpecificTargetClasses() in [Property|Index]Accessor 2024-04-24 15:39:01 +03:00
Sam Brannen
ca6d987c56 Support compilation of array and list indexing with Integer in SpEL
Prior to this commit, the Spring Expression Language (SpEL) failed to
compile an expression that indexed into any array or list using an
Integer.

This commit adds support for compilation of such expressions by
ensuring that an Integer is unboxed into an int in the compiled
bytecode.

Closes gh-32694
2024-04-23 11:36:48 +03:00
Sam Brannen
80fb8ea813 Avoid unnecessary compilation attempts in SpEL's Indexer
Closes gh-32677
2024-04-19 17:20:24 +02:00
Sam Brannen
1eed71bb1d Polishing 2024-04-19 14:34:09 +02:00
Sam Brannen
c8090fe0b4 Extract generateIndexCode() in SpEL's Indexer 2024-04-19 14:33:22 +02:00
Sam Brannen
9eab7bb11d Introduce null-safe indexing test for custom IndexAccessor 2024-04-19 14:29:43 +02:00
Sam Brannen
a01f7cefae Polish Javadoc for SpelNode 2024-04-19 14:27:11 +02:00
Sam Brannen
afbce96fb7 Introduce getName() in SpEL's BeanReference
Closes gh-32640
2024-04-15 16:44:37 +02:00
Sam Brannen
3f34a13436 Polishing 2024-04-15 16:30:51 +02:00
Sam Brannen
1c9cff668c Honor IndexAccessor#canWrite() and cache accessors
See gh-26409
See gh-26478
2024-04-10 15:54:34 +02:00
Sam Brannen
15511890bd Revise Javadoc for IndexAccessor
See gh-26409
See gh-26478
2024-04-10 15:54:34 +02:00
Sam Brannen
22bfe7da5a Introduce proper error handling for IndexAccessor support in SpEL
See gh-26409
See gh-26478
2024-04-10 15:54:34 +02:00
Sam Brannen
5c6b82a947 Change IndexAccessor#read()'s return type to TypedValue
Prior to this commit, the read() method in the IndexAccessor SPI
declared a return type of ValueRef which introduced a package cycle.

This commit addresses this by aligning with the PropertyAccess SPI and
returning TypedValue from IndexAccessor's read() method. This commit
also reworks the internals of Indexer based on a new, local
IndexAccessorValueRef implementation.

See gh-26409
See gh-26478
2024-04-10 15:54:34 +02:00
Sam Brannen
b7c3833732 Revise null-safety contracts in IndexAccessor SPI
When indexing into an object, the target object can never be null.

See gh-26409
See gh-26478
2024-04-10 15:54:34 +02:00
Sam Brannen
d91277095a Initial review and polish of IndexAccessor support in SpEL
See gh-26409
See gh-26478
2024-04-10 15:54:34 +02:00
ljmn3211
50a0000ed7 Introduce IndexAccessor SPI to customize the SpEL Indexer
See gh-26409
See gh-26478
2024-04-10 15:14:50 +02:00
Sébastien Deleuze
0c42874629 Merge branch '6.1.x' 2024-04-05 14:33:20 +02:00
Sébastien Deleuze
4a7c24d90f Refine null-safety
See gh-32475
2024-04-05 14:30:50 +02:00
Sam Brannen
f47352ff04 Polish PropertyOrFieldReference 2024-03-26 13:21:46 +01:00
Sam Brannen
4b0a048570 Polish SpEL internals and remove duplicate code 2024-03-25 17:47:14 +01:00
Sam Brannen
57632f9f08 Fix wording in SpEL's PropertyAccessor Javadoc
The documentation now properly refers to "property accessors" instead
of "resolvers".
2024-03-25 14:26:40 +01:00
Sam Brannen
5bec072dcb Polish SpEL internals 2024-03-24 17:07:42 +01:00
Sam Brannen
218a148898 Document null-safe index operator in SpEL
See gh-29847
2024-03-23 14:56:01 +01:00
Sam Brannen
38c473fd05 Support compilation of null-safe index operations in SpEL
See gh-29847
2024-03-23 13:48:20 +01:00
Sam Brannen
d2bd0d5716 Retain null-safe syntax in AST representation of SpEL indexers
Prior to this commit, SpEL's CompoundExpression omitted the null-safe
syntax in AST string representations of indexing operations.

To address this, this commit implements isNullSafe() in Indexer.

See gh-29847
2024-03-23 12:46:03 +01:00
Sam Brannen
4d433174eb Revise null-safe index operator support in SpEL
See gh-29847
2024-03-23 12:46:03 +01:00
Grigory Stepanov
9f4d46fe33 Introduce null-safe index operator in SpEL
See gh-29847
2024-03-23 12:38:10 +01:00
Sam Brannen
2a1abb5553 Simplify compilation of array indexing in SpEL's Indexer 2024-03-23 12:35:25 +01:00
Sam Brannen
88bc3f270e Merge branch '6.1.x' 2024-03-22 17:18:38 +01:00
Sam Brannen
52b8c71dcd 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
2024-03-22 17:05:48 +01:00
Sam Brannen
b695dbc2bf Merge branch '6.1.x' 2024-03-22 16:37:55 +01:00
Sam Brannen
f941754db6 Introduce isNullSafe() in SpelNodeImpl
Prior to this commit, MethodReference and PropertyOrFieldReference
already defined local isNullSafe() methods, but we need identical
methods in Selection, Projection, and Indexer, and we may potentially
need null-safe support for additional operators in the future.

To address the common need for an is-null-safe check, this commit
introduces an isNullSafe() method in SpelNodeImpl with a default
implementation that returns false.

Closes gh-32516
2024-03-22 16:37:08 +01:00
Sam Brannen
d4495a5654 Revise PropertyOrFieldReference since isNullSafe() is not final 2024-03-22 16:37:08 +01:00
Sam Brannen
7f40b49f4d Improve names of classes generated by the SpEL compiler
Prior to this commit, the SpEL compiler generated classes in a package
named "spel" with names following the pattern "Ex#", where # was an
index starting with 2.

This resulted in class names such as:

- spel.Ex2
- spel.Ex3

This commit improves the names of classes created by the SpEL compiler
by generating classes in a package named
"org.springframework.expression.spel.generated" with names following
the pattern "CompiledExpression#####", where ##### is a 0-padded
counter starting with 00001.

This results in class names such as:

- org.springframework.expression.spel.generated.CompiledExpression00001
- org.springframework.expression.spel.generated.CompiledExpression00002

This commit also moves the saveGeneratedClassFile() method from
SpelCompilationCoverageTests to SpelCompiler and enhances it to:

- Save classes in a "build/generated-classes" directory.
- Convert package names to directories.
- Create missing parent directories.
- Use logging instead of System.out.println().

Running a test with saveGeneratedClassFile() enabled now logs something
similar to the following.

DEBUG o.s.e.s.s.SpelCompiler - Saving compiled SpEL expression [(#root.empty ? 0 : #root.size)] to [/Users/<username>/spring-framework/spring-expression/build/generated-classes/org/springframework/expression/spel/generated/CompiledExpression00001.class]

Closes gh-32497
2024-03-20 12:34:01 +01:00