Skip to content

Commit 85e44df

Browse files
committed
mark all APIs nullable/non-nullable
JSpecify is de-facto standard annotations for marking nullability of variables, parameters, return values and fields. Supported by all IDEs. 1. By default, we mark everything as non-nullable (see @NullMarked in package-info.java) 2. When needed, we mark the nullable parameters/fields as @nullable.
1 parent 4e4a5bc commit 85e44df

File tree

78 files changed

+461
-192
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+461
-192
lines changed

pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
<jbanking.version>4.3.0</jbanking.version>
3838
<junit.version>6.0.3</junit.version>
3939
<libphonenumber.version>9.0.24</libphonenumber.version>
40+
<jspecify.version>1.0.0</jspecify.version>
41+
<error_prone.version>2.42.0</error_prone.version>
4042
<maven.compiler.source>17</maven.compiler.source>
4143
<maven.compiler.target>17</maven.compiler.target>
4244
<maven-compiler-plugin.version>3.15.0</maven-compiler-plugin.version>
@@ -89,6 +91,20 @@
8991
<version>${libphonenumber.version}</version>
9092
</dependency>
9193

94+
<!-- Annotations for nullability etc. -->
95+
<dependency>
96+
<groupId>org.jspecify</groupId>
97+
<artifactId>jspecify</artifactId>
98+
<version>${jspecify.version}</version>
99+
<scope>provided</scope>
100+
</dependency>
101+
<dependency>
102+
<groupId>com.google.errorprone</groupId>
103+
<artifactId>error_prone_annotations</artifactId>
104+
<version>${error_prone.version}</version>
105+
<scope>provided</scope>
106+
</dependency>
107+
92108
<!-- Test dependencies -->
93109
<dependency>
94110
<groupId>org.junit.jupiter</groupId>

src/main/java/net/datafaker/annotations/FakeResolver.java

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import net.datafaker.internal.helper.CopyOnWriteMap;
99
import net.datafaker.transformations.JavaObjectTransformer;
1010
import net.datafaker.transformations.Schema;
11+
import org.jspecify.annotations.Nullable;
1112

1213
import static java.util.Objects.requireNonNull;
1314

@@ -24,19 +25,22 @@ private FakeResolver(Class<T> clazz) {
2425
this.clazz = clazz;
2526
}
2627

28+
@SuppressWarnings("unchecked")
2729
public static <T> FakeResolver<T> of(Class<T> clazz) {
2830
var fakeFactory = CLASS_2_FAKE_RESOLVER.computeIfAbsent(clazz, k -> new FakeResolver<>(clazz));
2931
return (FakeResolver<T>) fakeFactory;
3032
}
3133

32-
public T generate(Schema<Object, ?> schema) {
34+
@SuppressWarnings("unchecked")
35+
public T generate(@Nullable Schema<Object, ?> schema) {
3336
if (schema == null) {
3437
return generateFromDefaultSchema();
3538
}
3639

3740
return (T) JAVA_OBJECT_TRANSFORMER.apply(clazz, schema);
3841
}
3942

43+
@SuppressWarnings("unchecked")
4044
private T generateFromDefaultSchema() {
4145
Schema<Object, ?> useSchema = DEFAULT_SCHEMA_CACHE.computeIfAbsent(clazz, (__) -> {
4246
FakeForSchema fakeForSchemaAnnotation = checkFakeAnnotation(clazz);
@@ -46,28 +50,27 @@ private T generateFromDefaultSchema() {
4650
return (T) JAVA_OBJECT_TRANSFORMER.apply(clazz, useSchema);
4751
}
4852

53+
@SuppressWarnings("unchecked")
4954
private Schema<Object, T> getSchema(String pathToSchema) {
50-
if (pathToSchema != null) {
51-
try {
52-
// indexOf(<String>) is faster than indexOf(<char>) since it has jvm intrinsic
53-
final int sharpIndex = pathToSchema.indexOf("#");
54-
final Class<?> classToCall;
55-
final String methodName;
56-
if (sharpIndex >= 0) {
57-
classToCall = Class.forName(pathToSchema.substring(0, sharpIndex));
58-
methodName = pathToSchema.substring(sharpIndex + 1);
59-
} else {
60-
classToCall = this.clazz.getEnclosingClass();
61-
methodName = pathToSchema;
62-
}
63-
Method myStaticMethod = classToCall.getMethod(methodName);
64-
myStaticMethod.setAccessible(true);
65-
return (Schema<Object, T>) myStaticMethod.invoke(null);
66-
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
67-
throw new RuntimeException(e);
55+
requireNonNull(pathToSchema, "The path to the schema is empty.");
56+
57+
try {
58+
// indexOf(<String>) is faster than indexOf(<char>) since it has jvm intrinsic
59+
final int sharpIndex = pathToSchema.indexOf("#");
60+
final Class<?> classToCall;
61+
final String methodName;
62+
if (sharpIndex >= 0) {
63+
classToCall = Class.forName(pathToSchema.substring(0, sharpIndex));
64+
methodName = pathToSchema.substring(sharpIndex + 1);
65+
} else {
66+
classToCall = this.clazz.getEnclosingClass();
67+
methodName = pathToSchema;
6868
}
69-
} else {
70-
throw new IllegalArgumentException("The path to the schema is empty.");
69+
Method myStaticMethod = classToCall.getMethod(methodName);
70+
myStaticMethod.setAccessible(true);
71+
return (Schema<Object, T>) myStaticMethod.invoke(null);
72+
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
73+
throw new RuntimeException(e);
7174
}
7275
}
7376

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@NullMarked
2+
@CheckReturnValue
3+
package net.datafaker.annotations;
4+
5+
import com.google.errorprone.annotations.CheckReturnValue;
6+
7+
import org.jspecify.annotations.NullMarked;

src/main/java/net/datafaker/idnumbers/EstonianIdNumber.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import static net.datafaker.idnumbers.Utils.randomGender;
1414

1515
/**
16-
* Estonian personal identification number ("Isikukood" in estonian)
16+
* Estonian personal identification number ("Isikukood" in Estonian)
1717
* <p>
1818
* The number is 11 digits, with modulus 11 checksum digit.
1919
* There is fixed list of valid first digits to signify gender and birth century

src/main/java/net/datafaker/idnumbers/HungarianIdNumber.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ private String basePart(BaseProviders faker, LocalDate birthday, PersonIdNumber.
6464

6565
static int getCheckDigit(String basePart) {
6666
char[] numbers = basePart.toCharArray();
67-
int summ = 0;
67+
int sum = 0;
6868
for (int i = 0; i < numbers.length; i++) {
69-
summ += getNumericValue(numbers[i]) * (i + 1);
69+
sum += getNumericValue(numbers[i]) * (i + 1);
7070
}
7171

72-
return summ % 11;
72+
return sum % 11;
7373
}
7474

7575
static int firstDigit(int birthYear, PersonIdNumber.Gender gender) {

src/main/java/net/datafaker/idnumbers/IdNumberGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ default String generateValid(BaseProviders faker) {
2727
String generateInvalid(BaseProviders faker);
2828

2929
/**
30-
* Generates a valid ID number for given country corresponding to given criterias (age range, gender etc.)
30+
* Generates a valid ID number for given country corresponding to given criteria (age range, gender etc.)
3131
*
3232
* @return PersonIdNumber containing a valid combination of ID, Birthday and Gender.
3333
* In countries where ID number doesn't contain gender and/or birthday, the latter values are just random.

src/main/java/net/datafaker/idnumbers/PolishIdNumber.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import net.datafaker.providers.base.IdNumber.GenderRequest;
55
import net.datafaker.providers.base.IdNumber.IdNumberRequest;
66
import net.datafaker.providers.base.PersonIdNumber;
7+
import org.jspecify.annotations.Nullable;
78

89
import java.time.LocalDate;
910

@@ -52,7 +53,7 @@ public String get(BaseProviders faker, LocalDate birthDate, Gender requestedGend
5253
return get(faker, birthDate, gender);
5354
}
5455

55-
private static PersonIdNumber.Gender pickGender(BaseProviders faker, Gender requestedGender) {
56+
private static PersonIdNumber.Gender pickGender(BaseProviders faker, @Nullable Gender requestedGender) {
5657
return requestedGender == null ? randomGender(faker) :
5758
switch (requestedGender) {
5859
case ANY -> randomGender(faker);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@NullMarked
2+
@CheckReturnValue
3+
package net.datafaker.idnumbers;
4+
5+
import com.google.errorprone.annotations.CheckReturnValue;
6+
import org.jspecify.annotations.NullMarked;

src/main/java/net/datafaker/idnumbers/pt/br/IdNumberGeneratorPtBrUtil.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public static boolean isCNPJValid(final String cnpj) {
108108

109109
/**
110110
* Return true if the CPF is valid
111-
* A valid CPF is unique and have a algorithm to validate it
111+
* A valid CPF is unique and have an algorithm to validate it
112112
* <p>
113113
* CPF generator could generate a valid or invalid because, sometimes, we need to test a
114114
* registration with invalid number
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
@NullMarked
2+
@CheckReturnValue
3+
package net.datafaker.idnumbers.pt.br;
4+
5+
import com.google.errorprone.annotations.CheckReturnValue;
6+
import org.jspecify.annotations.NullMarked;

0 commit comments

Comments
 (0)