Skip to content

Commit 791778e

Browse files
committed
Fix JSpecify annotations
1 parent 0fdb017 commit 791778e

File tree

7 files changed

+54
-41
lines changed

7 files changed

+54
-41
lines changed

junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ public DefaultArgumentConverter(ExtensionContext context) {
8888
}
8989

9090
@Override
91-
public final @Nullable Object convert(@NullableObject source, FieldContext context) throws ArgumentConversionException {
91+
public final @Nullable Object convert(@Nullable Object source, FieldContext context)
92+
throws ArgumentConversionException {
9293
ClassLoader classLoader = getClassLoader(context.getField().getDeclaringClass());
9394
return convert(source, TypeDescriptor.forField(context.getField()), classLoader);
9495
}

junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ private ConversionSupport() {
5454
*/
5555
@Deprecated
5656
@API(status = DEPRECATED, since = "5.13")
57-
public static <T> T convert(String source, Class<T> targetType, ClassLoader classLoader) {
57+
public static <T> @Nullable T convert(@Nullable String source, Class<T> targetType, ClassLoader classLoader) {
5858
return convert(source, TypeDescriptor.forClass(targetType), getClassLoader(classLoader));
5959
}
6060

@@ -76,7 +76,8 @@ public static <T> T convert(String source, Class<T> targetType, ClassLoader clas
7676
*/
7777
@API(status = EXPERIMENTAL, since = "1.13")
7878
@SuppressWarnings("unchecked")
79-
public static <T> @Nullable T convert(@Nullable Object source, TypeDescriptor targetType, @Nullable ClassLoader classLoader) {
79+
public static <T> @Nullable T convert(@Nullable Object source, TypeDescriptor targetType,
80+
@Nullable ClassLoader classLoader) {
8081
TypeDescriptor sourceType = TypeDescriptor.forInstance(source);
8182
ClassLoader classLoaderToUse = getClassLoader(classLoader);
8283
ServiceLoader<Converter> serviceLoader = ServiceLoader.load(Converter.class, classLoaderToUse);
@@ -87,12 +88,12 @@ public static <T> T convert(String source, Class<T> targetType, ClassLoader clas
8788
.filter(candidate -> candidate.canConvert(source, sourceType, targetType)) //
8889
.findFirst() //
8990
.orElseThrow(() -> new ConversionException("No registered or built-in converter for source '" + source
90-
+ "' and target type " + targetType.getType().getTypeName()));
91+
+ "' and target type " + targetType.getTypeName()));
9192

9293
return (T) converter.convert(source, sourceType, targetType, classLoaderToUse);
9394
}
9495

95-
private static ClassLoader getClassLoader(ClassLoader classLoader) {
96+
private static ClassLoader getClassLoader(@Nullable ClassLoader classLoader) {
9697
return classLoader != null ? classLoader : ClassLoaderUtils.getDefaultClassLoader();
9798
}
9899

junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/Converter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
1414

1515
import org.apiguardian.api.API;
16+
import org.jspecify.annotations.Nullable;
1617

1718
/**
1819
* {@code Converter} is an abstraction that allows an input object to
@@ -46,7 +47,7 @@ public interface Converter {
4647
* never {@code null}
4748
* @return {@code true} if the supplied source can be converted
4849
*/
49-
boolean canConvert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
50+
boolean canConvert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType);
5051

5152
/**
5253
* Convert the supplied source object into an instance of the specified
@@ -64,7 +65,7 @@ public interface Converter {
6465
* type is a reference type
6566
* @throws ConversionException if an error occurs during the conversion
6667
*/
67-
Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType, ClassLoader classLoader)
68-
throws ConversionException;
68+
Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType,
69+
ClassLoader classLoader) throws ConversionException;
6970

7071
}

junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
package org.junit.platform.commons.support.conversion;
1212

13-
import static java.util.Collections.unmodifiableMap;
14-
1513
import java.io.File;
1614
import java.net.MalformedURLException;
1715
import java.net.URI;
@@ -20,43 +18,36 @@
2018
import java.nio.file.Path;
2119
import java.nio.file.Paths;
2220
import java.util.Currency;
23-
import java.util.HashMap;
2421
import java.util.Locale;
2522
import java.util.Map;
2623
import java.util.UUID;
2724
import java.util.function.Function;
2825

26+
import org.jspecify.annotations.Nullable;
2927
import org.junit.platform.commons.util.Preconditions;
3028

3129
class StringToCommonJavaTypesConverter extends StringToObjectConverter {
3230

33-
private static final Map<Class<?>, Function<String, ?>> CONVERTERS;
34-
35-
static {
36-
Map<Class<?>, Function<String, ?>> converters = new HashMap<>();
37-
31+
private static final Map<Class<?>, Function<String, ?>> CONVERTERS = Map.of(
3832
// java.io and java.nio
39-
converters.put(File.class, File::new);
40-
converters.put(Charset.class, Charset::forName);
41-
converters.put(Path.class, Paths::get);
33+
File.class, File::new, //
34+
Charset.class, Charset::forName, //
35+
Path.class, Paths::get,
4236
// java.net
43-
converters.put(URI.class, URI::create);
44-
converters.put(URL.class, StringToCommonJavaTypesConverter::toURL);
37+
URI.class, URI::create, //
38+
URL.class, StringToCommonJavaTypesConverter::toURL,
4539
// java.util
46-
converters.put(Currency.class, Currency::getInstance);
47-
converters.put(Locale.class, Locale::new);
48-
converters.put(UUID.class, UUID::fromString);
49-
50-
CONVERTERS = unmodifiableMap(converters);
51-
}
40+
Currency.class, Currency::getInstance, //
41+
Locale.class, Locale::new, //
42+
UUID.class, UUID::fromString);
5243

5344
@Override
54-
public boolean canConvert(Class<?> targetType) {
45+
public boolean canConvert(@Nullable Class<?> targetType) {
5546
return CONVERTERS.containsKey(targetType);
5647
}
5748

5849
@Override
59-
public Object convert(String source, Class<?> targetType, ClassLoader classLoader) {
50+
public Object convert(@Nullable String source, @Nullable Class<?> targetType, ClassLoader classLoader) {
6051
Function<String, ?> converter = Preconditions.notNull(CONVERTERS.get(targetType),
6152
() -> "No registered converter for %s".formatted(targetType.getName()));
6253
return converter.apply(source);

junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
abstract class StringToObjectConverter implements Converter {
2020

2121
@Override
22-
public final boolean canConvert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
22+
public final boolean canConvert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
2323
return canConvert(targetType.getType());
2424
}
2525

@@ -28,10 +28,10 @@ public final boolean canConvert(Object source, TypeDescriptor sourceType, TypeDe
2828
* supplied target type (which is guaranteed to be a wrapper type for
2929
* primitives &mdash; for example, {@link Integer} instead of {@code int}).
3030
*/
31-
abstract boolean canConvert(Class<?> targetType);
31+
abstract boolean canConvert(@Nullable Class<?> targetType);
3232

3333
@Override
34-
public final Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType,
34+
public final Object convert(@Nullable Object source, TypeDescriptor sourceType, TypeDescriptor targetType,
3535
ClassLoader classLoader) {
3636
return convert((String) source, targetType.getType(), classLoader);
3737
}
@@ -44,6 +44,6 @@ public final Object convert(Object source, TypeDescriptor sourceType, TypeDescri
4444
* <p>This method will only be invoked if {@link #canConvert(Class)}
4545
* returned {@code true} for the same target type.
4646
*/
47-
abstract Object convert(String source, Class<?> targetType, ClassLoader classLoader);
47+
abstract Object convert(@Nullable String source, @Nullable Class<?> targetType, ClassLoader classLoader);
4848

4949
}

junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/TypeDescriptor.java

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414

1515
import java.lang.reflect.Field;
1616
import java.lang.reflect.Parameter;
17+
import java.util.Objects;
1718

1819
import org.apiguardian.api.API;
20+
import org.jspecify.annotations.Nullable;
1921
import org.junit.platform.commons.util.Preconditions;
2022
import org.junit.platform.commons.util.ReflectionUtils;
2123

@@ -27,13 +29,13 @@
2729
@API(status = EXPERIMENTAL, since = "1.13")
2830
public final class TypeDescriptor {
2931

30-
private final Class<?> type;
32+
private final @Nullable Class<?> type;
3133

3234
public static TypeDescriptor forClass(Class<?> clazz) {
3335
return new TypeDescriptor(clazz);
3436
}
3537

36-
public static TypeDescriptor forInstance(Object instance) {
38+
public static TypeDescriptor forInstance(@Nullable Object instance) {
3739
return new TypeDescriptor(instance != null ? instance.getClass() : null);
3840
}
3941

@@ -47,21 +49,28 @@ public static TypeDescriptor forParameter(Parameter parameter) {
4749
return new TypeDescriptor(parameter.getType());
4850
}
4951

50-
private TypeDescriptor(Class<?> type) {
52+
private TypeDescriptor(@Nullable Class<?> type) {
5153
this.type = type;
5254
}
5355

54-
public Class<?> getType() {
56+
public @Nullable Class<?> getType() {
5557
return type;
5658
}
5759

58-
public Class<?> getWrapperType() {
60+
public @Nullable Class<?> getWrapperType() {
61+
if (type == null) { // FIXME parameter of ReflectionUtils.getWrapperType should be @Nullable
62+
return null;
63+
}
5964
Class<?> wrapperType = ReflectionUtils.getWrapperType(type);
6065
return wrapperType != null ? wrapperType : type;
6166
}
6267

6368
public boolean isPrimitive() {
64-
return getType().isPrimitive();
69+
return type != null && type.isPrimitive();
70+
}
71+
72+
public String getTypeName() {
73+
return type != null ? type.getName() : "null";
6574
}
6675

6776
@Override
@@ -73,12 +82,12 @@ public boolean equals(Object o) {
7382
return false;
7483
}
7584
TypeDescriptor that = (TypeDescriptor) o;
76-
return this.type.equals(that.type);
85+
return Objects.equals(this.type, that.type);
7786
}
7887

7988
@Override
8089
public int hashCode() {
81-
return this.type.hashCode();
90+
return Objects.hashCode(type);
8291
}
8392

8493
}

platform-tests/src/test/java/org/junit/platform/commons/support/conversion/TypeDescriptorTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
/*
2+
* Copyright 2015-2025 the original author or authors.
3+
*
4+
* All rights reserved. This program and the accompanying materials are
5+
* made available under the terms of the Eclipse Public License v2.0 which
6+
* accompanies this distribution and is available at
7+
*
8+
* https://www.eclipse.org/legal/epl-v20.html
9+
*/
10+
111
package org.junit.platform.commons.support.conversion;
212

313
import static org.junit.jupiter.api.EqualsAndHashCodeAssertions.assertEqualsAndHashCode;

0 commit comments

Comments
 (0)