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
			
			
This commit is contained in:
		
							parent
							
								
									dfbed616ba
								
							
						
					
					
						commit
						5ad853ef5b
					
				| 
						 | 
					@ -16,7 +16,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package org.springframework.expression.spel.ast;
 | 
					package org.springframework.expression.spel.ast;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.StringJoiner;
 | 
					 | 
				
			||||||
import java.util.function.Supplier;
 | 
					import java.util.function.Supplier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.springframework.asm.MethodVisitor;
 | 
					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.CodeFlow;
 | 
				
			||||||
import org.springframework.expression.spel.ExpressionState;
 | 
					import org.springframework.expression.spel.ExpressionState;
 | 
				
			||||||
import org.springframework.expression.spel.SpelEvaluationException;
 | 
					import org.springframework.expression.spel.SpelEvaluationException;
 | 
				
			||||||
 | 
					import org.springframework.expression.spel.SpelNode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Represents a DOT separated expression sequence, such as
 | 
					 * Represents a DOT separated expression sequence, such as
 | 
				
			||||||
 * {@code 'property1.property2.methodOne()'}.
 | 
					 * {@code property1.property2.methodOne()}.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * <p>May also contain array/collection/map indexers, such as
 | 
				
			||||||
 | 
					 * {@code property1[0].property2['key']}.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @author Andy Clement
 | 
					 * @author Andy Clement
 | 
				
			||||||
 * @author Sam Brannen
 | 
					 * @author Sam Brannen
 | 
				
			||||||
| 
						 | 
					@ -111,11 +114,19 @@ public class CompoundExpression extends SpelNodeImpl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	@Override
 | 
						@Override
 | 
				
			||||||
	public String toStringAST() {
 | 
						public String toStringAST() {
 | 
				
			||||||
		StringJoiner sj = new StringJoiner(".");
 | 
							StringBuilder sb = new StringBuilder();
 | 
				
			||||||
		for (int i = 0; i < getChildCount(); i++) {
 | 
							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
 | 
						@Override
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,12 @@ class ParsingTests {
 | 
				
			||||||
	@Nested
 | 
						@Nested
 | 
				
			||||||
	class Miscellaneous {
 | 
						class Miscellaneous {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@Test
 | 
				
			||||||
 | 
							void compoundExpressions() {
 | 
				
			||||||
 | 
								parseCheck("property1.property2.methodOne()");
 | 
				
			||||||
 | 
								parseCheck("property1[0].property2['key'].methodOne()");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		@Test
 | 
							@Test
 | 
				
			||||||
		void supportedCharactersInIdentifiers() {
 | 
							void supportedCharactersInIdentifiers() {
 | 
				
			||||||
			parseCheck("#var='value'");
 | 
								parseCheck("#var='value'");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue