Skip to content

Commit b358656

Browse files
committed
Add support for AnnotatedType in MethodParameter.hasNullableAnnotation
This commit adds support for detecting annotated types. See gh-28797
1 parent 61545fa commit b358656

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

spring-core/src/main/java/org/springframework/core/MethodParameter.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.AnnotatedElement;
21+
import java.lang.reflect.AnnotatedType;
2122
import java.lang.reflect.Constructor;
2223
import java.lang.reflect.Executable;
2324
import java.lang.reflect.Field;
@@ -388,8 +389,8 @@ private MethodParameter nested(int nestingLevel, @Nullable Integer typeIndex) {
388389
/**
389390
* Return whether this method indicates a parameter which is not required:
390391
* either in the form of Java 8's {@link java.util.Optional}, any variant
391-
* of a parameter-level {@code Nullable} annotation (such as from JSR-305
392-
* or the FindBugs set of annotations), or a language-level nullable type
392+
* of a parameter-level {@code Nullable} annotation (such as from JSpecify,
393+
* JSR-305 or Jakarta set of annotations), or a language-level nullable type
393394
* declaration or {@code Continuation} parameter in Kotlin.
394395
* @since 4.3
395396
*/
@@ -402,15 +403,22 @@ public boolean isOptional() {
402403

403404
/**
404405
* Check whether this method parameter is annotated with any variant of a
405-
* {@code Nullable} annotation, for example, {@code jakarta.annotation.Nullable} or
406-
* {@code edu.umd.cs.findbugs.annotations.Nullable}.
406+
* {@code Nullable} annotation, for example, {@code org.springframework.lang.Nullable},
407+
* {@code org.jspecify.annotations.Nullable} or {@code jakarta.annotation.Nullable}.
407408
*/
408409
private boolean hasNullableAnnotation() {
409410
for (Annotation ann : getParameterAnnotations()) {
410411
if ("Nullable".equals(ann.annotationType().getSimpleName())) {
411412
return true;
412413
}
413414
}
415+
for (AnnotatedType annotatedType : this.executable.getAnnotatedParameterTypes()) {
416+
for (Annotation ann : annotatedType.getAnnotations()) {
417+
if ("Nullable".equals(ann.annotationType().getSimpleName())) {
418+
return true;
419+
}
420+
}
421+
}
414422
return false;
415423
}
416424

spring-core/src/test/java/org/springframework/core/MethodParameterTests.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,21 @@ class MethodParameterTests {
4949

5050
private MethodParameter intReturnType;
5151

52+
private MethodParameter jspecifyNullableParameter;
53+
54+
private MethodParameter springNullableParameter;
55+
5256

5357
@BeforeEach
5458
void setup() throws NoSuchMethodException {
5559
method = getClass().getMethod("method", String.class, long.class);
5660
stringParameter = new MethodParameter(method, 0);
5761
longParameter = new MethodParameter(method, 1);
5862
intReturnType = new MethodParameter(method, -1);
63+
Method jspecifyNullableMethod = getClass().getMethod("jspecifyNullableMethod", String.class);
64+
jspecifyNullableParameter = new MethodParameter(jspecifyNullableMethod, 0);
65+
Method springNullableMethod = getClass().getMethod("springNullableMethod", String.class);
66+
springNullableParameter = new MethodParameter(springNullableMethod, 0);
5967
}
6068

6169

@@ -238,21 +246,29 @@ void nestedWithTypeIndexReturnsNewInstance() throws Exception {
238246
}
239247

240248
@Test
241-
void nullableWithSpringAnnotation() {
242-
MethodParameter m = MethodParameter.forExecutable(method, 1);
243-
assertThat(m.isOptional()).isTrue();
249+
void jspecifyNullableParameter() {
250+
assertThat(jspecifyNullableParameter.isOptional()).isTrue();
244251
}
245252

246253
@Test
247-
void nullableWithJSpecifyAnnotation() {
248-
MethodParameter m = MethodParameter.forExecutable(method, 0);
249-
assertThat(m.isOptional()).isTrue();
254+
void springNullableParameter() {
255+
assertThat(springNullableParameter.isOptional()).isTrue();
250256
}
251257

252-
public int method(@org.jspecify.annotations.Nullable String p1, @org.springframework.lang.Nullable long p2) {
258+
public int method(String p1, long p2) {
253259
return 42;
254260
}
255261

262+
public @org.jspecify.annotations.Nullable String jspecifyNullableMethod(@org.jspecify.annotations.Nullable String parameter) {
263+
return parameter;
264+
}
265+
266+
@SuppressWarnings("deprecation")
267+
@org.springframework.lang.Nullable
268+
public String springNullableMethod(@org.springframework.lang.Nullable String parameter) {
269+
return parameter;
270+
}
271+
256272
@SuppressWarnings("unused")
257273
private static class NestedClass {
258274

0 commit comments

Comments
 (0)