From 5ad853ef5b31e410ca1677d8cbeff0b8ff438023 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Wed, 7 Jun 2023 14:45:44 +0200 Subject: [PATCH] Do not precede indexed access with a dot in SpEL AST representation Prior to this commit, if a Spring Expression Language (SpEL) expression contained indexed access to an object, the generated AST String representation incorrectly included a dot ('.') before the index access. For example, 'property[0]' had a generated AST string representation of 'property.[0]'. This commit addresses this by reworking the logic in CompoundExpression.toStringAST(). Closes gh-30610 --- .../spel/ast/CompoundExpression.java | 21 ++++++++++++++----- .../expression/spel/ParsingTests.java | 6 ++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java index 616a503a4ec..01745e65cfc 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/CompoundExpression.java @@ -16,7 +16,6 @@ package org.springframework.expression.spel.ast; -import java.util.StringJoiner; import java.util.function.Supplier; import org.springframework.asm.MethodVisitor; @@ -25,10 +24,14 @@ import org.springframework.expression.TypedValue; import org.springframework.expression.spel.CodeFlow; import org.springframework.expression.spel.ExpressionState; import org.springframework.expression.spel.SpelEvaluationException; +import org.springframework.expression.spel.SpelNode; /** * Represents a DOT separated expression sequence, such as - * {@code 'property1.property2.methodOne()'}. + * {@code property1.property2.methodOne()}. + * + *

May also contain array/collection/map indexers, such as + * {@code property1[0].property2['key']}. * * @author Andy Clement * @author Sam Brannen @@ -111,11 +114,19 @@ public class CompoundExpression extends SpelNodeImpl { @Override public String toStringAST() { - StringJoiner sj = new StringJoiner("."); + StringBuilder sb = new StringBuilder(); for (int i = 0; i < getChildCount(); i++) { - sj.add(getChild(i).toStringAST()); + sb.append(getChild(i).toStringAST()); + if (i < getChildCount() - 1) { + SpelNode nextChild = getChild(i + 1); + // Don't append a '.' if the next child is an Indexer. + // For example, we want 'myVar[0]' instead of 'myVar.[0]'. + if (!(nextChild instanceof Indexer)) { + sb.append('.'); + } + } } - return sj.toString(); + return sb.toString(); } @Override diff --git a/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java b/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java index 03e6b72dabe..eea5e2e3333 100644 --- a/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java +++ b/spring-expression/src/test/java/org/springframework/expression/spel/ParsingTests.java @@ -43,6 +43,12 @@ class ParsingTests { @Nested class Miscellaneous { + @Test + void compoundExpressions() { + parseCheck("property1.property2.methodOne()"); + parseCheck("property1[0].property2['key'].methodOne()"); + } + @Test void supportedCharactersInIdentifiers() { parseCheck("#var='value'");