Merge branch '6.1.x'
This commit is contained in:
commit
b695dbc2bf
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -24,7 +24,6 @@ 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
|
||||
|
@ -120,14 +119,13 @@ public class CompoundExpression extends SpelNodeImpl {
|
|||
for (int i = 0; i < getChildCount(); i++) {
|
||||
sb.append(getChild(i).toStringAST());
|
||||
if (i < getChildCount() - 1) {
|
||||
SpelNode nextChild = getChild(i + 1);
|
||||
SpelNodeImpl nextChild = this.children[i + 1];
|
||||
if (nextChild.isNullSafe()) {
|
||||
sb.append("?.");
|
||||
}
|
||||
// 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)) {
|
||||
if ((nextChild instanceof MethodReference methodRef && methodRef.isNullSafe()) ||
|
||||
(nextChild instanceof PropertyOrFieldReference pofRef && pofRef.isNullSafe())) {
|
||||
sb.append('?');
|
||||
}
|
||||
else if (!(nextChild instanceof Indexer)) {
|
||||
sb.append('.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ public class MethodReference extends SpelNodeImpl {
|
|||
* Does this node represent a null-safe method reference?
|
||||
* @since 6.0.13
|
||||
*/
|
||||
@Override
|
||||
public final boolean isNullSafe() {
|
||||
return this.nullSafe;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
|||
/**
|
||||
* Does this node represent a null-safe property or field reference?
|
||||
*/
|
||||
@Override
|
||||
public boolean isNullSafe() {
|
||||
return this.nullSafe;
|
||||
}
|
||||
|
@ -181,7 +182,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
|||
throws EvaluationException {
|
||||
|
||||
Object targetObject = contextObject.getValue();
|
||||
if (targetObject == null && this.nullSafe) {
|
||||
if (targetObject == null && isNullSafe()) {
|
||||
return TypedValue.NULL;
|
||||
}
|
||||
|
||||
|
@ -233,7 +234,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
|||
TypedValue contextObject, EvaluationContext evalContext, String name, @Nullable Object newValue)
|
||||
throws EvaluationException {
|
||||
|
||||
if (contextObject.getValue() == null && this.nullSafe) {
|
||||
if (contextObject.getValue() == null && isNullSafe()) {
|
||||
return;
|
||||
}
|
||||
if (contextObject.getValue() == null) {
|
||||
|
@ -353,7 +354,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
|||
}
|
||||
|
||||
Label skipIfNull = null;
|
||||
if (this.nullSafe) {
|
||||
if (isNullSafe()) {
|
||||
mv.visitInsn(DUP);
|
||||
skipIfNull = new Label();
|
||||
Label continueLabel = new Label();
|
||||
|
@ -381,7 +382,7 @@ public class PropertyOrFieldReference extends SpelNodeImpl {
|
|||
// If this property or field access would return a primitive - and yet
|
||||
// it is also marked null safe - then the exit type descriptor must be
|
||||
// promoted to the box type to allow a null value to be passed on
|
||||
if (this.nullSafe && CodeFlow.isPrimitive(descriptor)) {
|
||||
if (isNullSafe() && CodeFlow.isPrimitive(descriptor)) {
|
||||
this.originalPrimitiveExitTypeDescriptor = descriptor;
|
||||
this.exitTypeDescriptor = CodeFlow.toBoxedDescriptor(descriptor);
|
||||
}
|
||||
|
|
|
@ -181,6 +181,16 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
return this.endPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if this node is the target of a null-safe navigation operation.
|
||||
* <p>The default implementation returns {@code false}.
|
||||
* @return {@code true} if this node is the target of a null-safe operation
|
||||
* @since 6.1.6
|
||||
*/
|
||||
public boolean isNullSafe() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a node can be compiled to bytecode. The reasoning in each node may
|
||||
* be different but will typically involve checking whether the exit type descriptor
|
||||
|
|
Loading…
Reference in New Issue