Skip to content

Commit

Permalink
Perform NullAway build-time checks in more modules
Browse files Browse the repository at this point in the history
This commit enables null-safety build-time checks in
all remaining modules except spring-test.

See spring-projectsgh-32475
  • Loading branch information
sdeleuze committed Mar 26, 2024
1 parent 2fea3d7 commit 8b51b36
Show file tree
Hide file tree
Showing 53 changed files with 93 additions and 31 deletions.
7 changes: 3 additions & 4 deletions gradle/spring-module.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,11 @@ tasks.withType(JavaCompile).configureEach {
options.errorprone {
disableAllChecks = true
option("NullAway:CustomContractAnnotations", "org.springframework.lang.Contract")
option("NullAway:AnnotatedPackages", "org.springframework.core,org.springframework.expression," +
"org.springframework.web,org.springframework.jms,org.springframework.messaging,org.springframework.jdbc," +
"org.springframework.r2dbc,org.springframework.orm,org.springframework.beans,org.springframework.aop")
option("NullAway:AnnotatedPackages", "org.springframework")
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,org.springframework.aot.nativex.feature")
"org.springframework.javapoet,org.springframework.aot.nativex.substitution,org.springframework.aot.nativex.feature," +
"org.springframework.test,org.springframework.mock")
}
}
tasks.compileJava {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ protected void cacheException(@Nullable Cache exceptionCache, ExceptionTypeFilte
private Cache resolveExceptionCache(CacheOperationInvocationContext<CacheResultOperation> context) {
CacheResolver exceptionCacheResolver = context.getOperation().getExceptionCacheResolver();
if (exceptionCacheResolver != null) {
return extractFrom(context.getOperation().getExceptionCacheResolver().resolveCaches(context));
return extractFrom(exceptionCacheResolver.resolveCaches(context));
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ protected <T> T getBean(Class<T> type) {
}
}

@SuppressWarnings("NullAway")
protected CacheManager getDefaultCacheManager() {
if (getCacheManager() == null) {
Assert.state(this.beanFactory != null, "BeanFactory required for default CacheManager resolution");
Expand All @@ -207,6 +208,7 @@ protected CacheManager getDefaultCacheManager() {
}

@Override
@SuppressWarnings("NullAway")
protected CacheResolver getDefaultCacheResolver() {
if (getCacheResolver() == null) {
this.cacheResolver = SingletonSupplier.of(new SimpleCacheResolver(getDefaultCacheManager()));
Expand All @@ -215,6 +217,7 @@ protected CacheResolver getDefaultCacheResolver() {
}

@Override
@SuppressWarnings("NullAway")
protected CacheResolver getDefaultExceptionCacheResolver() {
if (getExceptionCacheResolver() == null) {
this.exceptionCacheResolver = SingletonSupplier.of(new LazyCacheResolver());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public class LocalDataSourceJobStore extends JobStoreCMT {


@Override
@SuppressWarnings("NullAway")
public void initialize(ClassLoadHelper loadHelper, SchedulerSignaler signaler) throws SchedulerConfigException {
// Absolutely needs thread-bound DataSource to initialize.
this.dataSource = SchedulerFactoryBean.getConfigTimeDataSource();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ public void setResourceLoader(ResourceLoader resourceLoader) {
/**
* Register jobs and triggers (within a transaction, if possible).
*/
@SuppressWarnings("NullAway")
protected void registerJobsAndTriggers() throws SchedulerException {
TransactionStatus transactionStatus = null;
if (this.transactionManager != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -661,6 +661,7 @@ private Scheduler prepareScheduler(SchedulerFactory schedulerFactory) throws Sch
* @see #afterPropertiesSet
* @see org.quartz.SchedulerFactory#getScheduler
*/
@SuppressWarnings("NullAway")
protected Scheduler createScheduler(SchedulerFactory schedulerFactory, @Nullable String schedulerName)
throws SchedulerException {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ final class BeanMethod extends ConfigurationMethod {


@Override
@SuppressWarnings("NullAway")
public void validate(ProblemReporter problemReporter) {
if ("void".equals(getMetadata().getReturnTypeName())) {
// declared as void: potential misuse of @Bean, maybe meant as init method instead?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.springframework.core.type.filter.RegexPatternTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;
Expand Down Expand Up @@ -112,14 +113,18 @@ protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserCo
parseBeanNameGenerator(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
String message = ex.getMessage();
Assert.state(message != null, "Exception message must not be null");
parserContext.getReaderContext().error(message, parserContext.extractSource(element), ex.getCause());
}

try {
parseScope(element, scanner);
}
catch (Exception ex) {
parserContext.getReaderContext().error(ex.getMessage(), parserContext.extractSource(element), ex.getCause());
String message = ex.getMessage();
Assert.state(message != null, "Exception message must not be null");
parserContext.getReaderContext().error(message, parserContext.extractSource(element), ex.getCause());
}

parseTypeFilters(element, scanner, parserContext);
Expand Down Expand Up @@ -214,8 +219,10 @@ else if (EXCLUDE_FILTER_ELEMENT.equals(localName)) {
"Ignoring non-present type filter class: " + ex, parserContext.extractSource(element));
}
catch (Exception ex) {
String message = ex.getMessage();
Assert.state(message != null, "Exception message must not be null");
parserContext.getReaderContext().error(
ex.getMessage(), parserContext.extractSource(element), ex.getCause());
message, parserContext.extractSource(element), ex.getCause());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> getImportBeanDefinitionRe
return this.importBeanDefinitionRegistrars;
}

@SuppressWarnings("NullAway")
void validate(ProblemReporter problemReporter) {
Map<String, Object> attributes = this.metadata.getAnnotationAttributes(Configuration.class.getName());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ void register(DeferredImportSelectorHolder deferredImport) {
deferredImport.getConfigurationClass());
}

@SuppressWarnings("NullAway")
void processGroupImports() {
for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
Predicate<String> filter = grouping.getCandidateFilter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ public BeanRegistrationAotContribution processAheadOfTime(RegisteredBean registe

@Override
@Nullable
@SuppressWarnings("NullAway")
public BeanFactoryInitializationAotContribution processAheadOfTime(ConfigurableListableBeanFactory beanFactory) {
boolean hasPropertySourceDescriptors = !CollectionUtils.isEmpty(this.propertySourceDescriptors);
boolean hasImportRegistry = beanFactory.containsBean(IMPORT_REGISTRY_BEAN_NAME);
Expand Down Expand Up @@ -556,6 +557,7 @@ public ImportAwareBeanPostProcessor(BeanFactory beanFactory) {
}

@Override
@Nullable
public PropertyValues postProcessProperties(@Nullable PropertyValues pvs, Object bean, String beanName) {
// Inject the BeanFactory before AutowiredAnnotationBeanPostProcessor's
// postProcessProperties method attempts to autowire other configuration beans.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public Class<?> getTargetClass() {
return descriptor.getDependencyType();
}
@Override
@SuppressWarnings("NullAway")
public Object getTarget() {
Set<String> autowiredBeanNames = (beanName != null ? new LinkedHashSet<>(1) : null);
Object target = dlbf.doResolveDependency(descriptor, beanName, autowiredBeanNames, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
class ProfileCondition implements Condition {

@Override
@SuppressWarnings("NullAway")
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

/**
Expand Down Expand Up @@ -229,6 +230,7 @@ protected Collection<ApplicationListener<?>> getApplicationListeners(
* @param retriever the ListenerRetriever, if supposed to populate one (for caching purposes)
* @return the pre-filtered list of application listeners for the given event and source type
*/
@SuppressWarnings("NullAway")
private Collection<ApplicationListener<?>> retrieveApplicationListeners(
ResolvableType eventType, @Nullable Class<?> sourceType, @Nullable CachedListenerRetriever retriever) {

Expand Down Expand Up @@ -313,7 +315,7 @@ private Collection<ApplicationListener<?>> retrieveApplicationListeners(

AnnotationAwareOrderComparator.sort(allListeners);
if (retriever != null) {
if (filteredListenerBeans.isEmpty()) {
if (CollectionUtils.isEmpty(filteredListenerBeans)) {
retriever.applicationListeners = new LinkedHashSet<>(allListeners);
retriever.applicationListenerBeans = filteredListenerBeans;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,7 @@ private void assertTargetBean(Method method, Object targetBean, @Nullable Object
}
}

@SuppressWarnings("NullAway")
private String getInvocationErrorMessage(Object bean, @Nullable String message, @Nullable Object[] resolvedArgs) {
StringBuilder sb = new StringBuilder(getDetailedErrorMessage(bean, message));
sb.append("Resolved arguments: \n");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
@Override
public void afterSingletonsInstantiated() {
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
Assert.state(beanFactory != null, "No ConfigurableListableBeanFactory set");
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import io.micrometer.context.ThreadLocalAccessor;

import org.springframework.lang.Nullable;

/**
* Adapt {@link LocaleContextHolder} to the {@link ThreadLocalAccessor} contract
* to assist the Micrometer Context Propagation library with {@link LocaleContext}
Expand All @@ -40,6 +42,7 @@ public Object key() {
}

@Override
@Nullable
public LocaleContext getValue() {
return LocaleContextHolder.getLocaleContext();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
* @see org.springframework.format.FormatterRegistrar#registerFormatters
* @see org.springframework.format.datetime.DateFormatterRegistrar
*/
@SuppressWarnings("NullAway")
public class DateTimeFormatterRegistrar implements FormatterRegistrar {

private enum Type {DATE, TIME, DATE_TIME}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,7 @@ private void registerNotificationListeners() throws MBeanExportException {
* Unregister the configured {@link NotificationListener NotificationListeners}
* from the {@link MBeanServer}.
*/
@SuppressWarnings("NullAway")
private void unregisterNotificationListeners() {
if (this.server != null) {
this.registeredNotificationListeners.forEach((bean, mappedObjectNames) -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.springframework.jmx.export.metadata.InvalidMetadataException;
import org.springframework.jmx.export.metadata.JmxAttributeSource;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;
import org.springframework.util.StringValueResolver;

/**
Expand Down Expand Up @@ -117,7 +118,7 @@ public org.springframework.jmx.export.metadata.ManagedAttribute getManagedAttrib
pvs.removePropertyValue("defaultValue");
PropertyAccessorFactory.forBeanPropertyAccess(bean).setPropertyValues(pvs);
String defaultValue = (String) map.get("defaultValue");
if (!defaultValue.isEmpty()) {
if (StringUtils.hasLength(defaultValue)) {
bean.setDefaultValue(defaultValue);
}
return bean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,8 @@ public void setValidator(@Nullable Validator validator) {
}
}

private void assertValidators(Validator... validators) {
@SuppressWarnings("NullAway")
private void assertValidators(@Nullable Validator... validators) {
Object target = getTarget();
for (Validator validator : validators) {
if (validator != null && (target != null && !validator.supports(target.getClass()))) {
Expand Down Expand Up @@ -741,6 +742,7 @@ public List<Validator> getValidators() {
* {@link #setExcludedValidators(Predicate) exclude predicate}.
* @since 6.1
*/
@SuppressWarnings("NullAway")
public List<Validator> getValidatorsToApply() {
return (this.excludedValidators != null ?
this.validators.stream().filter(validator -> !this.excludedValidators.test(validator)).toList() :
Expand Down Expand Up @@ -1168,6 +1170,7 @@ protected boolean isAllowed(String field) {
* @see #getBindingErrorProcessor
* @see BindingErrorProcessor#processMissingFieldError
*/
@SuppressWarnings("NullAway")
protected void checkRequiredFields(MutablePropertyValues mpvs) {
String[] requiredFields = getRequiredFields();
if (!ObjectUtils.isEmpty(requiredFields)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ public String format(String errorCode, @Nullable String objectName, @Nullable St
* {@link DefaultMessageCodesResolver#CODE_SEPARATOR}, skipping zero-length or
* null elements altogether.
*/
public static String toDelimitedString(String... elements) {
@SuppressWarnings("NullAway")
public static String toDelimitedString(@Nullable String... elements) {
StringJoiner rtn = new StringJoiner(CODE_SEPARATOR);
for (String element : elements) {
if (StringUtils.hasLength(element)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ public boolean equals(@Nullable Object other) {
if (!super.equals(other)) {
return false;
}
FieldError otherError = (FieldError) other;
return (getField().equals(otherError.getField()) &&
return (other instanceof FieldError otherError && getField().equals(otherError.getField()) &&
ObjectUtils.nullSafeEquals(getRejectedValue(), otherError.getRejectedValue()) &&
isBindingFailure() == otherError.isBindingFailure());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ public boolean equals(@Nullable Object other) {
if (!super.equals(other)) {
return false;
}
ParameterValidationResult otherResult = (ParameterValidationResult) other;
return (getMethodParameter().equals(otherResult.getMethodParameter()) &&
return (other instanceof ParameterValidationResult otherResult &&
getMethodParameter().equals(otherResult.getMethodParameter()) &&
ObjectUtils.nullSafeEquals(getArgument(), otherResult.getArgument()) &&
ObjectUtils.nullSafeEquals(getContainerIndex(), otherResult.getContainerIndex()) &&
ObjectUtils.nullSafeEquals(getContainerKey(), otherResult.getContainerKey()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public class BindingReflectionHintsRegistrar {
* @param hints the hints instance to use
* @param types the types to register
*/
@SuppressWarnings("NullAway")
public void registerReflectionHints(ReflectionHints hints, @Nullable Type... types) {
Set<Type> seen = new HashSet<>();
for (Type type : types) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public static Publisher<?> invokeSuspendingFunction(Method method, Object target
* @throws IllegalArgumentException if {@code method} is not a suspending function
* @since 6.0
*/
@SuppressWarnings({"deprecation", "DataFlowIssue"})
@SuppressWarnings({"deprecation", "DataFlowIssue", "NullAway"})
public static Publisher<?> invokeSuspendingFunction(
CoroutineContext context, Method method, @Nullable Object target, @Nullable Object... args) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ static class PartResolutionContext implements PlaceholderResolver {
}

@Override
@Nullable
public String resolvePlaceholder(String placeholderName) {
String value = this.resolver.resolvePlaceholder(placeholderName);
if (value != null && logger.isTraceEnabled()) {
Expand Down Expand Up @@ -358,6 +359,7 @@ public void flagPlaceholderAsVisited(String placeholder) {
}

public void removePlaceholder(String placeholder) {
Assert.state(this.visitedPlaceholders != null, "Visited placeholders must not be null");
this.visitedPlaceholders.remove(placeholder);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.io.OutputStream;
import java.nio.charset.Charset;

import org.springframework.lang.Contract;
import org.springframework.lang.Nullable;

/**
Expand Down Expand Up @@ -201,6 +202,7 @@ else if (bytesRead <= bytesToCopy) {
* @throws IOException in case of I/O errors
* @since 4.3
*/
@Contract("null -> fail")
public static int drain(@Nullable InputStream in) throws IOException {
Assert.notNull(in, "No InputStream specified");
return (int) in.transferTo(OutputStream.nullOutputStream());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ public <S extends Session> S getSession(Class<S> sessionType) {
* for the given connection, or {@code null} if none.
*/
@Nullable
@SuppressWarnings("NullAway")
public <S extends Session> S getSession(Class<S> sessionType, @Nullable Connection connection) {
Deque<Session> sessions =
(connection != null ? this.sessionsPerConnection.get(connection) : this.sessions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ protected MessageConsumer createListenerConsumer(final Session session) throws J
* @see #executeListener
* @see #setExposeListenerSession
*/
@SuppressWarnings("NullAway")
protected void processMessage(Message message, Session session) {
ConnectionFactory connectionFactory = getConnectionFactory();
boolean exposeResource = (connectionFactory != null && isExposeListenerSession());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ private static MethodParameter[] initMethodParameters(Method method) {
}

@Nullable
@SuppressWarnings("NullAway")
private static String initRoute(
Method method, Class<?> containingClass, RSocketStrategies strategies,
@Nullable StringValueResolver embeddedValueResolver) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ private void contributeHibernateHints(RuntimeHints hints, @Nullable ClassLoader
});
}

@SuppressWarnings("NullAway")
private void registerInstantiatorForReflection(ReflectionHints reflection, @Nullable Annotation annotation) {
if (annotation == null) {
return;
Expand Down

0 comments on commit 8b51b36

Please sign in to comment.