Relaxed position assertion (for overflows in large inline maps)
Issue: SPR-17605
(cherry picked from commit b2756f5bd2)
This commit is contained in:
@@ -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,9 +180,18 @@ 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;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generate code that handles building the argument values for the specified method.
|
||||
* This method will take account of whether the invoked method is a varargs method
|
||||
@@ -222,12 +219,12 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
|
||||
// have been passed to satisfy the varargs and so something needs to be built.
|
||||
int p = 0; // Current supplied argument being processed
|
||||
int childCount = arguments.length;
|
||||
|
||||
|
||||
// Fulfill all the parameter requirements except the last one
|
||||
for (p = 0; p < paramDescriptors.length - 1; p++) {
|
||||
generateCodeForArgument(mv, cf, arguments[p], paramDescriptors[p]);
|
||||
}
|
||||
|
||||
|
||||
SpelNodeImpl lastChild = (childCount == 0 ? null : arguments[childCount - 1]);
|
||||
String arrayType = paramDescriptors[paramDescriptors.length - 1];
|
||||
// Determine if the final passed argument is already suitably packaged in array
|
||||
|
||||
Reference in New Issue
Block a user