From fea1464562289c64b1bfe858f74d50970531a8a0 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:29:42 +0100 Subject: [PATCH 1/2] Ensure SpEL can compile an expression indexing into a boolean array Closes gh-32400 --- .../springframework/expression/spel/ast/Indexer.java | 6 ++++++ .../spel/SpelCompilationCoverageTests.java | 12 ++++++++++++ 2 files changed, 18 insertions(+) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java index b1fbc3225a..e0bc8be533 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/Indexer.java @@ -245,6 +245,12 @@ public class Indexer extends SpelNodeImpl { } case "B" -> { mv.visitTypeInsn(CHECKCAST, "[B"); + // byte and boolean arrays are both loaded via BALOAD + yield BALOAD; + } + case "Z" -> { + mv.visitTypeInsn(CHECKCAST, "[Z"); + // byte and boolean arrays are both loaded via BALOAD yield BALOAD; } case "C" -> { diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java index 33e8604732..41c22b88a3 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/SpelCompilationCoverageTests.java @@ -308,6 +308,18 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests { assertThat(getAst().getExitDescriptor()).isEqualTo("C"); } + @Test + void indexIntoPrimitiveBooleanArray() { + boolean[] booleans = { true, false }; + + expression = parser.parseExpression("[1]"); + + assertThat(expression.getValue(booleans)).isEqualTo(false); + assertCanCompile(expression); + assertThat(expression.getValue(booleans)).isEqualTo(false); + assertThat(getAst().getExitDescriptor()).isEqualTo("Z"); + } + @Test void indexIntoStringArray() { String[] strings = { "a", "b", "c" }; From 528029a0ba4f651e9bc9799d2cfab02b2689643e Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:47:10 +0100 Subject: [PATCH 2/2] Document that SpEL expressions using array construction cannot be compiled Closes gh-32401 --- .../ROOT/pages/core/expressions/evaluation.adoc | 1 + .../language-ref/array-construction.adoc | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc b/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc index 43840d17d2..9c9f6953f6 100644 --- a/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc +++ b/framework-docs/modules/ROOT/pages/core/expressions/evaluation.adoc @@ -518,6 +518,7 @@ following kinds of expressions cannot be compiled. * Expressions relying on the conversion service * Expressions using custom resolvers or accessors * Expressions using overloaded operators +* Expressions using array construction syntax * Expressions using selection or projection Compilation of additional kinds of expressions may be supported in the future. diff --git a/framework-docs/modules/ROOT/pages/core/expressions/language-ref/array-construction.adoc b/framework-docs/modules/ROOT/pages/core/expressions/language-ref/array-construction.adoc index 01e181ae30..4bc9317422 100644 --- a/framework-docs/modules/ROOT/pages/core/expressions/language-ref/array-construction.adoc +++ b/framework-docs/modules/ROOT/pages/core/expressions/language-ref/array-construction.adoc @@ -13,7 +13,7 @@ Java:: int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context); // Array with initializer - int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context); + int[] numbers2 = (int[]) parser.parseExpression("new int[] {1, 2, 3}").getValue(context); // Multi dimensional array int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context); @@ -26,14 +26,22 @@ Kotlin:: val numbers1 = parser.parseExpression("new int[4]").getValue(context) as IntArray // Array with initializer - val numbers2 = parser.parseExpression("new int[]{1,2,3}").getValue(context) as IntArray + val numbers2 = parser.parseExpression("new int[] {1, 2, 3}").getValue(context) as IntArray // Multi dimensional array val numbers3 = parser.parseExpression("new int[4][5]").getValue(context) as Array ---- ====== +[NOTE] +==== You cannot currently supply an initializer when you construct a multi-dimensional array. +==== - - +[CAUTION] +==== +Any expression that constructs an array – for example, via `new int[4]` or +`new int[] {1, 2, 3}` – cannot be compiled. See +xref:core/expressions/evaluation.adoc#expressions-compiler-limitations[Compiler Limitations] +for details. +====