Polishing

See gh-29857
This commit is contained in:
Sam Brannen 2024-03-09 15:29:21 +01:00
parent 20be9e150c
commit f4c1ad7ae6
3 changed files with 15 additions and 13 deletions

View File

@ -19,7 +19,6 @@ package org.springframework.expression.spel;
import org.springframework.asm.MethodVisitor;
import org.springframework.asm.Opcodes;
import org.springframework.expression.PropertyAccessor;
import org.springframework.lang.Nullable;
/**
* A compilable {@link PropertyAccessor} is able to generate bytecode that represents
@ -45,14 +44,10 @@ public interface CompilablePropertyAccessor extends PropertyAccessor, Opcodes {
* Generate the bytecode that performs the access operation into the specified
* {@link MethodVisitor} using context information from the {@link CodeFlow}
* where necessary.
* <p>Concrete implementations of {@code CompilablePropertyAccessor} typically
* have access to the property name via other means (for example, supplied as
* an argument when they were instantiated). Thus, the {@code propertyName}
* supplied to this method may be {@code null}.
* @param propertyName the name of the property, or {@code null} if not available
* @param propertyName the name of the property
* @param methodVisitor the ASM method visitor into which code should be generated
* @param codeFlow the current state of the expression compiler
*/
void generateCode(@Nullable String propertyName, MethodVisitor methodVisitor, CodeFlow codeFlow);
void generateCode(String propertyName, MethodVisitor methodVisitor, CodeFlow codeFlow);
}

View File

@ -213,16 +213,17 @@ public class Indexer extends SpelNodeImpl {
if (this.indexedType == IndexedType.ARRAY) {
return (this.exitTypeDescriptor != null);
}
else if (this.indexedType == IndexedType.LIST) {
return this.children[0].isCompilable();
SpelNodeImpl index = this.children[0];
if (this.indexedType == IndexedType.LIST) {
return index.isCompilable();
}
else if (this.indexedType == IndexedType.MAP) {
return (this.children[0] instanceof PropertyOrFieldReference || this.children[0].isCompilable());
return (index instanceof PropertyOrFieldReference || index.isCompilable());
}
else if (this.indexedType == IndexedType.OBJECT) {
// If the string name is changing, the accessor is clearly going to change.
// So compilation is only possible if the index expression is a StringLiteral.
return (getChild(0) instanceof StringLiteral &&
return (index instanceof StringLiteral &&
this.cachedReadAccessor instanceof CompilablePropertyAccessor compilablePropertyAccessor &&
compilablePropertyAccessor.isCompilable());
}
@ -238,6 +239,7 @@ public class Indexer extends SpelNodeImpl {
}
SpelNodeImpl index = this.children[0];
if (this.indexedType == IndexedType.ARRAY) {
int insn = switch (this.exitTypeDescriptor) {
case "D" -> {
@ -313,9 +315,14 @@ public class Indexer extends SpelNodeImpl {
}
else if (this.indexedType == IndexedType.OBJECT) {
if (!(index instanceof StringLiteral stringLiteral)) {
throw new IllegalStateException(
"Index expression must be a StringLiteral, but was: " + index.getClass().getName());
}
CompilablePropertyAccessor compilablePropertyAccessor = (CompilablePropertyAccessor) this.cachedReadAccessor;
Assert.state(compilablePropertyAccessor != null, "No cached read accessor");
compilablePropertyAccessor.generateCode(null, mv, cf);
String propertyName = (String) stringLiteral.getLiteralValue().getValue();
compilablePropertyAccessor.generateCode(propertyName, mv, cf);
}
cf.pushDescriptor(this.exitTypeDescriptor);

View File

@ -712,7 +712,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
}
@Override
public void generateCode(@Nullable String propertyName, MethodVisitor mv, CodeFlow cf) {
public void generateCode(String propertyName, MethodVisitor mv, CodeFlow cf) {
Class<?> publicDeclaringClass = this.member.getDeclaringClass();
if (!Modifier.isPublic(publicDeclaringClass.getModifiers()) && this.originalMethod != null) {
publicDeclaringClass = ReflectionHelper.findPublicDeclaringClass(this.originalMethod);