@@ -47,7 +47,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
47
47
private static final SpelNodeImpl [] NO_CHILDREN = new SpelNodeImpl [0 ];
48
48
49
49
50
- protected int pos ; // start = top 16bits, end = bottom 16bits
50
+ protected final int pos ; // start = top 16bits, end = bottom 16bits
51
51
52
52
protected SpelNodeImpl [] children = SpelNodeImpl .NO_CHILDREN ;
53
53
@@ -69,8 +69,6 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes {
69
69
70
70
public SpelNodeImpl (int pos , SpelNodeImpl ... operands ) {
71
71
this .pos = pos ;
72
- // pos combines start and end so can never be zero because tokens cannot be zero length
73
- Assert .isTrue (pos != 0 , "Pos must not be 0" );
74
72
if (!ObjectUtils .isEmpty (operands )) {
75
73
this .children = operands ;
76
74
for (SpelNodeImpl operand : operands ) {
@@ -84,17 +82,17 @@ public SpelNodeImpl(int pos, SpelNodeImpl... operands) {
84
82
/**
85
83
* Return {@code true} if the next child is one of the specified classes.
86
84
*/
87
- protected boolean nextChildIs (Class <?>... clazzes ) {
85
+ protected boolean nextChildIs (Class <?>... classes ) {
88
86
if (this .parent != null ) {
89
87
SpelNodeImpl [] peers = this .parent .children ;
90
88
for (int i = 0 , max = peers .length ; i < max ; i ++) {
91
89
if (this == peers [i ]) {
92
90
if (i + 1 >= max ) {
93
91
return false ;
94
92
}
95
- Class <?> clazz = peers [i + 1 ].getClass ();
96
- for (Class <?> desiredClazz : clazzes ) {
97
- if (clazz . equals ( desiredClazz ) ) {
93
+ Class <?> peerClass = peers [i + 1 ].getClass ();
94
+ for (Class <?> desiredClass : classes ) {
95
+ if (peerClass == desiredClass ) {
98
96
return true ;
99
97
}
100
98
}
@@ -146,11 +144,6 @@ public Class<?> getObjectClass(@Nullable Object obj) {
146
144
return (obj instanceof Class ? ((Class <?>) obj ) : obj .getClass ());
147
145
}
148
146
149
- @ Nullable
150
- protected final <T > T getValue (ExpressionState state , Class <T > desiredReturnType ) throws EvaluationException {
151
- return ExpressionUtils .convertTypedValue (state .getEvaluationContext (), getValueInternal (state ), desiredReturnType );
152
- }
153
-
154
147
@ Override
155
148
public int getStartPosition () {
156
149
return (this .pos >> 16 );
@@ -161,10 +154,6 @@ public int getEndPosition() {
161
154
return (this .pos & 0xffff );
162
155
}
163
156
164
- protected ValueRef getValueRef (ExpressionState state ) throws EvaluationException {
165
- throw new SpelEvaluationException (this .pos , SpelMessage .NOT_ASSIGNABLE , toStringAST ());
166
- }
167
-
168
157
/**
169
158
* Check whether a node can be compiled to bytecode. The reasoning in each node may
170
159
* be different but will typically involve checking whether the exit type descriptor
@@ -177,9 +166,8 @@ public boolean isCompilable() {
177
166
178
167
/**
179
168
* Generate the bytecode for this node into the supplied visitor. Context info about
180
- * the current expression being compiled is available in the codeflow object. For
181
- * example it will include information about the type of the object currently
182
- * on the stack.
169
+ * the current expression being compiled is available in the codeflow object, e.g.
170
+ * including information about the type of the object currently on the stack.
183
171
* @param mv the ASM MethodVisitor into which code should be generated
184
172
* @param cf a context object with info about what is on the stack
185
173
*/
@@ -192,9 +180,18 @@ public String getExitDescriptor() {
192
180
return this .exitTypeDescriptor ;
193
181
}
194
182
183
+ @ Nullable
184
+ protected final <T > T getValue (ExpressionState state , Class <T > desiredReturnType ) throws EvaluationException {
185
+ return ExpressionUtils .convertTypedValue (state .getEvaluationContext (), getValueInternal (state ), desiredReturnType );
186
+ }
187
+
188
+ protected ValueRef getValueRef (ExpressionState state ) throws EvaluationException {
189
+ throw new SpelEvaluationException (getStartPosition (), SpelMessage .NOT_ASSIGNABLE , toStringAST ());
190
+ }
191
+
195
192
public abstract TypedValue getValueInternal (ExpressionState expressionState ) throws EvaluationException ;
196
193
197
-
194
+
198
195
/**
199
196
* Generate code that handles building the argument values for the specified method.
200
197
* This method will take account of whether the invoked method is a varargs method
@@ -222,12 +219,12 @@ protected static void generateCodeForArguments(MethodVisitor mv, CodeFlow cf, Me
222
219
// have been passed to satisfy the varargs and so something needs to be built.
223
220
int p = 0 ; // Current supplied argument being processed
224
221
int childCount = arguments .length ;
225
-
222
+
226
223
// Fulfill all the parameter requirements except the last one
227
224
for (p = 0 ; p < paramDescriptors .length - 1 ; p ++) {
228
225
generateCodeForArgument (mv , cf , arguments [p ], paramDescriptors [p ]);
229
226
}
230
-
227
+
231
228
SpelNodeImpl lastChild = (childCount == 0 ? null : arguments [childCount - 1 ]);
232
229
String arrayType = paramDescriptors [paramDescriptors .length - 1 ];
233
230
// Determine if the final passed argument is already suitably packaged in array
0 commit comments