Perform NullAway build-time checks in spring-web

Also in spring-websocket.

See gh-32475
This commit is contained in:
Sébastien Deleuze 2024-03-25 11:10:30 +01:00
parent 2b1eb488fc
commit e52ee01ec8
17 changed files with 27 additions and 3 deletions

View File

@ -118,7 +118,7 @@ tasks.withType(JavaCompile).configureEach {
disableAllChecks = true
option("NullAway:CustomContractAnnotations", "org.springframework.lang.Contract")
option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression," +
"org.springframework.web.reactive,org.springframework.web.servlet")
"org.springframework.web")
option("NullAway:UnannotatedSubPackages", "org.springframework.instrument,org.springframework.context.index," +
"org.springframework.asm,org.springframework.cglib,org.springframework.objenesis," +
"org.springframework.javapoet,org.springframework.aot.nativex.substitution")

View File

@ -62,6 +62,7 @@ public abstract class CollectionUtils {
* @param collection the Collection to check
* @return whether the given Collection is empty
*/
@Contract("null -> true")
public static boolean isEmpty(@Nullable Collection<?> collection) {
return (collection == null || collection.isEmpty());
}

View File

@ -101,6 +101,7 @@ public abstract class ObjectUtils {
* either an Object array or a primitive array.
* @param obj the object to check
*/
@Contract("null -> false")
public static boolean isArray(@Nullable Object obj) {
return (obj != null && obj.getClass().isArray());
}

View File

@ -201,6 +201,7 @@ public class DefaultResponseErrorHandler implements ResponseErrorHandler {
* {@link RestClientResponseException#setBodyConvertFunction(Function)}.
* @since 6.0
*/
@SuppressWarnings("NullAway")
protected Function<ResolvableType, ?> initBodyConvertFunction(ClientHttpResponse response, byte[] body) {
Assert.state(!CollectionUtils.isEmpty(this.messageConverters), "Expected message converters");
return resolvableType -> {

View File

@ -522,6 +522,7 @@ final class DefaultRestClient implements RestClient {
}
}
@SuppressWarnings("NullAway")
private ClientHttpRequest createRequest(URI uri) throws IOException {
ClientHttpRequestFactory factory;
if (DefaultRestClient.this.interceptors != null) {

View File

@ -18,6 +18,8 @@ package org.springframework.web.context.request;
import io.micrometer.context.ThreadLocalAccessor;
import org.springframework.lang.Nullable;
/**
* Adapt {@link RequestContextHolder} to the {@link ThreadLocalAccessor} contract
* to assist the Micrometer Context Propagation library with
@ -40,6 +42,7 @@ public class RequestAttributesThreadLocalAccessor implements ThreadLocalAccessor
}
@Override
@Nullable
public RequestAttributes getValue() {
return RequestContextHolder.getRequestAttributes();
}

View File

@ -84,6 +84,7 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements
* @param previousRequest the existing request from the last dispatch
* @since 5.3.33
*/
@SuppressWarnings("NullAway")
StandardServletAsyncWebRequest(HttpServletRequest request, HttpServletResponse response,
@Nullable StandardServletAsyncWebRequest previousRequest) {
@ -243,6 +244,7 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements
}
@Override
@SuppressWarnings("NullAway")
public ServletOutputStream getOutputStream() throws IOException {
int level = obtainLockAndCheckState();
try {
@ -262,6 +264,7 @@ public class StandardServletAsyncWebRequest extends ServletWebRequest implements
}
@Override
@SuppressWarnings("NullAway")
public PrintWriter getWriter() throws IOException {
int level = obtainLockAndCheckState();
try {

View File

@ -287,6 +287,7 @@ public final class WebAsyncManager {
* via {@link #getConcurrentResultContext()}
* @throws Exception if concurrent processing failed to start
*/
@SuppressWarnings("NullAway")
public void startCallableProcessing(final WebAsyncTask<?> webAsyncTask, Object... processingContext)
throws Exception {
@ -408,6 +409,7 @@ public final class WebAsyncManager {
* @see #getConcurrentResult()
* @see #getConcurrentResultContext()
*/
@SuppressWarnings("NullAway")
public void startDeferredResultProcessing(
final DeferredResult<?> deferredResult, Object... processingContext) throws Exception {

View File

@ -104,6 +104,7 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP
* @see ServletContextResource
* @see jakarta.servlet.ServletContext#getResourcePaths
*/
@SuppressWarnings("NullAway")
protected void doRetrieveMatchingServletContextResources(
ServletContext servletContext, String fullPattern, String dir, Set<Resource> result)
throws IOException {

View File

@ -171,6 +171,7 @@ public class CorsConfiguration {
/**
* Variant of {@link #setAllowedOrigins} for adding one origin at a time.
*/
@SuppressWarnings("NullAway")
public void addAllowedOrigin(@Nullable String origin) {
if (origin == null) {
return;
@ -244,6 +245,7 @@ public class CorsConfiguration {
* Variant of {@link #setAllowedOriginPatterns} for adding one origin at a time.
* @since 5.3
*/
@SuppressWarnings("NullAway")
public void addAllowedOriginPattern(@Nullable String originPattern) {
if (originPattern == null) {
return;

View File

@ -342,7 +342,7 @@ public class HandlerMethod extends AnnotatedMethod {
@Override
public boolean equals(@Nullable Object other) {
return (this == other || (super.equals(other) && this.bean.equals(((HandlerMethod) other).bean)));
return (this == other || (super.equals(other) && other instanceof HandlerMethod otherMethod && this.bean.equals(otherMethod.bean)));
}
@Override

View File

@ -136,6 +136,7 @@ public abstract class AbstractMultipartHttpServletRequest extends HttpServletReq
* lazily initializing it if necessary.
* @see #initializeMultipart()
*/
@SuppressWarnings("NullAway")
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
if (this.multipartFiles == null) {
initializeMultipart();

View File

@ -137,6 +137,7 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
}
@Override
@SuppressWarnings("NullAway")
public Enumeration<String> getParameterNames() {
if (this.multipartParameterNames == null) {
initializeMultipart();
@ -157,6 +158,7 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe
}
@Override
@SuppressWarnings("NullAway")
public Map<String, String[]> getParameterMap() {
if (this.multipartParameterNames == null) {
initializeMultipart();

View File

@ -152,6 +152,7 @@ public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHa
/**
* Return the configured {@link ServerCodecConfigurer}.
*/
@SuppressWarnings("NullAway")
public ServerCodecConfigurer getCodecConfigurer() {
if (this.codecConfigurer == null) {
setCodecConfigurer(ServerCodecConfigurer.create());

View File

@ -189,6 +189,7 @@ public class InMemoryWebSessionStore implements WebSessionStore {
}
@Override
@SuppressWarnings("NullAway")
public String getId() {
return this.id.get();
}
@ -224,6 +225,7 @@ public class InMemoryWebSessionStore implements WebSessionStore {
}
@Override
@SuppressWarnings("NullAway")
public boolean isStarted() {
return this.state.get().equals(State.STARTED) || !getAttributes().isEmpty();
}
@ -252,6 +254,7 @@ public class InMemoryWebSessionStore implements WebSessionStore {
}
@Override
@SuppressWarnings("NullAway")
public Mono<Void> save() {
checkMaxSessionsLimit();
@ -289,6 +292,7 @@ public class InMemoryWebSessionStore implements WebSessionStore {
return isExpired(clock.instant());
}
@SuppressWarnings("NullAway")
private boolean isExpired(Instant now) {
if (this.state.get().equals(State.EXPIRED)) {
return true;

View File

@ -223,6 +223,7 @@ final class HttpServiceMethod {
}
@Nullable
@SuppressWarnings("NullAway")
private static String initUrl(
@Nullable HttpExchange typeAnnotation, HttpExchange methodAnnotation,
@Nullable StringValueResolver embeddedValueResolver) {

View File

@ -251,7 +251,7 @@ public final class HttpServiceProxyFactory {
this.exchangeAdapter, initArgumentResolvers(), this.embeddedValueResolver);
}
@SuppressWarnings("DataFlowIssue")
@SuppressWarnings({"DataFlowIssue", "NullAway"})
private List<HttpServiceArgumentResolver> initArgumentResolvers() {
// Custom