diff --git a/extras/src/main/java/com/google/gson/graph/GraphAdapterBuilder.java b/extras/src/main/java/com/google/gson/graph/GraphAdapterBuilder.java index cd360a4c4e..80963a68e2 100644 --- a/extras/src/main/java/com/google/gson/graph/GraphAdapterBuilder.java +++ b/extras/src/main/java/com/google/gson/graph/GraphAdapterBuilder.java @@ -29,6 +29,8 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.lang.reflect.Type; import java.util.ArrayDeque; @@ -151,7 +153,7 @@ static class Factory implements TypeAdapterFactory, InstanceCreator { } @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { if (!instanceCreators.containsKey(type.getType())) { return null; } diff --git a/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java b/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java index 7868a13352..95a60cc2f8 100644 --- a/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java +++ b/extras/src/main/java/com/google/gson/interceptors/InterceptorFactory.java @@ -22,12 +22,14 @@ import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; +import org.jspecify.annotations.Nullable; + import java.io.IOException; /** A type adapter factory that implements {@code @Intercept}. */ public final class InterceptorFactory implements TypeAdapterFactory { @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { Intercept intercept = type.getRawType().getAnnotation(Intercept.class); if (intercept == null) { return null; diff --git a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java index 924a9089ff..f6211b23f4 100644 --- a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java +++ b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java @@ -22,6 +22,8 @@ import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -30,7 +32,7 @@ public class PostConstructAdapterFactory implements TypeAdapterFactory { // copied from https://gist.github.com/swankjesse/20df26adaf639ed7fd160f145a0b661a @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { for (Class t = type.getRawType(); (t != Object.class) && (t.getSuperclass() != null); t = t.getSuperclass()) { diff --git a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java index 01812ad24f..e0122684c6 100644 --- a/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java +++ b/extras/src/main/java/com/google/gson/typeadapters/RuntimeTypeAdapterFactory.java @@ -27,6 +27,8 @@ import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; +import org.jspecify.annotations.Nullable; + import java.io.IOException; import java.util.LinkedHashMap; import java.util.Map; @@ -241,7 +243,7 @@ public RuntimeTypeAdapterFactory registerSubtype(Class type) { } @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { if (type == null) { return null; } diff --git a/gson/pom.xml b/gson/pom.xml index 10969fb8a9..ca760b7ccc 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -52,6 +52,11 @@ error_prone_annotations 2.43.0 + + org.jspecify + jspecify + compile + junit diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java index e33a839dbd..c38a254cb6 100644 --- a/gson/src/main/java/com/google/gson/TypeAdapter.java +++ b/gson/src/main/java/com/google/gson/TypeAdapter.java @@ -26,6 +26,7 @@ import java.io.Reader; import java.io.StringReader; import java.io.Writer; +import org.jspecify.annotations.Nullable; /** * Converts Java objects to and from JSON. @@ -127,7 +128,7 @@ public TypeAdapter() {} * * @param value the Java object to write. May be null. */ - public abstract void write(JsonWriter out, T value) throws IOException; + public abstract void write(JsonWriter out, @Nullable T value) throws IOException; /** * Converts {@code value} to a JSON document and writes it to {@code out}. @@ -191,7 +192,7 @@ public final JsonElement toJsonTree(T value) { * * @return the converted Java object. May be {@code null}. */ - public abstract T read(JsonReader in) throws IOException; + public abstract @Nullable T read(JsonReader in) throws IOException; /** * Converts the JSON document in {@code in} to a Java object. @@ -207,7 +208,7 @@ public final JsonElement toJsonTree(T value) { * @return the converted Java object. May be {@code null}. * @since 2.2 */ - public final T fromJson(Reader in) throws IOException { + public final @Nullable T fromJson(Reader in) throws IOException { JsonReader reader = new JsonReader(in); return read(reader); } @@ -226,7 +227,7 @@ public final T fromJson(Reader in) throws IOException { * @return the converted Java object. May be {@code null}. * @since 2.2 */ - public final T fromJson(String json) throws IOException { + public final @Nullable T fromJson(String json) throws IOException { return fromJson(new StringReader(json)); } @@ -238,7 +239,7 @@ public final T fromJson(String json) throws IOException { * @throws JsonIOException wrapping {@code IOException}s thrown by {@link #read(JsonReader)} * @since 2.2 */ - public final T fromJsonTree(JsonElement jsonTree) { + public final @Nullable T fromJsonTree(JsonElement jsonTree) { try { JsonReader jsonReader = new JsonTreeReader(jsonTree); return read(jsonReader); @@ -297,7 +298,7 @@ public final TypeAdapter nullSafe() { private final class NullSafeTypeAdapter extends TypeAdapter { @Override - public void write(JsonWriter out, T value) throws IOException { + public void write(JsonWriter out, @Nullable T value) throws IOException { if (value == null) { out.nullValue(); } else { @@ -306,7 +307,7 @@ public void write(JsonWriter out, T value) throws IOException { } @Override - public T read(JsonReader reader) throws IOException { + public @Nullable T read(JsonReader reader) throws IOException { if (reader.peek() == JsonToken.NULL) { reader.nextNull(); return null; diff --git a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java index 4473e59b7a..08141f8cb5 100644 --- a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java @@ -17,6 +17,7 @@ package com.google.gson; import com.google.gson.reflect.TypeToken; +import org.jspecify.annotations.Nullable; /** * Creates type adapters for set of related types. Type adapter factories are most useful when @@ -166,5 +167,5 @@ public interface TypeAdapterFactory { /** * Returns a type adapter for {@code type}, or null if this factory doesn't support {@code type}. */ - TypeAdapter create(Gson gson, TypeToken type); + @Nullable TypeAdapter create(Gson gson, TypeToken type); } diff --git a/gson/src/main/java/com/google/gson/annotations/package-info.java b/gson/src/main/java/com/google/gson/annotations/package-info.java index edc5304c4b..2518b81cca 100644 --- a/gson/src/main/java/com/google/gson/annotations/package-info.java +++ b/gson/src/main/java/com/google/gson/annotations/package-info.java @@ -20,4 +20,5 @@ * @author Inderjeet Singh, Joel Leitch */ @com.google.errorprone.annotations.CheckReturnValue +@org.jspecify.annotations.NullMarked package com.google.gson.annotations; diff --git a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java index a76a0014e4..332421156b 100644 --- a/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java +++ b/gson/src/main/java/com/google/gson/internal/ConstructorConstructor.java @@ -40,6 +40,7 @@ import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; +import org.jspecify.annotations.Nullable; /** Returns a function that can construct an instance of a requested type. */ public final class ConstructorConstructor { @@ -63,7 +64,7 @@ public ConstructorConstructor( * @param c instance of the class to be checked * @return if instantiable {@code null}, else a non-{@code null} exception message */ - static String checkInstantiable(Class c) { + static @Nullable String checkInstantiable(Class c) { int modifiers = c.getModifiers(); if (Modifier.isInterface(modifiers)) { return "Interfaces can't be instantiated! Register an InstanceCreator" @@ -174,7 +175,7 @@ public ObjectConstructor get(TypeToken typeToken, boolean allowUnsafe) * Creates constructors for special JDK collection types which do not have a public no-args * constructor. */ - private static ObjectConstructor newSpecialCollectionConstructor( + private static @Nullable ObjectConstructor newSpecialCollectionConstructor( Type type, Class rawType) { if (EnumSet.class.isAssignableFrom(rawType)) { return () -> { @@ -214,7 +215,7 @@ else if (rawType == EnumMap.class) { return null; } - private static ObjectConstructor newDefaultConstructor( + private static @Nullable ObjectConstructor newDefaultConstructor( Class rawType, FilterResult filterResult) { // Cannot invoke constructor of abstract class if (Modifier.isAbstract(rawType.getModifiers())) { @@ -285,7 +286,7 @@ private static ObjectConstructor newDefaultConstructor( } /** Constructors for common interface types like Map and List and their subtypes. */ - private static ObjectConstructor newDefaultImplementationConstructor( + private static @Nullable ObjectConstructor newDefaultImplementationConstructor( Type type, Class rawType) { /* @@ -349,7 +350,7 @@ private static boolean hasStringKeyType(Type mapType) { return GsonTypes.getRawType(typeArguments[0]) == String.class; } - private static ObjectConstructor> newMapConstructor( + private static @Nullable ObjectConstructor> newMapConstructor( Type type, Class rawType) { // First try Map implementation /* diff --git a/gson/src/main/java/com/google/gson/internal/Excluder.java b/gson/src/main/java/com/google/gson/internal/Excluder.java index 14ecd60fbe..537b8b10dc 100644 --- a/gson/src/main/java/com/google/gson/internal/Excluder.java +++ b/gson/src/main/java/com/google/gson/internal/Excluder.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import org.jspecify.annotations.Nullable; /** * This class selects which fields and types to omit. It is configurable, supporting version @@ -108,7 +109,7 @@ public Excluder withExclusionStrategy( } @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { Class rawType = type.getRawType(); boolean skipSerialize = excludeClass(rawType, true); diff --git a/gson/src/main/java/com/google/gson/internal/GsonTypes.java b/gson/src/main/java/com/google/gson/internal/GsonTypes.java index 412c3bf98a..6dc348a761 100644 --- a/gson/src/main/java/com/google/gson/internal/GsonTypes.java +++ b/gson/src/main/java/com/google/gson/internal/GsonTypes.java @@ -34,6 +34,7 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.Properties; +import org.jspecify.annotations.Nullable; /** * Static methods for working with types. @@ -55,7 +56,7 @@ private GsonTypes() { * @return a {@link java.io.Serializable serializable} parameterized type. */ public static ParameterizedType newParameterizedTypeWithOwner( - Type ownerType, Class rawType, Type... typeArguments) { + @Nullable Type ownerType, Class rawType, Type... typeArguments) { return new ParameterizedTypeImpl(ownerType, rawType, typeArguments); } @@ -512,7 +513,7 @@ public static boolean requiresOwnerType(Type rawType) { // the nested Type implementations here (which are also serializable). private static final class ParameterizedTypeImpl implements ParameterizedType, Serializable { @SuppressWarnings("serial") - private final Type ownerType; + private final @Nullable Type ownerType; @SuppressWarnings("serial") private final Type rawType; @@ -520,7 +521,7 @@ private static final class ParameterizedTypeImpl implements ParameterizedType, S @SuppressWarnings("serial") private final Type[] typeArguments; - ParameterizedTypeImpl(Type ownerType, Class rawType, Type... typeArguments) { + ParameterizedTypeImpl(@Nullable Type ownerType, Class rawType, Type... typeArguments) { requireNonNull(rawType); if (ownerType == null && requiresOwnerType(rawType)) { @@ -548,17 +549,17 @@ public Type getRawType() { } @Override - public Type getOwnerType() { + public @Nullable Type getOwnerType() { return ownerType; } @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { return other instanceof ParameterizedType && GsonTypes.equals(this, (ParameterizedType) other); } - private static int hashCodeOrZero(Object o) { + private static int hashCodeOrZero(@Nullable Object o) { return o != null ? o.hashCode() : 0; } @@ -631,7 +632,7 @@ private static final class WildcardTypeImpl implements WildcardType, Serializabl private final Type upperBound; @SuppressWarnings("serial") - private final Type lowerBound; + private final @Nullable Type lowerBound; WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { if (lowerBounds.length > 1) { diff --git a/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java b/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java index ead949ae1e..efbe0a9106 100644 --- a/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java +++ b/gson/src/main/java/com/google/gson/internal/ReflectionAccessFilterHelper.java @@ -21,6 +21,7 @@ import java.lang.reflect.AccessibleObject; import java.lang.reflect.Method; import java.util.List; +import org.jspecify.annotations.Nullable; /** Internal helper class for {@link ReflectionAccessFilter}. */ public class ReflectionAccessFilterHelper { @@ -73,7 +74,7 @@ public static FilterResult getFilterResult( } /** See {@link AccessibleObject#canAccess(Object)} (Java >= 9) */ - public static boolean canAccess(AccessibleObject accessibleObject, Object object) { + public static boolean canAccess(AccessibleObject accessibleObject, @Nullable Object object) { return AccessChecker.INSTANCE.canAccess(accessibleObject, object); } @@ -90,7 +91,8 @@ private abstract static class AccessChecker { accessChecker = new AccessChecker() { @Override - public boolean canAccess(AccessibleObject accessibleObject, Object object) { + public boolean canAccess( + AccessibleObject accessibleObject, @Nullable Object object) { try { return (Boolean) canAccessMethod.invoke(accessibleObject, object); } catch (Exception e) { @@ -107,7 +109,7 @@ public boolean canAccess(AccessibleObject accessibleObject, Object object) { accessChecker = new AccessChecker() { @Override - public boolean canAccess(AccessibleObject accessibleObject, Object object) { + public boolean canAccess(AccessibleObject accessibleObject, @Nullable Object object) { // Cannot determine whether object can be accessed, so assume it can be accessed return true; } @@ -116,6 +118,6 @@ public boolean canAccess(AccessibleObject accessibleObject, Object object) { INSTANCE = accessChecker; } - abstract boolean canAccess(AccessibleObject accessibleObject, Object object); + abstract boolean canAccess(AccessibleObject accessibleObject, @Nullable Object object); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java index 50efa418c0..da2d168926 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ArrayTypeAdapter.java @@ -29,13 +29,14 @@ import java.lang.reflect.GenericArrayType; import java.lang.reflect.Type; import java.util.ArrayList; +import org.jspecify.annotations.Nullable; /** Adapter for arrays. */ public final class ArrayTypeAdapter extends TypeAdapter { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); if (!(type instanceof GenericArrayType || (type instanceof Class && ((Class) type).isArray()))) { diff --git a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java index 7dd48a3ebb..d95685bf13 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/CollectionTypeAdapterFactory.java @@ -29,6 +29,7 @@ import java.io.IOException; import java.lang.reflect.Type; import java.util.Collection; +import org.jspecify.annotations.Nullable; /** Adapt a homogeneous collection of objects. */ public final class CollectionTypeAdapterFactory implements TypeAdapterFactory { @@ -39,7 +40,7 @@ public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructo } @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); Class rawType = typeToken.getRawType(); diff --git a/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java index b5dffe24fb..d8733e2e8f 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/DefaultDateTypeAdapter.java @@ -38,6 +38,7 @@ import java.util.Locale; import java.util.Objects; import java.util.TimeZone; +import org.jspecify.annotations.Nullable; /** * This type adapter supports subclasses of date by defining a {@link @@ -65,7 +66,7 @@ public final class DefaultDateTypeAdapter extends TypeAdapter new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.getRawType() == Date.class ? (TypeAdapter) new DefaultDateTypeAdapter<>( diff --git a/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java index 5f24dc18d9..557740db40 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/EnumTypeAdapter.java @@ -30,13 +30,14 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; /** Adapter for enum classes (but not for the base class {@code java.lang.Enum}). */ class EnumTypeAdapter> extends TypeAdapter { static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Class rawType = typeToken.getRawType(); if (!Enum.class.isAssignableFrom(rawType) || rawType == Enum.class) { return null; @@ -110,7 +111,7 @@ public T read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, T value) throws IOException { + public void write(JsonWriter out, @Nullable T value) throws IOException { out.value(value == null ? null : constantToName.get(value)); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java index 193ab8f7a6..571b56e29c 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java @@ -27,6 +27,7 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.jspecify.annotations.Nullable; /** * Given a type T, looks for the annotation {@link JsonAdapter} and uses an instance of the @@ -37,7 +38,7 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory { private static class DummyTypeAdapterFactory implements TypeAdapterFactory { @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { throw new AssertionError("Factory should not be used"); } } @@ -74,7 +75,7 @@ private static JsonAdapter getAnnotation(Class rawType) { // this is not safe; requires that user has specified correct adapter class for @JsonAdapter @SuppressWarnings("unchecked") @Override - public TypeAdapter create(Gson gson, TypeToken targetType) { + public @Nullable TypeAdapter create(Gson gson, TypeToken targetType) { Class rawType = targetType.getRawType(); JsonAdapter annotation = getAnnotation(rawType); if (annotation == null) { diff --git a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java index 49fc731edf..72518033d2 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/MapTypeAdapterFactory.java @@ -36,6 +36,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import org.jspecify.annotations.Nullable; /** * Adapts maps to either JSON objects or JSON arrays. @@ -123,7 +124,7 @@ public MapTypeAdapterFactory( } @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Type type = typeToken.getType(); Class rawType = typeToken.getRawType(); diff --git a/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java index 80eabccd93..30357f9018 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/NumberTypeAdapter.java @@ -27,6 +27,7 @@ import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import java.io.IOException; +import org.jspecify.annotations.Nullable; /** Type adapter for {@link Number}. */ public final class NumberTypeAdapter extends TypeAdapter { @@ -45,7 +46,7 @@ private static TypeAdapterFactory newFactory(ToNumberStrategy toNumberStrategy) return new TypeAdapterFactory() { @SuppressWarnings("unchecked") @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { return type.getRawType() == Number.class ? (TypeAdapter) adapter : null; } }; diff --git a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java index 2fa704544f..052a5d84e4 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ObjectTypeAdapter.java @@ -32,6 +32,7 @@ import java.util.Deque; import java.util.List; import java.util.Map; +import org.jspecify.annotations.Nullable; /** * Adapts types whose static type is only 'Object'. Uses getClass() on serialization and a @@ -53,7 +54,7 @@ private static TypeAdapterFactory newFactory(ToNumberStrategy toNumberStrategy) return new TypeAdapterFactory() { @SuppressWarnings("unchecked") @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { if (type.getRawType() == Object.class) { return (TypeAdapter) new ObjectTypeAdapter(gson, toNumberStrategy); } diff --git a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java index ef464684aa..7eff5e43e0 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java +++ b/gson/src/main/java/com/google/gson/internal/bind/ReflectiveTypeAdapterFactory.java @@ -55,6 +55,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.jspecify.annotations.Nullable; /** Type adapter that reflects over the fields and methods of a class. */ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory { @@ -107,7 +108,7 @@ private List getFieldNames(Field f) { } @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { Class raw = type.getRawType(); if (!Object.class.isAssignableFrom(raw)) { diff --git a/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java index 62ea14d383..8c59f7bd49 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TreeTypeAdapter.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.lang.reflect.Type; import java.util.Objects; +import org.jspecify.annotations.Nullable; /** * Adapts a Gson 1.x tree-style adapter as a streaming TypeAdapter. Since the tree adapter may be @@ -176,7 +177,7 @@ private static final class SingleTypeFactory implements TypeAdapterFactory { @SuppressWarnings("unchecked") // guarded by typeToken.equals() call @Override - public TypeAdapter create(Gson gson, TypeToken type) { + public @Nullable TypeAdapter create(Gson gson, TypeToken type) { boolean matches = exactType != null ? exactType.equals(type) || (matchRawType && exactType.getType() == type.getRawType()) diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java index 71f98c0034..6c69dab153 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java @@ -48,6 +48,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerArray; +import org.jspecify.annotations.Nullable; /** * Type adapters for basic types. More complex adapters exist as separate classes in the enclosing @@ -819,7 +820,7 @@ public static TypeAdapterFactory newFactory( return new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.equals(type) ? (TypeAdapter) typeAdapter : null; } }; @@ -830,7 +831,7 @@ public static TypeAdapterFactory newFactory(Class type, TypeAdapter return new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.getRawType() == type ? (TypeAdapter) typeAdapter : null; } @@ -847,7 +848,7 @@ public static TypeAdapterFactory newFactory( return new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Class rawType = typeToken.getRawType(); return (rawType == unboxed || rawType == boxed) ? (TypeAdapter) typeAdapter : null; } @@ -871,7 +872,7 @@ public static TypeAdapterFactory newFactoryForMultipleTypes( return new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Class rawType = typeToken.getRawType(); return (rawType == base || rawType == sub) ? (TypeAdapter) typeAdapter : null; } @@ -898,7 +899,7 @@ public static TypeAdapterFactory newTypeHierarchyFactory( return new TypeAdapterFactory() { @SuppressWarnings("unchecked") @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Class requestedType = typeToken.getRawType(); if (!clazz.isAssignableFrom(requestedType)) { return null; diff --git a/gson/src/main/java/com/google/gson/internal/bind/package-info.java b/gson/src/main/java/com/google/gson/internal/bind/package-info.java new file mode 100644 index 0000000000..5341e33820 --- /dev/null +++ b/gson/src/main/java/com/google/gson/internal/bind/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Do NOT use any class in this package as they are meant for internal use in Gson. These classes + * will very likely change incompatibly in future versions. You have been warned. + * + * @author Inderjeet Singh, Joel Leitch, Jesse Wilson + */ +@com.google.errorprone.annotations.CheckReturnValue +@org.jspecify.annotations.NullMarked +package com.google.gson.internal.bind; diff --git a/gson/src/main/java/com/google/gson/internal/bind/util/package-info.java b/gson/src/main/java/com/google/gson/internal/bind/util/package-info.java new file mode 100644 index 0000000000..50226806ac --- /dev/null +++ b/gson/src/main/java/com/google/gson/internal/bind/util/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Do NOT use any class in this package as they are meant for internal use in Gson. These classes + * will very likely change incompatibly in future versions. You have been warned. + * + * @author Inderjeet Singh, Joel Leitch, Jesse Wilson + */ +@com.google.errorprone.annotations.CheckReturnValue +@org.jspecify.annotations.NullMarked +package com.google.gson.internal.bind.util; diff --git a/gson/src/main/java/com/google/gson/internal/package-info.java b/gson/src/main/java/com/google/gson/internal/package-info.java index c92c71de63..a0577c0162 100644 --- a/gson/src/main/java/com/google/gson/internal/package-info.java +++ b/gson/src/main/java/com/google/gson/internal/package-info.java @@ -21,4 +21,5 @@ * @author Inderjeet Singh, Joel Leitch, Jesse Wilson */ @com.google.errorprone.annotations.CheckReturnValue +@org.jspecify.annotations.NullMarked package com.google.gson.internal; diff --git a/gson/src/main/java/com/google/gson/internal/reflect/package-info.java b/gson/src/main/java/com/google/gson/internal/reflect/package-info.java new file mode 100644 index 0000000000..f7552e0d83 --- /dev/null +++ b/gson/src/main/java/com/google/gson/internal/reflect/package-info.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Do NOT use any class in this package as they are meant for internal use in Gson. These classes + * will very likely change incompatibly in future versions. You have been warned. + * + * @author Inderjeet Singh, Joel Leitch, Jesse Wilson + */ +@com.google.errorprone.annotations.CheckReturnValue +@org.jspecify.annotations.NullMarked +package com.google.gson.internal.reflect; diff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java index 1991daefb0..7bbbfaba5a 100644 --- a/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/sql/SqlDateTypeAdapter.java @@ -30,6 +30,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; +import org.jspecify.annotations.Nullable; /** * Adapter for java.sql.Date. Although this class appears stateless, it is not. DateFormat captures @@ -42,7 +43,7 @@ final class SqlDateTypeAdapter extends TypeAdapter { new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { return typeToken.getRawType() == java.sql.Date.class ? (TypeAdapter) new SqlDateTypeAdapter() : null; diff --git a/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java index d63ae0677e..84a5463d9f 100644 --- a/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/sql/SqlTimeTypeAdapter.java @@ -31,6 +31,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; +import org.jspecify.annotations.Nullable; /** * Adapter for java.sql.Time. Although this class appears stateless, it is not. DateFormat captures @@ -43,7 +44,7 @@ final class SqlTimeTypeAdapter extends TypeAdapter