diff --git a/gson/pom.xml b/gson/pom.xml index 7918efc65d..ec08dfcda9 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -53,6 +53,12 @@ 2.47.0 + + org.jspecify + jspecify + compile + + junit junit diff --git a/gson/src/main/java/com/google/gson/FieldAttributes.java b/gson/src/main/java/com/google/gson/FieldAttributes.java index b4d3709fb0..5cf0a165cb 100644 --- a/gson/src/main/java/com/google/gson/FieldAttributes.java +++ b/gson/src/main/java/com/google/gson/FieldAttributes.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Objects; +import org.jspecify.annotations.Nullable; /** * A data object that stores attributes of a field. @@ -113,7 +114,7 @@ public Class getDeclaredClass() { * @param annotation the class of the annotation that will be retrieved * @return the annotation instance if it is bound to the field; otherwise {@code null} */ - public T getAnnotation(Class annotation) { + public @Nullable T getAnnotation(Class annotation) { return field.getAnnotation(annotation); } diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index a06f290747..52b3c2893b 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -45,6 +45,7 @@ import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.jspecify.annotations.Nullable; /** * This is the main class for using Gson. Gson is typically used by first constructing a Gson @@ -148,7 +149,7 @@ public final class Gson { * TypeAdapter} as value. */ @SuppressWarnings("ThreadLocalUsage") - private final ThreadLocal, TypeAdapter>> threadLocalAdapterResults = + private final ThreadLocal<@Nullable Map, TypeAdapter>> threadLocalAdapterResults = new ThreadLocal<>(); private final ConcurrentMap, TypeAdapter> typeTokenCache = @@ -167,7 +168,7 @@ public final class Gson { final boolean generateNonExecutableJson; final boolean htmlSafe; final FormattingStyle formattingStyle; - final Strictness strictness; + final @Nullable Strictness strictness; final boolean serializeSpecialFloatingPointValues; final boolean useJdkUnsafe; final String datePattern; @@ -493,7 +494,7 @@ public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeTo * @since 1.4 * @see #toJsonTree(Object, Type) */ - public JsonElement toJsonTree(Object src) { + public JsonElement toJsonTree(@Nullable Object src) { if (src == null) { return JsonNull.INSTANCE; } @@ -518,7 +519,7 @@ public JsonElement toJsonTree(Object src) { * @since 1.4 * @see #toJsonTree(Object) */ - public JsonElement toJsonTree(Object src, Type typeOfSrc) { + public JsonElement toJsonTree(@Nullable Object src, Type typeOfSrc) { JsonTreeWriter writer = new JsonTreeWriter(); toJson(src, typeOfSrc, writer); return writer.get(); @@ -539,7 +540,7 @@ public JsonElement toJsonTree(Object src, Type typeOfSrc) { * @see #toJson(Object, Appendable) * @see #toJson(Object, Type) */ - public String toJson(Object src) { + public String toJson(@Nullable Object src) { if (src == null) { return toJson(JsonNull.INSTANCE); } @@ -564,7 +565,7 @@ public String toJson(Object src) { * @see #toJson(Object, Type, Appendable) * @see #toJson(Object) */ - public String toJson(Object src, Type typeOfSrc) { + public String toJson(@Nullable Object src, Type typeOfSrc) { StringBuilder writer = new StringBuilder(); toJson(src, typeOfSrc, writer); return writer.toString(); @@ -586,7 +587,7 @@ public String toJson(Object src, Type typeOfSrc) { * @see #toJson(Object) * @see #toJson(Object, Type, Appendable) */ - public void toJson(Object src, Appendable writer) throws JsonIOException { + public void toJson(@Nullable Object src, Appendable writer) throws JsonIOException { if (src != null) { toJson(src, src.getClass(), writer); } else { @@ -614,7 +615,8 @@ public void toJson(Object src, Appendable writer) throws JsonIOException { * @see #toJson(Object, Type) * @see #toJson(Object, Appendable) */ - public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException { + public void toJson(@Nullable Object src, Type typeOfSrc, Appendable writer) + throws JsonIOException { try { JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); toJson(src, typeOfSrc, jsonWriter); @@ -644,7 +646,8 @@ public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOE * @param writer Writer to which the JSON representation of src needs to be written * @throws JsonIOException if there was a problem writing to the writer */ - public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { + public void toJson(@Nullable Object src, Type typeOfSrc, JsonWriter writer) + throws JsonIOException { @SuppressWarnings("unchecked") TypeAdapter adapter = (TypeAdapter) getAdapter(TypeToken.get(typeOfSrc)); @@ -682,7 +685,7 @@ public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOE * @return JSON String representation of the tree. * @since 1.4 */ - public String toJson(JsonElement jsonElement) { + public String toJson(@Nullable JsonElement jsonElement) { StringBuilder writer = new StringBuilder(); toJson(jsonElement, writer); return writer.toString(); @@ -696,7 +699,7 @@ public String toJson(JsonElement jsonElement) { * @throws JsonIOException if there was a problem writing to the writer * @since 1.4 */ - public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException { + public void toJson(@Nullable JsonElement jsonElement, Appendable writer) throws JsonIOException { try { JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); toJson(jsonElement, jsonWriter); @@ -725,7 +728,7 @@ public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOExce * @param writer the JSON writer to which the provided element will be written * @throws JsonIOException if there was a problem writing to the writer */ - public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException { + public void toJson(@Nullable JsonElement jsonElement, JsonWriter writer) throws JsonIOException { Strictness oldStrictness = writer.getStrictness(); boolean oldHtmlSafe = writer.isHtmlSafe(); boolean oldSerializeNulls = writer.getSerializeNulls(); @@ -824,7 +827,8 @@ public JsonReader newJsonReader(Reader reader) { * @see #fromJson(Reader, Class) * @see #fromJson(String, TypeToken) */ - public T fromJson(String json, Class classOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable String json, Class classOfT) + throws JsonSyntaxException { return fromJson(json, TypeToken.get(classOfT)); } @@ -853,7 +857,7 @@ public T fromJson(String json, Class classOfT) throws JsonSyntaxException * @see #fromJson(String, TypeToken) */ @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) - public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable String json, Type typeOfT) throws JsonSyntaxException { return (T) fromJson(json, TypeToken.get(typeOfT)); } @@ -883,7 +887,8 @@ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { * @see #fromJson(String, Class) * @since 2.10 */ - public T fromJson(String json, TypeToken typeOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable String json, TypeToken typeOfT) + throws JsonSyntaxException { if (json == null) { return null; } @@ -914,7 +919,7 @@ public T fromJson(String json, TypeToken typeOfT) throws JsonSyntaxExcept * @see #fromJson(String, Class) * @see #fromJson(Reader, TypeToken) */ - public T fromJson(Reader json, Class classOfT) + public @Nullable T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { return fromJson(json, TypeToken.get(classOfT)); } @@ -945,7 +950,8 @@ public T fromJson(Reader json, Class classOfT) * @see #fromJson(Reader, TypeToken) */ @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) - public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { + public @Nullable T fromJson(Reader json, Type typeOfT) + throws JsonIOException, JsonSyntaxException { return (T) fromJson(json, TypeToken.get(typeOfT)); } @@ -975,7 +981,7 @@ public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyn * @see #fromJson(Reader, Class) * @since 2.10 */ - public T fromJson(Reader json, TypeToken typeOfT) + public @Nullable T fromJson(Reader json, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException { JsonReader jsonReader = newJsonReader(json); T object = fromJson(jsonReader, typeOfT); @@ -1020,7 +1026,7 @@ public T fromJson(Reader json, TypeToken typeOfT) * @see #fromJson(JsonReader, TypeToken) */ @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) - public T fromJson(JsonReader reader, Type typeOfT) + public @Nullable T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { return (T) fromJson(reader, TypeToken.get(typeOfT)); } @@ -1061,7 +1067,7 @@ public T fromJson(JsonReader reader, Type typeOfT) * @see #fromJson(JsonReader, Type) * @since 2.10 */ - public T fromJson(JsonReader reader, TypeToken typeOfT) + public @Nullable T fromJson(JsonReader reader, TypeToken typeOfT) throws JsonIOException, JsonSyntaxException { boolean isEmpty = true; Strictness oldStrictness = reader.getStrictness(); @@ -1133,7 +1139,8 @@ public T fromJson(JsonReader reader, TypeToken typeOfT) * @see #fromJson(Reader, Class) * @see #fromJson(JsonElement, TypeToken) */ - public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable JsonElement json, Class classOfT) + throws JsonSyntaxException { return fromJson(json, TypeToken.get(classOfT)); } @@ -1160,7 +1167,8 @@ public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxExce * @see #fromJson(JsonElement, TypeToken) */ @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"}) - public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable JsonElement json, Type typeOfT) + throws JsonSyntaxException { return (T) fromJson(json, TypeToken.get(typeOfT)); } @@ -1186,14 +1194,15 @@ public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException * @see #fromJson(JsonElement, Class) * @since 2.10 */ - public T fromJson(JsonElement json, TypeToken typeOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable JsonElement json, TypeToken typeOfT) + throws JsonSyntaxException { if (json == null) { return null; } return fromJson(new JsonTreeReader(json), typeOfT); } - private static void assertFullConsumption(Object obj, JsonReader reader) { + private static void assertFullConsumption(@Nullable Object obj, JsonReader reader) { try { if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { throw new JsonSyntaxException("JSON document was not fully consumed."); @@ -1214,7 +1223,7 @@ private static void assertFullConsumption(Object obj, JsonReader reader) { * @see Gson#threadLocalAdapterResults */ static class FutureTypeAdapter extends SerializationDelegatingTypeAdapter { - private TypeAdapter delegate = null; + private @Nullable TypeAdapter delegate = null; public void setDelegate(TypeAdapter typeAdapter) { if (delegate != null) { diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index df2c4acb8e..478e27b3a0 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -51,6 +51,7 @@ import java.util.Objects; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; +import org.jspecify.annotations.Nullable; /** * Use this builder to construct a {@link Gson} instance when you need to set configuration options @@ -92,14 +93,14 @@ public final class GsonBuilder { private static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; // Strictness of `null` is the legacy mode where some Gson APIs are always lenient - private static final Strictness DEFAULT_STRICTNESS = null; + private static final @Nullable Strictness DEFAULT_STRICTNESS = null; private static final FormattingStyle DEFAULT_FORMATTING_STYLE = FormattingStyle.COMPACT; private static final boolean DEFAULT_ESCAPE_HTML = true; private static final boolean DEFAULT_SERIALIZE_NULLS = false; private static final boolean DEFAULT_COMPLEX_MAP_KEYS = false; private static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false; private static final boolean DEFAULT_USE_JDK_UNSAFE = true; - private static final String DEFAULT_DATE_PATTERN = null; + private static final @Nullable String DEFAULT_DATE_PATTERN = null; private static final FieldNamingStrategy DEFAULT_FIELD_NAMING_STRATEGY = FieldNamingPolicy.IDENTITY; private static final ToNumberStrategy DEFAULT_OBJECT_TO_NUMBER_STRATEGY = ToNumberPolicy.DOUBLE; @@ -135,7 +136,7 @@ public final class GsonBuilder { final List hierarchyFactories = new ArrayList<>(); boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; - String datePattern = DEFAULT_DATE_PATTERN; + @Nullable String datePattern = DEFAULT_DATE_PATTERN; int dateStyle = DateFormat.DEFAULT; int timeStyle = DateFormat.DEFAULT; boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; @@ -143,7 +144,7 @@ public final class GsonBuilder { boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML; FormattingStyle formattingStyle = DEFAULT_FORMATTING_STYLE; boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE; - Strictness strictness = DEFAULT_STRICTNESS; + @Nullable Strictness strictness = DEFAULT_STRICTNESS; boolean useJdkUnsafe = DEFAULT_USE_JDK_UNSAFE; ToNumberStrategy objectToNumberStrategy = DEFAULT_OBJECT_TO_NUMBER_STRATEGY; ToNumberStrategy numberToNumberStrategy = DEFAULT_NUMBER_TO_NUMBER_STRATEGY; @@ -635,7 +636,7 @@ public GsonBuilder disableHtmlEscaping() { * @since 1.2 */ @CanIgnoreReturnValue - public GsonBuilder setDateFormat(String pattern) { + public GsonBuilder setDateFormat(@Nullable String pattern) { if (pattern != null) { try { SimpleDateFormat unused = new SimpleDateFormat(pattern); diff --git a/gson/src/main/java/com/google/gson/JsonArray.java b/gson/src/main/java/com/google/gson/JsonArray.java index 10b94c0dc1..8402093d31 100644 --- a/gson/src/main/java/com/google/gson/JsonArray.java +++ b/gson/src/main/java/com/google/gson/JsonArray.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import org.jspecify.annotations.Nullable; /** * A class representing an array type in JSON. An array is a list of {@link JsonElement}s each of @@ -83,7 +84,7 @@ public JsonArray deepCopy() { * @param bool the boolean that needs to be added to the array. * @since 2.4 */ - public void add(Boolean bool) { + public void add(@Nullable Boolean bool) { elements.add(bool == null ? JsonNull.INSTANCE : new JsonPrimitive(bool)); } @@ -93,7 +94,7 @@ public void add(Boolean bool) { * @param character the character that needs to be added to the array. * @since 2.4 */ - public void add(Character character) { + public void add(@Nullable Character character) { elements.add(character == null ? JsonNull.INSTANCE : new JsonPrimitive(character)); } @@ -103,7 +104,7 @@ public void add(Character character) { * @param number the number that needs to be added to the array. * @since 2.4 */ - public void add(Number number) { + public void add(@Nullable Number number) { elements.add(number == null ? JsonNull.INSTANCE : new JsonPrimitive(number)); } @@ -113,7 +114,7 @@ public void add(Number number) { * @param string the string that needs to be added to the array. * @since 2.4 */ - public void add(String string) { + public void add(@Nullable String string) { elements.add(string == null ? JsonNull.INSTANCE : new JsonPrimitive(string)); } @@ -122,7 +123,7 @@ public void add(String string) { * * @param element the element that needs to be added to the array. */ - public void add(JsonElement element) { + public void add(@Nullable JsonElement element) { if (element == null) { element = JsonNull.INSTANCE; } @@ -147,7 +148,7 @@ public void addAll(JsonArray array) { * @throws IndexOutOfBoundsException if the specified index is outside the array bounds */ @CanIgnoreReturnValue - public JsonElement set(int index, JsonElement element) { + public JsonElement set(int index, @Nullable JsonElement element) { return elements.set(index, element == null ? JsonNull.INSTANCE : element); } diff --git a/gson/src/main/java/com/google/gson/JsonObject.java b/gson/src/main/java/com/google/gson/JsonObject.java index 3bde741190..a64cba1688 100644 --- a/gson/src/main/java/com/google/gson/JsonObject.java +++ b/gson/src/main/java/com/google/gson/JsonObject.java @@ -20,6 +20,7 @@ import com.google.gson.internal.LinkedTreeMap; import java.util.Map; import java.util.Set; +import org.jspecify.annotations.Nullable; /** * A class representing an object type in JSON. An object consists of name-value pairs where names @@ -66,7 +67,7 @@ public JsonObject deepCopy() { * @param property name of the member. * @param value the member object. */ - public void add(String property, JsonElement value) { + public void add(String property, @Nullable JsonElement value) { members.put(property, value == null ? JsonNull.INSTANCE : value); } @@ -79,7 +80,7 @@ public void add(String property, JsonElement value) { * @since 1.3 */ @CanIgnoreReturnValue - public JsonElement remove(String property) { + public @Nullable JsonElement remove(String property) { return members.remove(property); } @@ -90,7 +91,7 @@ public JsonElement remove(String property) { * @param property name of the member. * @param value the string value associated with the member. */ - public void addProperty(String property, String value) { + public void addProperty(String property, @Nullable String value) { add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value)); } @@ -101,7 +102,7 @@ public void addProperty(String property, String value) { * @param property name of the member. * @param value the number value associated with the member. */ - public void addProperty(String property, Number value) { + public void addProperty(String property, @Nullable Number value) { add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value)); } @@ -112,7 +113,7 @@ public void addProperty(String property, Number value) { * @param property name of the member. * @param value the boolean value associated with the member. */ - public void addProperty(String property, Boolean value) { + public void addProperty(String property, @Nullable Boolean value) { add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value)); } @@ -123,7 +124,7 @@ public void addProperty(String property, Boolean value) { * @param property name of the member. * @param value the char value associated with the member. */ - public void addProperty(String property, Character value) { + public void addProperty(String property, @Nullable Character value) { add(property, value == null ? JsonNull.INSTANCE : new JsonPrimitive(value)); } @@ -183,7 +184,7 @@ public boolean has(String memberName) { * @param memberName name of the member that is being requested. * @return the member matching the name, or {@code null} if no such member exists. */ - public JsonElement get(String memberName) { + public @Nullable JsonElement get(String memberName) { return members.get(memberName); } @@ -195,7 +196,7 @@ public JsonElement get(String memberName) { * member with this name exists. * @throws ClassCastException if the member is not of type {@code JsonPrimitive}. */ - public JsonPrimitive getAsJsonPrimitive(String memberName) { + public @Nullable JsonPrimitive getAsJsonPrimitive(String memberName) { return (JsonPrimitive) members.get(memberName); } @@ -207,7 +208,7 @@ public JsonPrimitive getAsJsonPrimitive(String memberName) { * member with this name exists. * @throws ClassCastException if the member is not of type {@code JsonArray}. */ - public JsonArray getAsJsonArray(String memberName) { + public @Nullable JsonArray getAsJsonArray(String memberName) { return (JsonArray) members.get(memberName); } @@ -219,7 +220,7 @@ public JsonArray getAsJsonArray(String memberName) { * member with this name exists. * @throws ClassCastException if the member is not of type {@code JsonObject}. */ - public JsonObject getAsJsonObject(String memberName) { + public @Nullable JsonObject getAsJsonObject(String memberName) { return (JsonObject) members.get(memberName); } diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java index e33a839dbd..9337c6cddd 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. @@ -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 T fromJsonTree(@Nullable 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..4e27a711eb 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 @@ -19,5 +19,6 @@ * * @author Inderjeet Singh, Joel Leitch */ +@org.jspecify.annotations.NullMarked @com.google.errorprone.annotations.CheckReturnValue package com.google.gson.annotations; 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/Streams.java b/gson/src/main/java/com/google/gson/internal/Streams.java index 12b8be86ee..cf4402e5b7 100644 --- a/gson/src/main/java/com/google/gson/internal/Streams.java +++ b/gson/src/main/java/com/google/gson/internal/Streams.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.Writer; import java.util.Objects; +import org.jspecify.annotations.Nullable; /** Reads and writes GSON parse trees over streams. */ public final class Streams { @@ -66,7 +67,7 @@ public static JsonElement parse(JsonReader reader) throws JsonParseException { } /** Writes the JSON element to the writer, recursively. */ - public static void write(JsonElement element, JsonWriter writer) throws IOException { + public static void write(@Nullable JsonElement element, JsonWriter writer) throws IOException { JsonElementTypeAdapter.ADAPTER.write(writer, element); } @@ -133,8 +134,8 @@ public Writer append(CharSequence csq, int start, int end) throws IOException { /** A mutable char sequence pointing at a single char[]. */ private static class CurrentWrite implements CharSequence { - private char[] chars; - private String cachedString; + private char @Nullable [] chars; + private @Nullable String cachedString; void setChars(char[] chars) { this.chars = chars; 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..8675fa69e4 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()))) { @@ -63,13 +64,13 @@ public ArrayTypeAdapter( } @Override - public Object read(JsonReader in) throws IOException { + public @Nullable Object read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } - ArrayList list = new ArrayList<>(); + ArrayList<@Nullable E> list = new ArrayList<>(); in.beginArray(); while (in.hasNext()) { E instance = componentTypeAdapter.read(in); @@ -95,7 +96,7 @@ public Object read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, Object array) throws IOException { + public void write(JsonWriter out, @Nullable Object array) throws IOException { if (array == null) { out.nullValue(); return; 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..b377f0d47e 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(); @@ -72,13 +73,13 @@ private static final class Adapter extends TypeAdapter> { } @Override - public Collection read(JsonReader in) throws IOException { + public @Nullable Collection<@Nullable E> read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } - Collection collection = constructor.construct(); + Collection<@Nullable E> collection = constructor.construct(); in.beginArray(); while (in.hasNext()) { E instance = elementTypeAdapter.read(in); @@ -89,7 +90,7 @@ public Collection read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, Collection collection) throws IOException { + public void write(JsonWriter out, @Nullable Collection collection) throws IOException { if (collection == null) { out.nullValue(); return; 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..5c900fbf3b 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 b3dbb680c1..f7ffd95048 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; @@ -111,7 +112,7 @@ private EnumTypeAdapter(Class classOfT) { } @Override - public T read(JsonReader in) throws IOException { + public @Nullable T read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -123,7 +124,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/JavaTimeTypeAdapters.java b/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java index 791f15b44a..217939dfbc 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java +++ b/gson/src/main/java/com/google/gson/internal/bind/JavaTimeTypeAdapters.java @@ -26,6 +26,7 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import org.jspecify.annotations.Nullable; /** * Type adapters for {@code java.time} types. @@ -393,7 +394,7 @@ public void write(JsonWriter out, ZonedDateTime value) throws IOException { static final TypeAdapterFactory JAVA_TIME_FACTORY = new TypeAdapterFactory() { @Override - public TypeAdapter create(Gson gson, TypeToken typeToken) { + public @Nullable TypeAdapter create(Gson gson, TypeToken typeToken) { Class rawType = typeToken.getRawType(); if (!rawType.getName().startsWith("java.time.")) { // Immediately return null so we don't load all these classes when nobody's doing 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..f56cc933ba 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"); } } diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java b/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java index 6590dcff1b..51723541d9 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/JsonElementTypeAdapter.java @@ -30,6 +30,7 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.Map; +import org.jspecify.annotations.Nullable; /** Adapter for {@link JsonElement} and subclasses. */ public class JsonElementTypeAdapter extends TypeAdapter { @@ -41,7 +42,8 @@ private JsonElementTypeAdapter() {} * Tries to begin reading a JSON array or JSON object, returning {@code null} if the next element * is neither of those. */ - private JsonElement tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { + private @Nullable JsonElement tryBeginNesting(JsonReader in, JsonToken peeked) + throws IOException { switch (peeked) { case BEGIN_ARRAY: in.beginArray(); @@ -136,7 +138,7 @@ public JsonElement read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, JsonElement value) throws IOException { + public void write(JsonWriter out, @Nullable JsonElement value) throws IOException { if (value == null || value.isJsonNull()) { out.nullValue(); } else if (value.isJsonPrimitive()) { 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..8f6b10a388 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(); @@ -173,7 +174,7 @@ private final class Adapter extends TypeAdapter> { } @Override - public Map read(JsonReader in) throws IOException { + public @Nullable Map read(JsonReader in) throws IOException { JsonToken peek = in.peek(); if (peek == JsonToken.NULL) { in.nextNull(); @@ -212,7 +213,7 @@ public Map read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, Map map) throws IOException { + public void write(JsonWriter out, @Nullable Map map) throws IOException { if (map == null) { out.nullValue(); return; 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..34de742940 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; } }; @@ -60,7 +61,7 @@ public static TypeAdapterFactory getFactory(ToNumberStrategy toNumberStrategy) { } @Override - public Number read(JsonReader in) throws IOException { + public @Nullable Number read(JsonReader in) throws IOException { JsonToken jsonToken = in.peek(); switch (jsonToken) { case NULL: @@ -76,7 +77,7 @@ public Number read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, Number value) throws IOException { + public void write(JsonWriter out, @Nullable Number value) throws IOException { out.value(value); } } 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..f36bdb01c7 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); } @@ -74,7 +75,7 @@ public static TypeAdapterFactory getFactory(ToNumberStrategy toNumberStrategy) { * Tries to begin reading a JSON array or JSON object, returning {@code null} if the next element * is neither of those. */ - private Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { + private @Nullable Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { switch (peeked) { case BEGIN_ARRAY: in.beginArray(); @@ -88,7 +89,7 @@ private Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOExcepti } /** Reads an {@code Object} which cannot have any nested elements */ - private Object readTerminal(JsonReader in, JsonToken peeked) throws IOException { + private @Nullable Object readTerminal(JsonReader in, JsonToken peeked) throws IOException { switch (peeked) { case STRING: return in.nextString(); @@ -167,7 +168,7 @@ public Object read(JsonReader in) throws IOException { } @Override - public void write(JsonWriter out, Object value) throws IOException { + public void write(JsonWriter out, @Nullable Object value) throws IOException { if (value == null) { out.nullValue(); return; 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..5e2c433486 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)) { @@ -166,7 +167,7 @@ public String toString() { } private static void checkAccessible( - Object object, M member) { + @Nullable Object object, M member) { if (!ReflectionAccessFilterHelper.canAccess( member, Modifier.isStatic(member.getModifiers()) ? null : object)) { String memberDescription = ReflectionHelper.getAccessibleObjectDescription(member, true); @@ -181,7 +182,7 @@ private static void checkAccessible( private BoundField createBoundField( Gson context, Field field, - Method accessor, + @Nullable Method accessor, String serializedName, TypeToken fieldType, boolean serialize, @@ -252,7 +253,7 @@ void write(JsonWriter writer, Object source) throws IOException, IllegalAccessEx } @Override - void readIntoArray(JsonReader reader, int index, Object[] target) + void readIntoArray(JsonReader reader, int index, @Nullable Object[] target) throws IOException, JsonParseException { Object fieldValue = typeAdapter.read(reader); if (fieldValue == null && isPrimitive) { @@ -479,7 +480,7 @@ public abstract static class Adapter 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(); return; 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..8e74a4d824 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 852ae56c5b..9da3b9b5a3 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 @@ -52,6 +52,7 @@ import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; +import org.jspecify.annotations.Nullable; /** * Type adapters for basic types. More complex adapters exist as separate classes in the enclosing @@ -946,7 +947,7 @@ interface FactorySupplier { TypeAdapterFactory get(); } - public static TypeAdapterFactory javaTimeTypeAdapterFactory() { + public static @Nullable TypeAdapterFactory javaTimeTypeAdapterFactory() { try { Class javaTimeTypeAdapterFactoryClass = Class.forName("com.google.gson.internal.bind.JavaTimeTypeAdapters"); @@ -964,7 +965,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; } }; @@ -975,7 +976,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; } @@ -992,7 +993,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; } @@ -1016,7 +1017,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; } 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..b8929d0191 --- /dev/null +++ b/gson/src/main/java/com/google/gson/internal/bind/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2008 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. + */ + +/** Internal type adapters and factories used by Gson. */ +@org.jspecify.annotations.NullMarked +package com.google.gson.internal.bind; 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..0308c84bed 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 @@ -20,5 +20,6 @@ * * @author Inderjeet Singh, Joel Leitch, Jesse Wilson */ +@org.jspecify.annotations.NullMarked @com.google.errorprone.annotations.CheckReturnValue 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..d4429ef4aa --- /dev/null +++ b/gson/src/main/java/com/google/gson/internal/reflect/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 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. + */ + +/** Reflection helpers used internally by Gson. */ +@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..a4fb3bf6d7 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..24c48e0153 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