Clean up TODOs in SpEL

This commit is contained in:
Sam Brannen 2024-02-17 15:33:05 +01:00
parent 5f1e25a61f
commit d4cde29f75
7 changed files with 20 additions and 26 deletions

View File

@ -76,7 +76,6 @@ public class ConstructorReference extends SpelNodeImpl {
@Nullable @Nullable
private final SpelNodeImpl[] dimensions; private final SpelNodeImpl[] dimensions;
// TODO is this caching safe - passing the expression around will mean this executor is also being passed around
/** The cached executor that may be reused on subsequent evaluations. */ /** The cached executor that may be reused on subsequent evaluations. */
@Nullable @Nullable
private volatile ConstructorExecutor cachedExecutor; private volatile ConstructorExecutor cachedExecutor;

View File

@ -82,7 +82,7 @@ public class Projection extends SpelNodeImpl {
state.exitScope(); state.exitScope();
} }
} }
return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this); // TODO unable to build correct type descriptor return new ValueRef.TypedValueHolderValueRef(new TypedValue(result), this);
} }
boolean operandIsArray = ObjectUtils.isArray(operand); boolean operandIsArray = ObjectUtils.isArray(operand);

View File

@ -90,7 +90,6 @@ public class Selection extends SpelNodeImpl {
SpelNodeImpl selectionCriteria = this.children[0]; SpelNodeImpl selectionCriteria = this.children[0];
if (operand instanceof Map<?, ?> mapdata) { if (operand instanceof Map<?, ?> mapdata) {
// TODO don't lose generic info for the new map
Map<Object, Object> result = new HashMap<>(); Map<Object, Object> result = new HashMap<>();
Object lastKey = null; Object lastKey = null;

View File

@ -54,7 +54,7 @@ public class TypeReference extends SpelNodeImpl {
@Override @Override
public TypedValue getValueInternal(ExpressionState state) throws EvaluationException { public TypedValue getValueInternal(ExpressionState state) throws EvaluationException {
// TODO possible optimization here if we cache the discovered type reference, but can we do that? // TODO Possible optimization: if we cache the discovered type reference, but can we do that?
String typeName = (String) this.children[0].getValueInternal(state).getValue(); String typeName = (String) this.children[0].getValueInternal(state).getValue();
Assert.state(typeName != null, "No type name"); Assert.state(typeName != null, "No type name");
if (!typeName.contains(".") && Character.isLowerCase(typeName.charAt(0))) { if (!typeName.contains(".") && Character.isLowerCase(typeName.charAt(0))) {
@ -99,7 +99,7 @@ public class TypeReference extends SpelNodeImpl {
@Override @Override
public void generateCode(MethodVisitor mv, CodeFlow cf) { public void generateCode(MethodVisitor mv, CodeFlow cf) {
// TODO Future optimization - if followed by a static method call, skip generating code here // TODO Future optimization: if followed by a static method call, skip generating code here.
Assert.state(this.type != null, "No type available"); Assert.state(this.type != null, "No type available");
if (this.type.isPrimitive()) { if (this.type.isPrimitive()) {
if (this.type == boolean.class) { if (this.type == boolean.class) {

View File

@ -733,7 +733,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
/** /**
* Eat an identifier, possibly qualified (meaning that it is dotted). * Eat an identifier, possibly qualified (meaning that it is dotted).
* TODO AndyC Could create complete identifiers (a.b.c) here rather than a sequence of them? (a, b, c)
*/ */
private SpelNodeImpl eatPossiblyQualifiedId() { private SpelNodeImpl eatPossiblyQualifiedId() {
Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>(); Deque<SpelNodeImpl> qualifiedIdPieces = new ArrayDeque<>();
@ -783,7 +782,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// method reference // method reference
push(new MethodReference(nullSafeNavigation, methodOrPropertyName.stringValue(), push(new MethodReference(nullSafeNavigation, methodOrPropertyName.stringValue(),
methodOrPropertyName.startPos, methodOrPropertyName.endPos, args)); methodOrPropertyName.startPos, methodOrPropertyName.endPos, args));
// TODO what is the end position for a method reference? the name or the last arg?
return true; return true;
} }
return false; return false;
@ -826,7 +824,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
else { else {
// regular constructor invocation // regular constructor invocation
eatConstructorArgs(nodes); eatConstructorArgs(nodes);
// TODO correct end position?
push(new ConstructorReference(newToken.startPos, newToken.endPos, nodes.toArray(new SpelNodeImpl[0]))); push(new ConstructorReference(newToken.startPos, newToken.endPos, nodes.toArray(new SpelNodeImpl[0])));
} }
return true; return true;

View File

@ -233,7 +233,6 @@ public abstract class ReflectionHelper {
return (match != null ? new ArgumentsMatchInfo(match) : null); return (match != null ? new ArgumentsMatchInfo(match) : null);
} }
// TODO could do with more refactoring around argument handling and varargs
/** /**
* Convert the supplied set of arguments into the parameter types specified * Convert the supplied set of arguments into the parameter types specified
* by the supplied {@link Method}. * by the supplied {@link Method}.

View File

@ -64,7 +64,7 @@ import static org.springframework.expression.spel.standard.SpelExpressionTestUti
public class SpelCompilationCoverageTests extends AbstractExpressionTests { public class SpelCompilationCoverageTests extends AbstractExpressionTests {
/* /*
* Further TODOs for compilation: * TODO Potential optimizations for SpEL compilation:
* *
* - OpMinus with a single literal operand could be treated as a negative literal. Will save a * - OpMinus with a single literal operand could be treated as a negative literal. Will save a
* pointless loading of 0 and then a subtract instruction in code gen. * pointless loading of 0 and then a subtract instruction in code gen.
@ -1205,12 +1205,12 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
assertCanCompile(expression); assertCanCompile(expression);
assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("xyz"); assertThat(expression.getValue(context, new SomeCompareMethod2()).toString()).isEqualTo("xyz");
// TODO fails due to conversionservice handling of String[] to Object... // TODO Determine why the String[] is passed as the first element of the Object... varargs array instead of the entire varargs array.
// expression = parser.parseExpression("#append2(#stringArray)"); // expression = parser.parseExpression("#append2(#stringArray)");
// assertEquals("xyz", expression.getValue(context).toString()); // assertThat(expression.getValue(context)).hasToString("xyz");
// assertTrue(((SpelNodeImpl)((SpelExpression) expression).getAST()).isCompilable()); // assertThat(((SpelNodeImpl) ((SpelExpression) expression).getAST()).isCompilable()).isTrue();
// assertCanCompile(expression); // assertCanCompile(expression);
// assertEquals("xyz", expression.getValue(context).toString()); // assertThat(expression.getValue(context)).hasToString("xyz");
expression = parser.parseExpression("#sum(1,2,3)"); expression = parser.parseExpression("#sum(1,2,3)");
assertThat(expression.getValue(context)).isEqualTo(6); assertThat(expression.getValue(context)).isEqualTo(6);
@ -3703,16 +3703,16 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
assertThat(tc.s).isEqualTo("aaabbbccc"); assertThat(tc.s).isEqualTo("aaabbbccc");
tc.reset(); tc.reset();
// TODO Fails related to conversion service converting a String[] to satisfy Object... // TODO Determine why the String[] is passed as the first element of the Object... varargs array instead of the entire varargs array.
// expression = parser.parseExpression("sixteen(stringArray)"); // expression = parser.parseExpression("sixteen(stringArray)");
// assertCantCompile(expression); // assertCantCompile(expression);
// expression.getValue(tc); // expression.getValue(tc);
// assertEquals("aaabbbccc", tc.s); // assertThat(tc.s).isEqualTo("aaabbbccc");
// assertCanCompile(expression); // assertCanCompile(expression);
// tc.reset(); // tc.reset();
// expression.getValue(tc); // expression.getValue(tc);
// assertEquals("aaabbbccc", tc.s); // assertThat(tc.s).isEqualTo("aaabbbccc");
// tc.reset(); // tc.reset();
// varargs int // varargs int
expression = parser.parseExpression("twelve(1,2,3)"); expression = parser.parseExpression("twelve(1,2,3)");