Specify generic type nullness in spring-core

Also in spring-core-test.

See gh-34140
This commit is contained in:
Sébastien Deleuze
2025-01-13 20:52:00 +01:00
parent 435cb0c7d6
commit 9d9383aaeb
31 changed files with 160 additions and 134 deletions

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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()) &&

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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--;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}
};

View File

@@ -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));
}
/**

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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());
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
}