Relaxed position assertion (for overflows in large inline maps)
Issue: SPR-17605
This commit is contained in:
parent
31a24720a6
commit
b2756f5bd2
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2018 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.
|
||||
|
|
@ -21,8 +21,8 @@ import org.springframework.expression.TypedValue;
|
|||
import org.springframework.expression.spel.ExpressionState;
|
||||
|
||||
/**
|
||||
* Represents assignment. An alternative to calling setValue() for an expression is to use
|
||||
* an assign.
|
||||
* Represents assignment. An alternative to calling {@code setValue}
|
||||
* for an expression which indicates an assign statement.
|
||||
*
|
||||
* <p>Example: 'someNumberProperty=42'
|
||||
*
|
||||
|
|
@ -31,8 +31,8 @@ import org.springframework.expression.spel.ExpressionState;
|
|||
*/
|
||||
public class Assign extends SpelNodeImpl {
|
||||
|
||||
public Assign(int pos,SpelNodeImpl... operands) {
|
||||
super(pos,operands);
|
||||
public Assign(int pos, SpelNodeImpl... operands) {
|
||||
super(pos, operands);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
private static final SpelNodeImpl[] NO_CHILDREN = new SpelNodeImpl[0];
|
||||
|
||||
|
||||
protected int pos; // start = top 16bits, end = bottom 16bits
|
||||
protected final int pos; // start = top 16bits, end = bottom 16bits
|
||||
|
||||
protected SpelNodeImpl[] children = SpelNodeImpl.NO_CHILDREN;
|
||||
|
||||
|
|
@ -69,8 +69,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
|
||||
public SpelNodeImpl(int pos, SpelNodeImpl... operands) {
|
||||
this.pos = pos;
|
||||
// pos combines start and end so can never be zero because tokens cannot be zero length
|
||||
Assert.isTrue(pos != 0, "Pos must not be 0");
|
||||
if (!ObjectUtils.isEmpty(operands)) {
|
||||
this.children = operands;
|
||||
for (SpelNodeImpl operand : operands) {
|
||||
|
|
@ -84,7 +82,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
/**
|
||||
* Return {@code true} if the next child is one of the specified classes.
|
||||
*/
|
||||
protected boolean nextChildIs(Class<?>... clazzes) {
|
||||
protected boolean nextChildIs(Class<?>... classes) {
|
||||
if (this.parent != null) {
|
||||
SpelNodeImpl[] peers = this.parent.children;
|
||||
for (int i = 0, max = peers.length; i < max; i++) {
|
||||
|
|
@ -92,9 +90,9 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
if (i + 1 >= max) {
|
||||
return false;
|
||||
}
|
||||
Class<?> clazz = peers[i + 1].getClass();
|
||||
for (Class<?> desiredClazz : clazzes) {
|
||||
if (clazz.equals(desiredClazz)) {
|
||||
Class<?> peerClass = peers[i + 1].getClass();
|
||||
for (Class<?> desiredClass : classes) {
|
||||
if (peerClass == desiredClass) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -146,11 +144,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
return (obj instanceof Class ? ((Class<?>) obj) : obj.getClass());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException {
|
||||
return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), getValueInternal(state), desiredReturnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartPosition() {
|
||||
return (this.pos >> 16);
|
||||
|
|
@ -161,10 +154,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
return (this.pos & 0xffff);
|
||||
}
|
||||
|
||||
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
|
||||
throw new SpelEvaluationException(this.pos, SpelMessage.NOT_ASSIGNABLE, toStringAST());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
@ -177,9 +166,8 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
|
||||
/**
|
||||
* Generate the bytecode for this node into the supplied visitor. Context info about
|
||||
* the current expression being compiled is available in the codeflow object. For
|
||||
* example it will include information about the type of the object currently
|
||||
* on the stack.
|
||||
* the current expression being compiled is available in the codeflow object, e.g.
|
||||
* including information about the type of the object currently on the stack.
|
||||
* @param mv the ASM MethodVisitor into which code should be generated
|
||||
* @param cf a context object with info about what is on the stack
|
||||
*/
|
||||
|
|
@ -192,6 +180,15 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
|||
return this.exitTypeDescriptor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final <T> T getValue(ExpressionState state, Class<T> desiredReturnType) throws EvaluationException {
|
||||
return ExpressionUtils.convertTypedValue(state.getEvaluationContext(), getValueInternal(state), desiredReturnType);
|
||||
}
|
||||
|
||||
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
|
||||
throw new SpelEvaluationException(getStartPosition(), SpelMessage.NOT_ASSIGNABLE, toStringAST());
|
||||
}
|
||||
|
||||
public abstract TypedValue getValueInternal(ExpressionState expressionState) throws EvaluationException;
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue