Specify generic type nullness in spring-core
Also in spring-core-test. See gh-34140
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -37,7 +37,7 @@ final class CompileWithForkedClassLoaderClassLoader extends ClassLoader {
|
||||
|
||||
private final ClassLoader testClassLoader;
|
||||
|
||||
private Function<String, byte[]> classResourceLookup = name -> null;
|
||||
private Function<String, byte @Nullable []> classResourceLookup = name -> null;
|
||||
|
||||
|
||||
public CompileWithForkedClassLoaderClassLoader(ClassLoader testClassLoader) {
|
||||
@@ -48,7 +48,7 @@ final class CompileWithForkedClassLoaderClassLoader extends ClassLoader {
|
||||
|
||||
// Invoked reflectively by DynamicClassLoader
|
||||
@SuppressWarnings("unused")
|
||||
void setClassResourceLookup(Function<String, byte[]> classResourceLookup) {
|
||||
void setClassResourceLookup(Function<String, byte @Nullable []> classResourceLookup) {
|
||||
this.classResourceLookup = classResourceLookup;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -71,7 +71,7 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
"setClassResourceLookup", Function.class);
|
||||
ReflectionUtils.makeAccessible(setClassResourceLookupMethod);
|
||||
ReflectionUtils.invokeMethod(setClassResourceLookupMethod,
|
||||
getParent(), (Function<String, byte[]>) this::findClassBytes);
|
||||
getParent(), (Function<String, byte @Nullable []>) this::findClassBytes);
|
||||
this.defineClassMethod = lookupMethod(parentClass,
|
||||
"defineDynamicClass", String.class, byte[].class, int.class, int.class);
|
||||
ReflectionUtils.makeAccessible(this.defineClassMethod);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -106,7 +106,7 @@ public interface MethodReference {
|
||||
* @param function the resolver function
|
||||
* @return a new {@link ArgumentCodeGenerator} instance backed by the function
|
||||
*/
|
||||
static ArgumentCodeGenerator from(Function<TypeName, CodeBlock> function) {
|
||||
static ArgumentCodeGenerator from(Function<TypeName, @Nullable CodeBlock> function) {
|
||||
return function::apply;
|
||||
}
|
||||
|
||||
|
||||
@@ -706,7 +706,7 @@ public class MethodParameter {
|
||||
}
|
||||
ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
|
||||
if (discoverer != null) {
|
||||
String[] parameterNames = null;
|
||||
@Nullable String[] parameterNames = null;
|
||||
if (this.executable instanceof Method method) {
|
||||
parameterNames = discoverer.getParameterNames(method);
|
||||
}
|
||||
@@ -865,7 +865,7 @@ public class MethodParameter {
|
||||
* @return the corresponding MethodParameter instance
|
||||
* @since 6.1
|
||||
*/
|
||||
public static MethodParameter forFieldAwareConstructor(Constructor<?> ctor, int parameterIndex, String fieldName) {
|
||||
public static MethodParameter forFieldAwareConstructor(Constructor<?> ctor, int parameterIndex, @Nullable String fieldName) {
|
||||
return new FieldAwareConstructorParameter(ctor, parameterIndex, fieldName);
|
||||
}
|
||||
|
||||
@@ -877,7 +877,7 @@ public class MethodParameter {
|
||||
|
||||
private volatile Annotation @Nullable [] combinedAnnotations;
|
||||
|
||||
public FieldAwareConstructorParameter(Constructor<?> constructor, int parameterIndex, String fieldName) {
|
||||
public FieldAwareConstructorParameter(Constructor<?> constructor, int parameterIndex, @Nullable String fieldName) {
|
||||
super(constructor, parameterIndex);
|
||||
this.parameterName = fieldName;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -19,12 +19,15 @@ package org.springframework.core;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionStage;
|
||||
import java.util.concurrent.Flow;
|
||||
import java.util.function.Function;
|
||||
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.reactivestreams.FlowAdapters;
|
||||
import org.reactivestreams.Publisher;
|
||||
@@ -380,13 +383,13 @@ public class ReactiveAdapterRegistry {
|
||||
io.smallrye.mutiny.groups.MultiCreate.class, "publisher", Flow.Publisher.class);
|
||||
registry.registerReactiveType(uniDesc,
|
||||
uni -> FlowAdapters.toPublisher((Flow.Publisher<Object>)
|
||||
ReflectionUtils.invokeMethod(uniToPublisher, ((io.smallrye.mutiny.Uni<?>) uni).convert())),
|
||||
publisher -> ReflectionUtils.invokeMethod(uniPublisher, io.smallrye.mutiny.Uni.createFrom(),
|
||||
FlowAdapters.toFlowPublisher(publisher)));
|
||||
Objects.requireNonNull(ReflectionUtils.invokeMethod(uniToPublisher, ((Uni<?>) uni).convert()))),
|
||||
publisher -> Objects.requireNonNull(ReflectionUtils.invokeMethod(uniPublisher, Uni.createFrom(),
|
||||
FlowAdapters.toFlowPublisher(publisher))));
|
||||
registry.registerReactiveType(multiDesc,
|
||||
multi -> FlowAdapters.toPublisher((Flow.Publisher<Object>) multi),
|
||||
publisher -> ReflectionUtils.invokeMethod(multiPublisher, io.smallrye.mutiny.Multi.createFrom(),
|
||||
FlowAdapters.toFlowPublisher(publisher)));
|
||||
publisher -> Objects.requireNonNull(ReflectionUtils.invokeMethod(multiPublisher, Multi.createFrom(),
|
||||
FlowAdapters.toFlowPublisher(publisher))));
|
||||
}
|
||||
else {
|
||||
// Mutiny 1 based on Reactive Streams
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -825,9 +825,9 @@ public class ResolvableType implements Serializable {
|
||||
* @see #getGenerics()
|
||||
* @see #resolve()
|
||||
*/
|
||||
public Class<?>[] resolveGenerics() {
|
||||
public @Nullable Class<?>[] resolveGenerics() {
|
||||
ResolvableType[] generics = getGenerics();
|
||||
Class<?>[] resolvedGenerics = new Class<?>[generics.length];
|
||||
@Nullable Class<?>[] resolvedGenerics = new Class<?>[generics.length];
|
||||
for (int i = 0; i < generics.length; i++) {
|
||||
resolvedGenerics[i] = generics[i].resolve();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -205,7 +205,7 @@ final class SerializableTypeWrapper {
|
||||
if (returnValue == null) {
|
||||
return null;
|
||||
}
|
||||
Type[] result = new Type[((Type[]) returnValue).length];
|
||||
@Nullable Type[] result = new Type[((Type[]) returnValue).length];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, i));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -478,7 +478,7 @@ public abstract class AnnotatedElementUtils {
|
||||
* attributes from all annotations found, or {@code null} if not found
|
||||
* @see #getAllAnnotationAttributes(AnnotatedElement, String, boolean, boolean)
|
||||
*/
|
||||
public static @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(
|
||||
public static MultiValueMap<String, @Nullable Object> getAllAnnotationAttributes(
|
||||
AnnotatedElement element, String annotationName) {
|
||||
|
||||
return getAllAnnotationAttributes(element, annotationName, false, false);
|
||||
@@ -502,7 +502,7 @@ public abstract class AnnotatedElementUtils {
|
||||
* @return a {@link MultiValueMap} keyed by attribute name, containing the annotation
|
||||
* attributes from all annotations found, or {@code null} if not found
|
||||
*/
|
||||
public static @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(AnnotatedElement element,
|
||||
public static MultiValueMap<String, @Nullable Object> getAllAnnotationAttributes(AnnotatedElement element,
|
||||
String annotationName, final boolean classValuesAsString, final boolean nestedAnnotationsAsMap) {
|
||||
|
||||
Adapt[] adaptations = Adapt.values(classValuesAsString, nestedAnnotationsAsMap);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -45,7 +45,7 @@ import org.springframework.util.StringUtils;
|
||||
* @see AnnotatedElementUtils
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
public class AnnotationAttributes extends LinkedHashMap<String, @Nullable Object> {
|
||||
|
||||
private static final String UNKNOWN = "unknown";
|
||||
|
||||
@@ -83,7 +83,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
* @param map original source of annotation attribute <em>key-value</em> pairs
|
||||
* @see #fromMap(Map)
|
||||
*/
|
||||
public AnnotationAttributes(Map<String, Object> map) {
|
||||
public AnnotationAttributes(Map<String, @Nullable Object> map) {
|
||||
super(map);
|
||||
this.annotationType = null;
|
||||
this.displayName = UNKNOWN;
|
||||
@@ -376,10 +376,10 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
Iterator<Map.Entry<String, Object>> entries = entrySet().iterator();
|
||||
Iterator<Map.Entry<String, @Nullable Object>> entries = entrySet().iterator();
|
||||
StringBuilder sb = new StringBuilder("{");
|
||||
while (entries.hasNext()) {
|
||||
Map.Entry<String, Object> entry = entries.next();
|
||||
Map.Entry<String, @Nullable Object> entry = entries.next();
|
||||
sb.append(entry.getKey());
|
||||
sb.append('=');
|
||||
sb.append(valueToString(entry.getValue()));
|
||||
@@ -391,7 +391,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String valueToString(Object value) {
|
||||
private String valueToString(@Nullable Object value) {
|
||||
if (value == this) {
|
||||
return "(this Map)";
|
||||
}
|
||||
@@ -410,7 +410,7 @@ public class AnnotationAttributes extends LinkedHashMap<String, Object> {
|
||||
* to the {@link #AnnotationAttributes(Map)} constructor.
|
||||
* @param map original source of annotation attribute <em>key-value</em> pairs
|
||||
*/
|
||||
public static @Nullable AnnotationAttributes fromMap(@Nullable Map<String, Object> map) {
|
||||
public static @Nullable AnnotationAttributes fromMap(@Nullable Map<String, @Nullable Object> map) {
|
||||
if (map == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -27,6 +27,7 @@ import java.util.Set;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Contract;
|
||||
import org.springframework.util.ConcurrentReferenceHashMap;
|
||||
|
||||
/**
|
||||
@@ -87,7 +88,7 @@ final class AnnotationTypeMappings {
|
||||
}
|
||||
|
||||
private void addMetaAnnotationsToQueue(Deque<AnnotationTypeMapping> queue, AnnotationTypeMapping source) {
|
||||
Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(source.getAnnotationType(), false);
|
||||
@Nullable Annotation[] metaAnnotations = AnnotationsScanner.getDeclaredAnnotations(source.getAnnotationType(), false);
|
||||
for (Annotation metaAnnotation : metaAnnotations) {
|
||||
if (!isMappable(source, metaAnnotation)) {
|
||||
continue;
|
||||
@@ -127,6 +128,7 @@ final class AnnotationTypeMappings {
|
||||
}
|
||||
}
|
||||
|
||||
@Contract("_, null -> false")
|
||||
private boolean isMappable(AnnotationTypeMapping source, @Nullable Annotation metaAnnotation) {
|
||||
return (metaAnnotation != null && !this.filter.matches(metaAnnotation) &&
|
||||
!AnnotationFilter.PLAIN.matches(source.getAnnotationType()) &&
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -773,7 +773,7 @@ public abstract class AnnotationUtils {
|
||||
* @see #getAnnotationAttributes(Annotation, boolean, boolean)
|
||||
* @see #getAnnotationAttributes(AnnotatedElement, Annotation, boolean, boolean)
|
||||
*/
|
||||
public static Map<String, Object> getAnnotationAttributes(Annotation annotation) {
|
||||
public static Map<String, @Nullable Object> getAnnotationAttributes(Annotation annotation) {
|
||||
return getAnnotationAttributes(null, annotation);
|
||||
}
|
||||
|
||||
@@ -791,7 +791,7 @@ public abstract class AnnotationUtils {
|
||||
* corresponding attribute values as values (never {@code null})
|
||||
* @see #getAnnotationAttributes(Annotation, boolean, boolean)
|
||||
*/
|
||||
public static Map<String, Object> getAnnotationAttributes(
|
||||
public static Map<String, @Nullable Object> getAnnotationAttributes(
|
||||
Annotation annotation, boolean classValuesAsString) {
|
||||
|
||||
return getAnnotationAttributes(annotation, classValuesAsString, false);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -54,7 +54,7 @@ interface AnnotationsProcessor<C, R> {
|
||||
* {@code null} elements)
|
||||
* @return a {@code non-null} result if no further processing is required
|
||||
*/
|
||||
@Nullable R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, Annotation[] annotations);
|
||||
@Nullable R doWithAnnotations(C context, int aggregateIndex, @Nullable Object source, @Nullable Annotation[] annotations);
|
||||
|
||||
/**
|
||||
* Get the final result to be returned. By default this method returns
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -47,7 +47,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
abstract class AnnotationsScanner {
|
||||
|
||||
private static final Annotation[] NO_ANNOTATIONS = {};
|
||||
private static final @Nullable Annotation[] NO_ANNOTATIONS = {};
|
||||
|
||||
private static final Method[] NO_METHODS = {};
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class AnnotationsScanner {
|
||||
private static final Map<AnnotatedElement, Annotation[]> declaredAnnotationCache =
|
||||
new ConcurrentReferenceHashMap<>(256);
|
||||
|
||||
private static final Map<Class<?>, Method[]> baseTypeMethodsCache =
|
||||
private static final Map<Class<?>, @Nullable Method[]> baseTypeMethodsCache =
|
||||
new ConcurrentReferenceHashMap<>(256);
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ abstract class AnnotationsScanner {
|
||||
if (isWithoutHierarchy(source, Search.never)) {
|
||||
return processElement(context, source, processor);
|
||||
}
|
||||
Annotation[] relevant = null;
|
||||
@Nullable Annotation[] relevant = null;
|
||||
int remaining = Integer.MAX_VALUE;
|
||||
int aggregateIndex = 0;
|
||||
Class<?> root = source;
|
||||
@@ -123,7 +123,7 @@ abstract class AnnotationsScanner {
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
Annotation[] declaredAnns = getDeclaredAnnotations(source, true);
|
||||
@Nullable Annotation[] declaredAnns = getDeclaredAnnotations(source, true);
|
||||
if (declaredAnns.length > 0) {
|
||||
if (relevant == null) {
|
||||
relevant = root.getAnnotations();
|
||||
@@ -133,6 +133,7 @@ abstract class AnnotationsScanner {
|
||||
if (declaredAnns[i] != null) {
|
||||
boolean isRelevant = false;
|
||||
for (int relevantIndex = 0; relevantIndex < relevant.length; relevantIndex++) {
|
||||
//noinspection DataFlowIssue
|
||||
if (relevant[relevantIndex] != null &&
|
||||
declaredAnns[i].annotationType() == relevant[relevantIndex].annotationType()) {
|
||||
isRelevant = true;
|
||||
@@ -181,7 +182,7 @@ abstract class AnnotationsScanner {
|
||||
if (hasPlainJavaAnnotationsOnly(source)) {
|
||||
return null;
|
||||
}
|
||||
Annotation[] annotations = getDeclaredAnnotations(source, false);
|
||||
@Nullable Annotation[] annotations = getDeclaredAnnotations(source, false);
|
||||
result = processor.doWithAnnotations(context, aggregateIndex[0], source, annotations);
|
||||
if (result != null) {
|
||||
return result;
|
||||
@@ -320,16 +321,18 @@ abstract class AnnotationsScanner {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static <C> Method[] getBaseTypeMethods(C context, Class<?> baseType) {
|
||||
@SuppressWarnings("NullAway") // Dataflow analysis limitation
|
||||
private static <C> @Nullable Method[] getBaseTypeMethods(C context, Class<?> baseType) {
|
||||
if (baseType == Object.class || hasPlainJavaAnnotationsOnly(baseType)) {
|
||||
return NO_METHODS;
|
||||
}
|
||||
|
||||
Method[] methods = baseTypeMethodsCache.get(baseType);
|
||||
@Nullable Method[] methods = baseTypeMethodsCache.get(baseType);
|
||||
if (methods == null) {
|
||||
methods = ReflectionUtils.getDeclaredMethods(baseType);
|
||||
int cleared = 0;
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
//noinspection DataFlowIssue
|
||||
if (Modifier.isPrivate(methods[i].getModifiers()) ||
|
||||
hasPlainJavaAnnotationsOnly(methods[i]) ||
|
||||
getDeclaredAnnotations(methods[i], false).length == 0) {
|
||||
@@ -385,14 +388,14 @@ abstract class AnnotationsScanner {
|
||||
private static <C, R> @Nullable R processMethodAnnotations(C context, int aggregateIndex, Method source,
|
||||
AnnotationsProcessor<C, R> processor) {
|
||||
|
||||
Annotation[] annotations = getDeclaredAnnotations(source, false);
|
||||
@Nullable Annotation[] annotations = getDeclaredAnnotations(source, false);
|
||||
R result = processor.doWithAnnotations(context, aggregateIndex, source, annotations);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(source);
|
||||
if (bridgedMethod != source) {
|
||||
Annotation[] bridgedAnnotations = getDeclaredAnnotations(bridgedMethod, true);
|
||||
@Nullable Annotation[] bridgedAnnotations = getDeclaredAnnotations(bridgedMethod, true);
|
||||
for (int i = 0; i < bridgedAnnotations.length; i++) {
|
||||
if (ObjectUtils.containsElement(annotations, bridgedAnnotations[i])) {
|
||||
bridgedAnnotations[i] = null;
|
||||
@@ -419,7 +422,7 @@ abstract class AnnotationsScanner {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <A extends Annotation> @Nullable A getDeclaredAnnotation(AnnotatedElement source, Class<A> annotationType) {
|
||||
Annotation[] annotations = getDeclaredAnnotations(source, false);
|
||||
@Nullable Annotation[] annotations = getDeclaredAnnotations(source, false);
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation != null && annotationType == annotation.annotationType()) {
|
||||
return (A) annotation;
|
||||
@@ -428,9 +431,10 @@ abstract class AnnotationsScanner {
|
||||
return null;
|
||||
}
|
||||
|
||||
static Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {
|
||||
@SuppressWarnings("NullAway") // Dataflow analysis limitation
|
||||
static @Nullable Annotation[] getDeclaredAnnotations(AnnotatedElement source, boolean defensive) {
|
||||
boolean cached = false;
|
||||
Annotation[] annotations = declaredAnnotationCache.get(source);
|
||||
@Nullable Annotation[] annotations = declaredAnnotationCache.get(source);
|
||||
if (annotations != null) {
|
||||
cached = true;
|
||||
}
|
||||
@@ -440,6 +444,7 @@ abstract class AnnotationsScanner {
|
||||
boolean allIgnored = true;
|
||||
for (int i = 0; i < annotations.length; i++) {
|
||||
Annotation annotation = annotations[i];
|
||||
//noinspection DataFlowIssue
|
||||
if (isIgnorable(annotation.annotationType()) ||
|
||||
!AttributeMethods.forAnnotationType(annotation.annotationType()).canLoad(annotation)) {
|
||||
annotations[i] = null;
|
||||
@@ -450,6 +455,7 @@ abstract class AnnotationsScanner {
|
||||
}
|
||||
annotations = (allIgnored ? NO_ANNOTATIONS : annotations);
|
||||
if (source instanceof Class || source instanceof Member) {
|
||||
//noinspection NullableProblems
|
||||
declaredAnnotationCache.put(source, annotations);
|
||||
cached = true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -250,11 +250,13 @@ final class AttributeMethods {
|
||||
return cache.computeIfAbsent(annotationType, AttributeMethods::compute);
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullAway") // Dataflow analysis limitation
|
||||
private static AttributeMethods compute(Class<? extends Annotation> annotationType) {
|
||||
Method[] methods = annotationType.getDeclaredMethods();
|
||||
int size = methods.length;
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (!isAttributeMethod(methods[i])) {
|
||||
//noinspection DataFlowIssue
|
||||
methods[i] = null;
|
||||
size--;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -26,6 +26,8 @@ import java.util.function.IntFunction;
|
||||
import java.util.stream.Collector;
|
||||
import java.util.stream.Collector.Characteristics;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.core.annotation.MergedAnnotation.Adapt;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -108,10 +110,10 @@ public abstract class MergedAnnotationCollectors {
|
||||
* annotations into a {@link LinkedMultiValueMap}
|
||||
* @see #toMultiValueMap(Function, MergedAnnotation.Adapt...)
|
||||
*/
|
||||
public static <A extends Annotation> Collector<MergedAnnotation<A>, ?, MultiValueMap<String, Object>> toMultiValueMap(
|
||||
public static <A extends Annotation> Collector<MergedAnnotation<A>, ? extends @Nullable Object, @Nullable MultiValueMap<String, @Nullable Object>> toMultiValueMap(
|
||||
Adapt... adaptations) {
|
||||
|
||||
return toMultiValueMap(Function.identity(), adaptations);
|
||||
return toMultiValueMap((MultiValueMap<String, @Nullable Object> t) -> t, adaptations);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,14 +128,14 @@ public abstract class MergedAnnotationCollectors {
|
||||
* annotations into a {@link LinkedMultiValueMap}
|
||||
* @see #toMultiValueMap(MergedAnnotation.Adapt...)
|
||||
*/
|
||||
public static <A extends Annotation> Collector<MergedAnnotation<A>, ?, MultiValueMap<String, Object>> toMultiValueMap(
|
||||
Function<MultiValueMap<String, Object>, MultiValueMap<String, Object>> finisher,
|
||||
public static <A extends Annotation> Collector<MergedAnnotation<A>, ? extends @Nullable Object, @Nullable MultiValueMap<String, @Nullable Object>> toMultiValueMap(
|
||||
Function<MultiValueMap<String, @Nullable Object>, @Nullable MultiValueMap<String, @Nullable Object>> finisher,
|
||||
Adapt... adaptations) {
|
||||
|
||||
Characteristics[] characteristics = (isSameInstance(finisher, Function.identity()) ?
|
||||
IDENTITY_FINISH_CHARACTERISTICS : NO_CHARACTERISTICS);
|
||||
return Collector.of(LinkedMultiValueMap::new,
|
||||
(map, annotation) -> annotation.asMap(adaptations).forEach(map::add),
|
||||
(MultiValueMap<String, @Nullable Object> map, MergedAnnotation<A> annotation) -> annotation.asMap(adaptations).forEach(map::add),
|
||||
MergedAnnotationCollectors::combiner, finisher, characteristics);
|
||||
}
|
||||
|
||||
@@ -157,7 +159,7 @@ public abstract class MergedAnnotationCollectors {
|
||||
* <p>This method is only invoked if the {@link java.util.stream.Stream} is
|
||||
* processed in {@linkplain java.util.stream.Stream#parallel() parallel}.
|
||||
*/
|
||||
private static <K, V> MultiValueMap<K, V> combiner(MultiValueMap<K, V> map, MultiValueMap<K, V> additions) {
|
||||
private static <K, V> MultiValueMap<K, @Nullable V> combiner(MultiValueMap<K, @Nullable V> map, MultiValueMap<K, @Nullable V> additions) {
|
||||
map.addAll(additions);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -23,8 +23,6 @@ import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -126,7 +124,8 @@ public abstract class MergedAnnotationPredicates {
|
||||
|
||||
private boolean hasLastValue;
|
||||
|
||||
private @Nullable Object lastValue;
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private Object lastValue;
|
||||
|
||||
FirstRunOfPredicate(Function<? super MergedAnnotation<A>, ?> valueExtractor) {
|
||||
Assert.notNull(valueExtractor, "Value extractor must not be null");
|
||||
@@ -134,7 +133,7 @@ public abstract class MergedAnnotationPredicates {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(@Nullable MergedAnnotation<A> annotation) {
|
||||
public boolean test(MergedAnnotation<A> annotation) {
|
||||
if (!this.hasLastValue) {
|
||||
this.hasLastValue = true;
|
||||
this.lastValue = this.valueExtractor.apply(annotation);
|
||||
@@ -162,7 +161,7 @@ public abstract class MergedAnnotationPredicates {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(@Nullable MergedAnnotation<A> annotation) {
|
||||
public boolean test(MergedAnnotation<A> annotation) {
|
||||
K key = this.keyExtractor.apply(annotation);
|
||||
return this.seen.add(key);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -29,6 +29,7 @@ import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
/**
|
||||
@@ -309,7 +310,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||
|
||||
@Override
|
||||
public @Nullable Boolean doWithAnnotations(Object requiredType, int aggregateIndex,
|
||||
@Nullable Object source, Annotation[] annotations) {
|
||||
@Nullable Object source, @Nullable Annotation[] annotations) {
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation != null) {
|
||||
@@ -388,7 +389,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||
|
||||
@Override
|
||||
public @Nullable MergedAnnotation<A> doWithAnnotations(Object type, int aggregateIndex,
|
||||
@Nullable Object source, Annotation[] annotations) {
|
||||
@Nullable Object source, @Nullable Annotation[] annotations) {
|
||||
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation != null && !annotationFilter.matches(annotation)) {
|
||||
@@ -450,24 +451,24 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||
|
||||
@Override
|
||||
public @Nullable List<Aggregate> doWithAnnotations(Object criteria, int aggregateIndex,
|
||||
@Nullable Object source, Annotation[] annotations) {
|
||||
@Nullable Object source, @Nullable Annotation[] annotations) {
|
||||
|
||||
this.aggregates.add(createAggregate(aggregateIndex, source, annotations));
|
||||
return null;
|
||||
}
|
||||
|
||||
private Aggregate createAggregate(int aggregateIndex, @Nullable Object source, Annotation[] annotations) {
|
||||
private Aggregate createAggregate(int aggregateIndex, @Nullable Object source, @Nullable Annotation[] annotations) {
|
||||
List<Annotation> aggregateAnnotations = getAggregateAnnotations(annotations);
|
||||
return new Aggregate(aggregateIndex, source, aggregateAnnotations);
|
||||
}
|
||||
|
||||
private List<Annotation> getAggregateAnnotations(Annotation[] annotations) {
|
||||
private List<Annotation> getAggregateAnnotations(@Nullable Annotation[] annotations) {
|
||||
List<Annotation> result = new ArrayList<>(annotations.length);
|
||||
addAggregateAnnotations(result, annotations);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void addAggregateAnnotations(List<Annotation> aggregateAnnotations, Annotation[] annotations) {
|
||||
private void addAggregateAnnotations(List<Annotation> aggregateAnnotations, @Nullable Annotation[] annotations) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation != null && !annotationFilter.matches(annotation)) {
|
||||
Annotation[] repeatedAnnotations = repeatableContainers.findRepeatedAnnotations(annotation);
|
||||
@@ -482,7 +483,7 @@ final class TypeMappedAnnotations implements MergedAnnotations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Aggregate> finish(@Nullable List<Aggregate> processResult) {
|
||||
public @NonNull List<Aggregate> finish(@Nullable List<Aggregate> processResult) {
|
||||
return this.aggregates;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -584,11 +584,11 @@ public class SpringFactoriesLoader {
|
||||
* @param function the resolver function
|
||||
* @return a new {@link ArgumentResolver} instance backed by the function
|
||||
*/
|
||||
static ArgumentResolver from(Function<Class<?>, Object> function) {
|
||||
static ArgumentResolver from(Function<Class<?>, @Nullable Object> function) {
|
||||
return new ArgumentResolver() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T resolve(Class<T> type) {
|
||||
public <T> @Nullable T resolve(Class<T> type) {
|
||||
return (T) function.apply(type);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -87,7 +87,7 @@ public interface AnnotatedTypeMetadata {
|
||||
* as map key (for example, "location") and the attribute's value as map value; or
|
||||
* {@code null} if no matching annotation is found
|
||||
*/
|
||||
default @Nullable Map<String, Object> getAnnotationAttributes(String annotationName) {
|
||||
default @Nullable Map<String, @Nullable Object> getAnnotationAttributes(String annotationName) {
|
||||
return getAnnotationAttributes(annotationName, false);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public interface AnnotatedTypeMetadata {
|
||||
* as map key (for example, "location") and the attribute's value as map value; or
|
||||
* {@code null} if no matching annotation is found
|
||||
*/
|
||||
default @Nullable Map<String, Object> getAnnotationAttributes(String annotationName,
|
||||
default @Nullable Map<String, @Nullable Object> getAnnotationAttributes(String annotationName,
|
||||
boolean classValuesAsString) {
|
||||
|
||||
MergedAnnotation<Annotation> annotation = getAnnotations().get(annotationName,
|
||||
@@ -129,7 +129,7 @@ public interface AnnotatedTypeMetadata {
|
||||
* map value; or {@code null} if no matching annotation is found
|
||||
* @see #getAllAnnotationAttributes(String, boolean)
|
||||
*/
|
||||
default @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName) {
|
||||
default @Nullable MultiValueMap<String, @Nullable Object> getAllAnnotationAttributes(String annotationName) {
|
||||
return getAllAnnotationAttributes(annotationName, false);
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ public interface AnnotatedTypeMetadata {
|
||||
* map value; or {@code null} if no matching annotation is found
|
||||
* @see #getAllAnnotationAttributes(String)
|
||||
*/
|
||||
default @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(
|
||||
default @Nullable MultiValueMap<String, @Nullable Object> getAllAnnotationAttributes(
|
||||
String annotationName, boolean classValuesAsString) {
|
||||
|
||||
Adapt[] adaptations = Adapt.values(classValuesAsString, true);
|
||||
@@ -156,7 +156,7 @@ public interface AnnotatedTypeMetadata {
|
||||
.filter(MergedAnnotationPredicates.unique(MergedAnnotation::getMetaTypes))
|
||||
.map(MergedAnnotation::withNonMergedAttributes)
|
||||
.collect(MergedAnnotationCollectors.toMultiValueMap(
|
||||
map -> (map.isEmpty() ? null : map), adaptations));
|
||||
(MultiValueMap<String, @Nullable Object> map) -> (map.isEmpty() ? null : map), adaptations));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -105,7 +105,7 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
public @Nullable Map<String, @Nullable Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return AnnotationMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
@@ -114,7 +114,8 @@ public class StandardAnnotationMetadata extends StandardClassMetadata implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
@SuppressWarnings("NullAway") // Null-safety of Java super method not yet managed
|
||||
public @Nullable MultiValueMap<String, @Nullable Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return AnnotationMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -131,7 +131,7 @@ public class StandardMethodMetadata implements MethodMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
public @Nullable Map<String, @Nullable Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return MethodMetadata.super.getAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
@@ -140,7 +140,8 @@ public class StandardMethodMetadata implements MethodMetadata {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
@SuppressWarnings("NullAway") // Null-safety of Java super method not yet managed
|
||||
public @Nullable MultiValueMap<String, @Nullable Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString) {
|
||||
if (this.nestedAnnotationsAsMap) {
|
||||
return MethodMetadata.super.getAllAnnotationAttributes(annotationName, classValuesAsString);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -64,7 +64,7 @@ public abstract class CollectionUtils {
|
||||
* @return whether the given Collection is empty
|
||||
*/
|
||||
@Contract("null -> true")
|
||||
public static boolean isEmpty(@Nullable Collection<?> collection) {
|
||||
public static boolean isEmpty(@Nullable Collection<? extends @Nullable Object> collection) {
|
||||
return (collection == null || collection.isEmpty());
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public abstract class CollectionUtils {
|
||||
* @return whether the given Map is empty
|
||||
*/
|
||||
@Contract("null -> true")
|
||||
public static boolean isEmpty(@Nullable Map<?, ?> map) {
|
||||
public static boolean isEmpty(@Nullable Map<?, ? extends @Nullable Object> map) {
|
||||
return (map == null || map.isEmpty());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -20,6 +20,8 @@ import java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
|
||||
/**
|
||||
* Composite collection that combines two other collections. This type is only
|
||||
@@ -83,10 +85,10 @@ class CompositeCollection<E> implements Collection<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(T[] a) {
|
||||
@SuppressWarnings({"unchecked","NullAway"}) // Overridden method does not define nullness
|
||||
public <T> @Nullable T[] toArray(@Nullable T[] a) {
|
||||
int size = this.size();
|
||||
T[] result;
|
||||
@Nullable T[] result;
|
||||
if (a.length >= size) {
|
||||
result = a;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -456,7 +456,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
|
||||
* Array of references indexed using the low order bits from the hash.
|
||||
* This property should only be set along with {@code resizeThreshold}.
|
||||
*/
|
||||
private volatile Reference<K, V>[] references;
|
||||
private volatile @Nullable Reference<K, V>[] references;
|
||||
|
||||
/**
|
||||
* The total number of references contained in this segment. This includes chained
|
||||
@@ -485,7 +485,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
|
||||
return null;
|
||||
}
|
||||
// Use a local copy to protect against other threads writing
|
||||
Reference<K, V>[] references = this.references;
|
||||
@Nullable Reference<K, V>[] references = this.references;
|
||||
int index = getIndex(hash, references);
|
||||
Reference<K, V> head = references[index];
|
||||
return findInChain(head, key, hash);
|
||||
@@ -641,7 +641,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable Reference<K, V> findInChain(Reference<K, V> ref, @Nullable Object key, int hash) {
|
||||
private @Nullable Reference<K, V> findInChain(@Nullable Reference<K, V> ref, @Nullable Object key, int hash) {
|
||||
Reference<K, V> currRef = ref;
|
||||
while (currRef != null) {
|
||||
if (currRef.getHash() == hash) {
|
||||
@@ -663,7 +663,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
|
||||
return new Reference[size];
|
||||
}
|
||||
|
||||
private int getIndex(int hash, Reference<K, V>[] references) {
|
||||
private int getIndex(int hash, @Nullable Reference<K, V>[] references) {
|
||||
return (hash & (references.length - 1));
|
||||
}
|
||||
|
||||
@@ -879,7 +879,7 @@ public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V> implemen
|
||||
|
||||
private int referenceIndex;
|
||||
|
||||
private Reference<K, V> @Nullable [] references;
|
||||
private @Nullable Reference<K, V> @Nullable [] references;
|
||||
|
||||
private @Nullable Reference<K, V> reference;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -49,7 +49,7 @@ public class MethodInvoker {
|
||||
|
||||
private @Nullable String staticMethod;
|
||||
|
||||
private Object @Nullable [] arguments;
|
||||
private @Nullable Object @Nullable [] arguments;
|
||||
|
||||
/** The method we will call. */
|
||||
private @Nullable Method methodObject;
|
||||
@@ -127,14 +127,14 @@ public class MethodInvoker {
|
||||
* Set arguments for the method invocation. If this property is not set,
|
||||
* or the Object array is of length 0, a method with no arguments is assumed.
|
||||
*/
|
||||
public void setArguments(Object @Nullable ... arguments) {
|
||||
public void setArguments(@Nullable Object... arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the arguments for the method invocation.
|
||||
*/
|
||||
public Object[] getArguments() {
|
||||
public @Nullable Object[] getArguments() {
|
||||
return (this.arguments != null ? this.arguments : EMPTY_ARGUMENTS);
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ public class MethodInvoker {
|
||||
Assert.notNull(targetClass, "Either 'targetClass' or 'targetObject' is required");
|
||||
Assert.notNull(targetMethod, "Property 'targetMethod' is required");
|
||||
|
||||
Object[] arguments = getArguments();
|
||||
@Nullable Object[] arguments = getArguments();
|
||||
Class<?>[] argTypes = new Class<?>[arguments.length];
|
||||
for (int i = 0; i < arguments.length; ++i) {
|
||||
argTypes[i] = (arguments[i] != null ? arguments[i].getClass() : Object.class);
|
||||
@@ -206,7 +206,7 @@ public class MethodInvoker {
|
||||
*/
|
||||
protected @Nullable Method findMatchingMethod() {
|
||||
String targetMethod = getTargetMethod();
|
||||
Object[] arguments = getArguments();
|
||||
@Nullable Object[] arguments = getArguments();
|
||||
int argCount = arguments.length;
|
||||
|
||||
Class<?> targetClass = getTargetClass();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -29,7 +29,7 @@ import org.jspecify.annotations.Nullable;
|
||||
* @param <K> the key type
|
||||
* @param <V> the value element type
|
||||
*/
|
||||
public interface MultiValueMap<K, V> extends Map<K, List<V>> {
|
||||
public interface MultiValueMap<K, V extends @Nullable Object> extends Map<K, List<V>> {
|
||||
|
||||
/**
|
||||
* Return the first value for the given key.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -188,7 +188,7 @@ public abstract class ObjectUtils {
|
||||
* @param element the element to check for
|
||||
* @return whether the element has been found in the given array
|
||||
*/
|
||||
public static boolean containsElement(Object @Nullable [] array, Object element) {
|
||||
public static boolean containsElement(@Nullable Object @Nullable [] array, @Nullable Object element) {
|
||||
if (array == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -266,7 +266,7 @@ public abstract class ObjectUtils {
|
||||
* @return the new array (of the same component type; never {@code null})
|
||||
* @since 6.0
|
||||
*/
|
||||
public static <A, O extends A> A[] addObjectToArray(A @Nullable [] array, @Nullable O obj, int position) {
|
||||
public static <A, O extends A> @Nullable A[] addObjectToArray(A @Nullable [] array, @Nullable O obj, int position) {
|
||||
Class<?> componentType = Object.class;
|
||||
if (array != null) {
|
||||
componentType = array.getClass().componentType();
|
||||
@@ -276,7 +276,7 @@ public abstract class ObjectUtils {
|
||||
}
|
||||
int newArrayLength = (array != null ? array.length + 1 : 1);
|
||||
@SuppressWarnings("unchecked")
|
||||
A[] newArray = (A[]) Array.newInstance(componentType, newArrayLength);
|
||||
@Nullable A[] newArray = (A[]) Array.newInstance(componentType, newArrayLength);
|
||||
if (array != null) {
|
||||
System.arraycopy(array, 0, newArray, 0, position);
|
||||
System.arraycopy(array, position, newArray, position + 1, array.length - position);
|
||||
@@ -651,7 +651,7 @@ public abstract class ObjectUtils {
|
||||
* @param array the array to build a String representation for
|
||||
* @return a String representation of {@code array}
|
||||
*/
|
||||
public static String nullSafeToString(Object @Nullable [] array) {
|
||||
public static String nullSafeToString(@Nullable Object @Nullable [] array) {
|
||||
if (array == null) {
|
||||
return NULL_STRING;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -1038,12 +1038,12 @@ public abstract class StringUtils {
|
||||
* @param array the original {@code String} array (potentially empty)
|
||||
* @return the resulting array (of the same size) with trimmed elements
|
||||
*/
|
||||
public static String[] trimArrayElements(String[] array) {
|
||||
public static @Nullable String[] trimArrayElements(@Nullable String[] array) {
|
||||
if (ObjectUtils.isEmpty(array)) {
|
||||
return array;
|
||||
}
|
||||
|
||||
String[] result = new String[array.length];
|
||||
@Nullable String[] result = new String[array.length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
String element = array[i];
|
||||
result[i] = (element != null ? element.trim() : null);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -22,6 +22,7 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Contract;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -38,11 +39,11 @@ import org.springframework.util.Assert;
|
||||
* @since 5.1
|
||||
* @param <T> the type of results supplied by this supplier
|
||||
*/
|
||||
public class SingletonSupplier<T> implements Supplier<T> {
|
||||
public class SingletonSupplier<T> implements Supplier<@Nullable T> {
|
||||
|
||||
private final @Nullable Supplier<? extends T> instanceSupplier;
|
||||
private final @Nullable Supplier<? extends @Nullable T> instanceSupplier;
|
||||
|
||||
private final @Nullable Supplier<? extends T> defaultSupplier;
|
||||
private final @Nullable Supplier<? extends @Nullable T> defaultSupplier;
|
||||
|
||||
private volatile @Nullable T singletonInstance;
|
||||
|
||||
@@ -58,7 +59,7 @@ public class SingletonSupplier<T> implements Supplier<T> {
|
||||
* @param instance the singleton instance (potentially {@code null})
|
||||
* @param defaultSupplier the default supplier as a fallback
|
||||
*/
|
||||
public SingletonSupplier(@Nullable T instance, Supplier<? extends T> defaultSupplier) {
|
||||
public SingletonSupplier(@Nullable T instance, Supplier<? extends @Nullable T> defaultSupplier) {
|
||||
this.instanceSupplier = null;
|
||||
this.defaultSupplier = defaultSupplier;
|
||||
this.singletonInstance = instance;
|
||||
@@ -70,17 +71,17 @@ public class SingletonSupplier<T> implements Supplier<T> {
|
||||
* @param instanceSupplier the immediate instance supplier
|
||||
* @param defaultSupplier the default supplier as a fallback
|
||||
*/
|
||||
public SingletonSupplier(@Nullable Supplier<? extends T> instanceSupplier, Supplier<? extends T> defaultSupplier) {
|
||||
public SingletonSupplier(@Nullable Supplier<? extends @Nullable T> instanceSupplier, Supplier<? extends @Nullable T> defaultSupplier) {
|
||||
this.instanceSupplier = instanceSupplier;
|
||||
this.defaultSupplier = defaultSupplier;
|
||||
}
|
||||
|
||||
private SingletonSupplier(Supplier<? extends T> supplier) {
|
||||
private SingletonSupplier(Supplier<? extends @Nullable T> supplier) {
|
||||
this.instanceSupplier = supplier;
|
||||
this.defaultSupplier = null;
|
||||
}
|
||||
|
||||
private SingletonSupplier(T singletonInstance) {
|
||||
private SingletonSupplier(@Nullable T singletonInstance) {
|
||||
this.instanceSupplier = null;
|
||||
this.defaultSupplier = null;
|
||||
this.singletonInstance = singletonInstance;
|
||||
@@ -141,6 +142,7 @@ public class SingletonSupplier<T> implements Supplier<T> {
|
||||
* @param instance the singleton instance (potentially {@code null})
|
||||
* @return the singleton supplier, or {@code null} if the instance was {@code null}
|
||||
*/
|
||||
@Contract("null -> null; !null -> !null")
|
||||
public static <T> @Nullable SingletonSupplier<T> ofNullable(@Nullable T instance) {
|
||||
return (instance != null ? new SingletonSupplier<>(instance) : null);
|
||||
}
|
||||
@@ -159,7 +161,8 @@ public class SingletonSupplier<T> implements Supplier<T> {
|
||||
* @param supplier the instance supplier (potentially {@code null})
|
||||
* @return the singleton supplier, or {@code null} if the instance supplier was {@code null}
|
||||
*/
|
||||
public static <T> @Nullable SingletonSupplier<T> ofNullable(@Nullable Supplier<T> supplier) {
|
||||
@Contract("null -> null; !null -> !null")
|
||||
public static <T> @Nullable SingletonSupplier<T> ofNullable(@Nullable Supplier<? extends @Nullable T> supplier) {
|
||||
return (supplier != null ? new SingletonSupplier<>(supplier) : null);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -20,6 +20,8 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.lang.Contract;
|
||||
|
||||
/**
|
||||
* Convenience utilities for {@link java.util.function.Supplier} handling.
|
||||
*
|
||||
@@ -35,6 +37,7 @@ public abstract class SupplierUtils {
|
||||
* @param supplier the supplier to resolve
|
||||
* @return the supplier's result, or {@code null} if none
|
||||
*/
|
||||
@Contract("null -> null; !null -> !null")
|
||||
public static <T> @Nullable T resolve(@Nullable Supplier<T> supplier) {
|
||||
return (supplier != null ? supplier.get() : null);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
@@ -29,6 +29,7 @@ import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -469,13 +470,13 @@ class AnnotationsScannerTests {
|
||||
new AnnotationsProcessor<Object, String>() {
|
||||
|
||||
@Override
|
||||
public String doWithAggregate(Object context, int aggregateIndex) {
|
||||
public @NonNull String doWithAggregate(Object context, int aggregateIndex) {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String doWithAnnotations(Object context, int aggregateIndex,
|
||||
@Nullable Object source, Annotation[] annotations) {
|
||||
public @NonNull String doWithAnnotations(Object context, int aggregateIndex,
|
||||
@Nullable Object source, @Nullable Annotation @Nullable [] annotations) {
|
||||
throw new IllegalStateException("Should not call");
|
||||
}
|
||||
|
||||
@@ -501,13 +502,13 @@ class AnnotationsScannerTests {
|
||||
new AnnotationsProcessor<Object, String>() {
|
||||
|
||||
@Override
|
||||
public String doWithAnnotations(Object context, int aggregateIndex,
|
||||
@Nullable Object source, Annotation[] annotations) {
|
||||
public @NonNull String doWithAnnotations(Object context, int aggregateIndex,
|
||||
@Nullable Object source, @Nullable Annotation @Nullable [] annotations) {
|
||||
return "K";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String finish(@Nullable String result) {
|
||||
public @NonNull String finish(@Nullable String result) {
|
||||
return "O" + result;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user