Switch to JSpecify annotations
This commit updates the whole Spring Framework codebase to use JSpecify annotations instead of Spring null-safety annotations with JSR 305 semantics. JSpecify provides signficant enhancements such as properly defined specifications, a canonical dependency with no split-package issue, better tooling, better Kotlin integration and the capability to specify generic type, array and varargs element null-safety. Generic type null-safety is not defined by this commit yet and will be specified later. A key difference is that Spring null-safety annotations, following JSR 305 semantics, apply to fields, parameters and return values, while JSpecify annotations apply to type usages. That's why this commit moves nullability annotations closer to the type for fields and return values. See gh-28797
This commit is contained in:
@@ -18,6 +18,7 @@ package org.springframework.expression.spel;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.expression.EvaluationException;
|
||||
@@ -27,7 +28,6 @@ import org.springframework.expression.TypeComparator;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeComparator;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
|
||||
@@ -18,11 +18,12 @@ package org.springframework.expression.spel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.expression.AccessException;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.TypedValue;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.NullNode;
|
||||
import com.fasterxml.jackson.databind.node.TextNode;
|
||||
import example.Color;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@@ -51,7 +52,6 @@ import org.springframework.expression.spel.support.ReflectiveIndexAccessor;
|
||||
import org.springframework.expression.spel.support.SimpleEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.testresources.Person;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.stream.Stream;
|
||||
|
||||
import example.Color;
|
||||
import example.FruitMap;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
@@ -60,7 +61,6 @@ import org.springframework.expression.spel.support.ReflectiveIndexAccessor;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.testdata.PersonInOtherPackage;
|
||||
import org.springframework.expression.spel.testresources.Person;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
@@ -61,7 +62,6 @@ import org.springframework.expression.spel.support.ReflectivePropertyAccessor;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeLocator;
|
||||
import org.springframework.expression.spel.testresources.le.div.mod.reserved.Reserver;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -1169,7 +1169,6 @@ class SpelReproTests extends AbstractExpressionTests {
|
||||
TypedValue value = accessor.read(context, target, "property");
|
||||
assertThat(value.getValue()).isEqualTo(1);
|
||||
assertThat(value.getTypeDescriptor().getType()).isEqualTo(Integer.class);
|
||||
assertThat(value.getTypeDescriptor().getAnnotations()).isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -2158,8 +2157,7 @@ class SpelReproTests extends AbstractExpressionTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Integer getProperty() {
|
||||
public @Nullable Integer getProperty() {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ package org.springframework.expression.spel.ast;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.expression.TargetedAccessor;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -102,8 +102,7 @@ class AccessorUtilsTests {
|
||||
private record DemoAccessor(String name, Class<?>[] types) implements TargetedAccessor {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Class<?>[] getSpecificTargetClasses() {
|
||||
public Class<?> @Nullable [] getSpecificTargetClasses() {
|
||||
return this.types;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.expression.spel.testresources;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class PlaceOfBirth {
|
||||
|
||||
|
||||
@@ -40,9 +40,9 @@ class SpelReproKotlinTests {
|
||||
val expr = parser.parseExpression("#key.startsWith('hello')")
|
||||
context.registerFunction("get", Config::class.java.getMethod("get", String::class.java))
|
||||
context.setVariable("key", "hello world")
|
||||
assertThat(expr.getValue(context, Boolean::class.java)).isTrue()
|
||||
assertThat(expr.getValue(context, Boolean::class.java)!!).isTrue()
|
||||
context.setVariable("key", "")
|
||||
assertThat(expr.getValue(context, Boolean::class.java)).isFalse()
|
||||
assertThat(expr.getValue(context, Boolean::class.java)!!).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -50,23 +50,23 @@ class SpelReproKotlinTests {
|
||||
val expr = parser.parseExpression("#key.startsWith('hello')")
|
||||
context.registerFunction("suspendingGet", Config::class.java.getMethod("suspendingGet", String::class.java, Continuation::class.java))
|
||||
context.setVariable("key", "hello world")
|
||||
assertThat(expr.getValue(context, Boolean::class.java)).isTrue()
|
||||
assertThat(expr.getValue(context, Boolean::class.java)!!).isTrue()
|
||||
context.setVariable("key", "")
|
||||
assertThat(expr.getValue(context, Boolean::class.java)).isFalse()
|
||||
assertThat(expr.getValue(context, Boolean::class.java)!!).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `gh-30468 Unmangle Kotlin inlined class getter`() {
|
||||
context.setVariable("something", Something(UUID(123), "name"))
|
||||
val expr = parser.parseExpression("#something.id")
|
||||
assertThat(expr.getValue(context, Int::class.java)).isEqualTo(123)
|
||||
assertThat(expr.getValue(context, Int::class.java)!!).isEqualTo(123)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `gh-30468 Unmangle Kotlin inlined class setter`() {
|
||||
context.setVariable("something", Something(UUID(123), "name"))
|
||||
val expr = parser.parseExpression("#something.id = 456")
|
||||
assertThat(expr.getValue(context, Int::class.java)).isEqualTo(456)
|
||||
assertThat(expr.getValue(context, Int::class.java)!!).isEqualTo(456)
|
||||
}
|
||||
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
|
||||
Reference in New Issue
Block a user