Skip to content

Commit 4c98814

Browse files
committed
Specify generic type nullness in spring-expression
See spring-projectsgh-34140
1 parent 9d9383a commit 4c98814

File tree

6 files changed

+31
-29
lines changed

6 files changed

+31
-29
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/ast/ConstructorReference.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -124,7 +124,7 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
124124
* @throws EvaluationException if there is a problem creating the object
125125
*/
126126
private TypedValue createNewInstance(ExpressionState state) throws EvaluationException {
127-
Object[] arguments = new Object[getChildCount() - 1];
127+
@Nullable Object[] arguments = new Object[getChildCount() - 1];
128128
List<TypeDescriptor> argumentTypes = new ArrayList<>(getChildCount() - 1);
129129
for (int i = 0; i < arguments.length; i++) {
130130
TypedValue childValue = this.children[i + 1].getValueInternal(state);
@@ -359,7 +359,7 @@ private void checkNumElements(long numElements) {
359359
private Object createReferenceTypeArray(ExpressionState state, TypeConverter typeConverter, SpelNodeImpl[] children,
360360
Class<?> componentType) {
361361

362-
Object[] array = (Object[]) Array.newInstance(componentType, children.length);
362+
@Nullable Object[] array = (Object[]) Array.newInstance(componentType, children.length);
363363
TypeDescriptor targetType = TypeDescriptor.valueOf(componentType);
364364
for (int i = 0; i < array.length; i++) {
365365
Object value = children[i].getValue(state);

spring-expression/src/main/java/org/springframework/expression/spel/ast/FunctionReference.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -116,7 +116,7 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
116116
* @throws EvaluationException if there is any problem invoking the method
117117
*/
118118
private TypedValue executeFunctionViaMethod(ExpressionState state, Method method) throws EvaluationException {
119-
Object[] functionArgs = getArguments(state);
119+
@Nullable Object[] functionArgs = getArguments(state);
120120

121121
if (!method.isVarArgs()) {
122122
int declaredParamCount = method.getParameterCount();
@@ -175,7 +175,7 @@ private TypedValue executeFunctionViaMethod(ExpressionState state, Method method
175175
* @since 6.1
176176
*/
177177
private TypedValue executeFunctionViaMethodHandle(ExpressionState state, MethodHandle methodHandle) throws EvaluationException {
178-
Object[] functionArgs = getArguments(state);
178+
@Nullable Object[] functionArgs = getArguments(state);
179179
MethodType declaredParams = methodHandle.type();
180180
int spelParamCount = functionArgs.length;
181181
int declaredParamCount = declaredParams.parameterCount();
@@ -280,9 +280,9 @@ public String toStringAST() {
280280
* Compute the arguments to the function, they are the children of this expression node.
281281
* @return an array of argument values for the function call
282282
*/
283-
private Object[] getArguments(ExpressionState state) throws EvaluationException {
283+
private @Nullable Object[] getArguments(ExpressionState state) throws EvaluationException {
284284
// Compute arguments to the function
285-
Object[] arguments = new Object[getChildCount()];
285+
@Nullable Object[] arguments = new Object[getChildCount()];
286286
for (int i = 0; i < arguments.length; i++) {
287287
arguments[i] = this.children[i].getValueInternal(state).getValue();
288288
}

spring-expression/src/main/java/org/springframework/expression/spel/ast/MethodReference.java

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -90,7 +90,7 @@ public final String getName() {
9090

9191
@Override
9292
protected ValueRef getValueRef(ExpressionState state) throws EvaluationException {
93-
Object[] arguments = getArguments(state);
93+
@Nullable Object[] arguments = getArguments(state);
9494
if (state.getActiveContextObject().getValue() == null) {
9595
throwIfNotNullSafe(getArgumentTypes(arguments));
9696
return ValueRef.NullValueRef.INSTANCE;
@@ -103,14 +103,14 @@ public TypedValue getValueInternal(ExpressionState state) throws EvaluationExcep
103103
EvaluationContext evaluationContext = state.getEvaluationContext();
104104
Object value = state.getActiveContextObject().getValue();
105105
TypeDescriptor targetType = state.getActiveContextObject().getTypeDescriptor();
106-
Object[] arguments = getArguments(state);
106+
@Nullable Object[] arguments = getArguments(state);
107107
TypedValue result = getValueInternal(evaluationContext, value, targetType, arguments);
108108
updateExitTypeDescriptor();
109109
return result;
110110
}
111111

112112
private TypedValue getValueInternal(EvaluationContext evaluationContext,
113-
@Nullable Object value, @Nullable TypeDescriptor targetType, Object[] arguments) {
113+
@Nullable Object value, @Nullable TypeDescriptor targetType, @Nullable Object[] arguments) {
114114

115115
List<TypeDescriptor> argumentTypes = getArgumentTypes(arguments);
116116
if (value == null) {
@@ -167,8 +167,8 @@ private void throwIfNotNullSafe(List<TypeDescriptor> argumentTypes) {
167167
}
168168
}
169169

170-
private Object[] getArguments(ExpressionState state) {
171-
Object[] arguments = new Object[getChildCount()];
170+
private @Nullable Object[] getArguments(ExpressionState state) {
171+
@Nullable Object[] arguments = new Object[getChildCount()];
172172
for (int i = 0; i < arguments.length; i++) {
173173
// Make the root object the active context again for evaluating the parameter expressions
174174
try {
@@ -182,8 +182,8 @@ private Object[] getArguments(ExpressionState state) {
182182
return arguments;
183183
}
184184

185-
private List<TypeDescriptor> getArgumentTypes(Object... arguments) {
186-
List<TypeDescriptor> descriptors = new ArrayList<>(arguments.length);
185+
private List<TypeDescriptor> getArgumentTypes(@Nullable Object... arguments) {
186+
List<@Nullable TypeDescriptor> descriptors = new ArrayList<>(arguments.length);
187187
for (Object argument : arguments) {
188188
descriptors.add(TypeDescriptor.forObject(argument));
189189
}
@@ -380,9 +380,9 @@ private class MethodValueRef implements ValueRef {
380380

381381
private final @Nullable TypeDescriptor targetType;
382382

383-
private final Object[] arguments;
383+
private final @Nullable Object[] arguments;
384384

385-
public MethodValueRef(ExpressionState state, Object[] arguments) {
385+
public MethodValueRef(ExpressionState state, @Nullable Object[] arguments) {
386386
this.evaluationContext = state.getEvaluationContext();
387387
this.value = state.getActiveContextObject().getValue();
388388
this.targetType = state.getActiveContextObject().getTypeDescriptor();

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -250,7 +250,7 @@ else if (typeConverter.canConvert(suppliedArg, TypeDescriptor.valueOf(varargsCom
250250
* @return {@code true} if some kind of conversion occurred on an argument
251251
* @throws SpelEvaluationException if a problem occurs during conversion
252252
*/
253-
public static boolean convertAllArguments(TypeConverter converter, Object[] arguments, Method method)
253+
public static boolean convertAllArguments(TypeConverter converter, @Nullable Object[] arguments, Method method)
254254
throws SpelEvaluationException {
255255

256256
Integer varargsPosition = (method.isVarArgs() ? method.getParameterCount() - 1 : null);
@@ -269,7 +269,8 @@ public static boolean convertAllArguments(TypeConverter converter, Object[] argu
269269
* @return {@code true} if some kind of conversion occurred on an argument
270270
* @throws EvaluationException if a problem occurs during conversion
271271
*/
272-
static boolean convertArguments(TypeConverter converter, Object[] arguments, Executable executable,
272+
@SuppressWarnings("NullAway") // Dataflow analysis limitation
273+
static boolean convertArguments(TypeConverter converter, @Nullable Object[] arguments, Executable executable,
273274
@Nullable Integer varargsPosition) throws EvaluationException {
274275

275276
boolean conversionOccurred = false;
@@ -359,7 +360,8 @@ else if (!sourceType.isAssignableTo(componentTypeDesc) ||
359360
* @throws EvaluationException if a problem occurs during conversion
360361
* @since 6.1
361362
*/
362-
public static boolean convertAllMethodHandleArguments(TypeConverter converter, Object[] arguments,
363+
@SuppressWarnings("NullAway") // Dataflow analysis limitation
364+
public static boolean convertAllMethodHandleArguments(TypeConverter converter, @Nullable Object[] arguments,
363365
MethodHandle methodHandle, @Nullable Integer varargsPosition) throws EvaluationException {
364366

365367
boolean conversionOccurred = false;
@@ -453,7 +455,7 @@ else if (!sourceType.isAssignableTo(varargsComponentType) ||
453455
* @param possibleArray an array object that may have the supplied value as the first element
454456
* @return true if the supplied value is the first entry in the array
455457
*/
456-
private static boolean isFirstEntryInArray(Object value, @Nullable Object possibleArray) {
458+
private static boolean isFirstEntryInArray(@Nullable Object value, @Nullable Object possibleArray) {
457459
if (possibleArray == null) {
458460
return false;
459461
}
@@ -477,7 +479,7 @@ private static boolean isFirstEntryInArray(Object value, @Nullable Object possib
477479
* @param args the arguments to be set up for the invocation
478480
* @return a repackaged array of arguments where any varargs setup has been performed
479481
*/
480-
public static Object[] setupArgumentsForVarargsInvocation(Class<?>[] requiredParameterTypes, Object... args) {
482+
public static @Nullable Object[] setupArgumentsForVarargsInvocation(Class<?>[] requiredParameterTypes, @Nullable Object... args) {
481483
Assert.notEmpty(requiredParameterTypes, "Required parameter types array must not be empty");
482484

483485
int parameterCount = requiredParameterTypes.length;
@@ -491,7 +493,7 @@ public static Object[] setupArgumentsForVarargsInvocation(Class<?>[] requiredPar
491493
// Check if repackaging is needed...
492494
if (parameterCount != argumentCount || !lastRequiredParameterType.isInstance(lastArgument)) {
493495
// Create an array for the leading arguments plus the varargs array argument.
494-
Object[] newArgs = new Object[parameterCount];
496+
@Nullable Object[] newArgs = new Object[parameterCount];
495497
// Copy all leading arguments to the new array, omitting the varargs array argument.
496498
System.arraycopy(args, 0, newArgs, 0, newArgs.length - 1);
497499

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveConstructorExecutor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -52,7 +52,7 @@ public ReflectiveConstructorExecutor(Constructor<?> ctor) {
5252
}
5353

5454
@Override
55-
public TypedValue execute(EvaluationContext context, Object... arguments) throws AccessException {
55+
public TypedValue execute(EvaluationContext context, @Nullable Object... arguments) throws AccessException {
5656
try {
5757
ReflectionHelper.convertArguments(
5858
context.getTypeConverter(), arguments, this.ctor, this.varargsPosition);

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectiveMethodExecutor.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2024 the original author or authors.
2+
* Copyright 2002-2025 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -102,7 +102,7 @@ public boolean didArgumentConversionOccur() {
102102

103103

104104
@Override
105-
public TypedValue execute(EvaluationContext context, Object target, Object... arguments) throws AccessException {
105+
public TypedValue execute(EvaluationContext context, Object target, @Nullable Object... arguments) throws AccessException {
106106
try {
107107
this.argumentConversionOccurred = ReflectionHelper.convertArguments(
108108
context.getTypeConverter(), arguments, this.originalMethod, this.varargsPosition);

0 commit comments

Comments
 (0)