From 535d5b9c596301fbbba192d1530c65e75ce06bbd Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Fri, 29 May 2020 10:08:38 +0530 Subject: [PATCH 1/8] Adjust build system to run checker --- gson/pom.xml | 35 ++++++++++++++++++++++++++++- gson/src/main/java/module-info.java | 1 + pom.xml | 31 ++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/gson/pom.xml b/gson/pom.xml index cf32962ad0..2e9a151dec 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -11,15 +11,48 @@ Gson + + org.checkerframework + checker + 3.4.0 + junit junit test - + + + maven-compiler-plugin + 3.8.1 + + + **/gson/GsonBuilder.java + module-info.java + + 11 + + 10000 + 10000 + + + + org.checkerframework + checker + 3.4.0 + + + + org.checkerframework.checker.nullness.NullnessChecker + + + -AprintErrorStack + + + org.apache.maven.plugins maven-javadoc-plugin diff --git a/gson/src/main/java/module-info.java b/gson/src/main/java/module-info.java index 161fbdba7f..a42440cb22 100644 --- a/gson/src/main/java/module-info.java +++ b/gson/src/main/java/module-info.java @@ -9,4 +9,5 @@ exports com.google.gson.stream; requires transitive java.sql; + requires org.checkerframework.checker; } diff --git a/pom.xml b/pom.xml index 1fb47fcde4..d4a826441d 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,16 @@ 4.12 test + + org.checkerframework + checker + 3.4.0 + + + org.checkerframework + jdk11 + 3.4.0 + @@ -71,7 +81,10 @@ 9 - 9 + + **/gson/GsonBuilder.java + module-info.java + @@ -90,8 +103,20 @@ [1.5,9) - 1.6 - 1.6 + 11 + + + 10000 + 10000 + + + org.checkerframework.checker.nullness.NullnessChecker + + + + -J- -add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED + -AprintErrorStack + From bd4ece5810ca3bebd5fae76834e206c4cc82ea1e Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Mon, 1 Jun 2020 10:51:20 +0530 Subject: [PATCH 2/8] Added annotations for nullness in gson/ --- gson/pom.xml | 7 ++- gson/src/main/java/com/google/gson/Gson.java | 47 +++++++++++-------- .../java/com/google/gson/GsonBuilder.java | 5 +- .../main/java/com/google/gson/JsonObject.java | 13 ++--- .../java/com/google/gson/TypeAdapter.java | 11 +++-- pom.xml | 7 ++- 6 files changed, 53 insertions(+), 37 deletions(-) diff --git a/gson/pom.xml b/gson/pom.xml index 2e9a151dec..5bea2924e5 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -30,8 +30,11 @@ 3.8.1 - **/gson/GsonBuilder.java - module-info.java + **/gson/Gson.java + **/gson/JsonObject.java + **/gson/GsonBuilder.java + **/gson/TypeAdapter.java + module-info.java 11 diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 27f3ee9246..af6302825c 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -57,6 +57,7 @@ import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import com.google.gson.stream.MalformedJsonException; +import org.checkerframework.checker.nullness.qual.Nullable; /** * This is the main class for using Gson. Gson is typically used by first constructing a @@ -121,8 +122,8 @@ public final class Gson { * lookup would stack overflow. We cheat by returning a proxy type adapter. * The proxy is wired up once the initial adapter has been created. */ - private final ThreadLocal, FutureTypeAdapter>> calls - = new ThreadLocal, FutureTypeAdapter>>(); + private final ThreadLocal<@Nullable Map, FutureTypeAdapter>> calls + = new ThreadLocal<@Nullable Map, FutureTypeAdapter>>(); private final Map, TypeAdapter> typeTokenCache = new ConcurrentHashMap, TypeAdapter>(); @@ -141,7 +142,7 @@ public final class Gson { final boolean prettyPrinting; final boolean lenient; final boolean serializeSpecialFloatingPointValues; - final String datePattern; + final @Nullable String datePattern; final int dateStyle; final int timeStyle; final LongSerializationPolicy longSerializationPolicy; @@ -192,11 +193,13 @@ public Gson() { Collections.emptyList()); } + /*dangerous to call an instance method inside a constructor, framework could identify #1 and #2 out of 4 such errors*/ + @SuppressWarnings("method.invocation.invalid") Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy, Map> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues, - LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle, + LongSerializationPolicy longSerializationPolicy, @Nullable String datePattern, int dateStyle, int timeStyle, List builderFactories, List builderHierarchyFactories, List factoriesToBeAdded) { @@ -239,9 +242,9 @@ public Gson() { TypeAdapter longAdapter = longAdapter(longSerializationPolicy); factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); factories.add(TypeAdapters.newFactory(double.class, Double.class, - doubleAdapter(serializeSpecialFloatingPointValues))); + doubleAdapter(serializeSpecialFloatingPointValues))); //#1 factories.add(TypeAdapters.newFactory(float.class, Float.class, - floatAdapter(serializeSpecialFloatingPointValues))); + floatAdapter(serializeSpecialFloatingPointValues))); //#2 factories.add(TypeAdapters.NUMBER_FACTORY); factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY); factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY); @@ -311,7 +314,7 @@ private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointV return TypeAdapters.DOUBLE; } return new TypeAdapter() { - @Override public Double read(JsonReader in) throws IOException { + @Override public @Nullable Double read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -335,7 +338,7 @@ private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointVa return TypeAdapters.FLOAT; } return new TypeAdapter() { - @Override public Float read(JsonReader in) throws IOException { + @Override public @Nullable Float read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -367,7 +370,7 @@ private static TypeAdapter longAdapter(LongSerializationPolicy longSeria return TypeAdapters.LONG; } return new TypeAdapter() { - @Override public Number read(JsonReader in) throws IOException { + @Override public @Nullable Number read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -389,8 +392,10 @@ private static TypeAdapter atomicLongAdapter(final TypeAdapter atomicLongArrayAdapter(final TypeAda } out.endArray(); } + /*in.hasNext() ensures read(in) doesnt return null in #4*/ + @SuppressWarnings({"dereference.of.nullable", "argument.type.incompatible"}) @Override public AtomicLongArray read(JsonReader in) throws IOException { List list = new ArrayList(); in.beginArray(); - while (in.hasNext()) { + while (in.hasNext()) { //#4 long value = longAdapter.read(in).longValue(); list.add(value); } @@ -813,7 +820,7 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce * @throws JsonSyntaxException if json is not a valid representation for an object of type * classOfT */ - public T fromJson(String json, Class classOfT) throws JsonSyntaxException { + public @Nullable T fromJson(String json, Class classOfT) throws JsonSyntaxException { Object object = fromJson(json, (Type) classOfT); return Primitives.wrap(classOfT).cast(object); } @@ -838,7 +845,7 @@ public T fromJson(String json, Class classOfT) throws JsonSyntaxException * @throws JsonSyntaxException if json is not a valid representation for an object of type */ @SuppressWarnings("unchecked") - public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { + public @Nullable T fromJson(@Nullable String json, Type typeOfT) throws JsonSyntaxException { if (json == null) { return null; } @@ -865,7 +872,7 @@ public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { * @throws JsonSyntaxException if json is not a valid representation for an object of type * @since 1.2 */ - public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { + public @Nullable T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { JsonReader jsonReader = newJsonReader(json); Object object = fromJson(jsonReader, classOfT); assertFullConsumption(object, jsonReader); @@ -899,7 +906,7 @@ public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyn return object; } - 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 JsonIOException("JSON document was not fully consumed."); @@ -920,7 +927,7 @@ private static void assertFullConsumption(Object obj, JsonReader reader) { * @throws JsonSyntaxException if json is not a valid representation for an object of type */ @SuppressWarnings("unchecked") - public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { + public @Nullable T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { boolean isEmpty = true; boolean oldLenient = reader.isLenient(); reader.setLenient(true); @@ -971,7 +978,7 @@ public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, J * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT * @since 1.3 */ - public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { + public @Nullable T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { Object object = fromJson(json, (Type) classOfT); return Primitives.wrap(classOfT).cast(object); } @@ -996,7 +1003,7 @@ public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxExce * @since 1.3 */ @SuppressWarnings("unchecked") - public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { + public @Nullable T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { if (json == null) { return null; } @@ -1004,7 +1011,7 @@ public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException } static class FutureTypeAdapter extends TypeAdapter { - private TypeAdapter delegate; + private @Nullable TypeAdapter delegate; public void setDelegate(TypeAdapter typeAdapter) { if (delegate != null) { @@ -1013,7 +1020,7 @@ public void setDelegate(TypeAdapter typeAdapter) { delegate = typeAdapter; } - @Override public T read(JsonReader in) throws IOException { + @Override public @Nullable T read(JsonReader in) throws IOException { if (delegate == null) { throw new IllegalStateException(); } diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index b97be452be..1bba325052 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -40,6 +40,7 @@ import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT; import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS; import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES; +import org.checkerframework.checker.nullness.qual.Nullable; /** *

Use this builder to construct a {@link Gson} instance when you need to set configuration @@ -85,7 +86,7 @@ public final class GsonBuilder { /** tree-style hierarchy factories. These come after factories for backwards compatibility. */ private final List hierarchyFactories = new ArrayList(); private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; - private String datePattern; + private @Nullable String datePattern; private int dateStyle = DateFormat.DEFAULT; private int timeStyle = DateFormat.DEFAULT; private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; @@ -603,7 +604,7 @@ public Gson create() { } @SuppressWarnings("unchecked") - private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, + private void addTypeAdaptersForDate(@Nullable String datePattern, int dateStyle, int timeStyle, List factories) { DefaultDateTypeAdapter dateTypeAdapter; TypeAdapter timestampTypeAdapter; diff --git a/gson/src/main/java/com/google/gson/JsonObject.java b/gson/src/main/java/com/google/gson/JsonObject.java index d4feb96e84..b4bc672163 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 java.util.Map; import java.util.Set; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A class representing an object type in Json. An object consists of name-value pairs where names @@ -65,7 +66,7 @@ public void add(String property, JsonElement value) { * @return the {@link JsonElement} object that is being removed. * @since 1.3 */ - public JsonElement remove(String property) { + public @Nullable JsonElement remove(String property) { return members.remove(property); } @@ -158,7 +159,7 @@ public boolean has(String memberName) { * @param memberName name of the member that is being requested. * @return the member matching the name. Null if no such member exists. */ - public JsonElement get(String memberName) { + public @Nullable JsonElement get(String memberName) { return members.get(memberName); } @@ -168,7 +169,7 @@ public JsonElement get(String memberName) { * @param memberName name of the member being requested. * @return the JsonPrimitive corresponding to the specified member. */ - public JsonPrimitive getAsJsonPrimitive(String memberName) { + public @Nullable JsonPrimitive getAsJsonPrimitive(String memberName) { return (JsonPrimitive) members.get(memberName); } @@ -178,7 +179,7 @@ public JsonPrimitive getAsJsonPrimitive(String memberName) { * @param memberName name of the member being requested. * @return the JsonArray corresponding to the specified member. */ - public JsonArray getAsJsonArray(String memberName) { + public @Nullable JsonArray getAsJsonArray(String memberName) { return (JsonArray) members.get(memberName); } @@ -188,12 +189,12 @@ public JsonArray getAsJsonArray(String memberName) { * @param memberName name of the member being requested. * @return the JsonObject corresponding to the specified member. */ - public JsonObject getAsJsonObject(String memberName) { + public @Nullable JsonObject getAsJsonObject(String memberName) { return (JsonObject) members.get(memberName); } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { return (o == this) || (o instanceof JsonObject && ((JsonObject) o).members.equals(members)); } diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java index 4646d271d7..b5d02006c1 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.StringReader; import java.io.StringWriter; import java.io.Writer; +import org.checkerframework.checker.nullness.qual.*; /** * Converts Java objects to and from JSON. @@ -191,7 +192,7 @@ public final TypeAdapter nullSafe() { TypeAdapter.this.write(out, value); } } - @Override public T read(JsonReader reader) throws IOException { + @Override public @Nullable T read(JsonReader reader) throws IOException { if (reader.peek() == JsonToken.NULL) { reader.nextNull(); return null; @@ -244,7 +245,7 @@ public final JsonElement toJsonTree(T value) { * * @return the converted Java object. May be 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. Unlike Gson's @@ -255,7 +256,7 @@ public final JsonElement toJsonTree(T value) { * @return the converted Java object. May be 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); } @@ -269,7 +270,7 @@ public final T fromJson(Reader in) throws IOException { * @return the converted Java object. May be 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)); } @@ -279,7 +280,7 @@ public final T fromJson(String json) throws IOException { * @param jsonTree the Java object to convert. May be {@link JsonNull}. * @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); diff --git a/pom.xml b/pom.xml index d4a826441d..ee6dbd9fa1 100644 --- a/pom.xml +++ b/pom.xml @@ -82,8 +82,11 @@ 9 + **/gson/Gson.java + **/gson/JsonObject.java **/gson/GsonBuilder.java - module-info.java + **/gson/TypeAdapter.java + module-info.java @@ -94,7 +97,7 @@ - module-info.java + From 46bb5a3201ed7247e0c633ef3d265ac4cbb3a59a Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Thu, 4 Jun 2020 08:58:58 +0530 Subject: [PATCH 3/8] Add remaining annotations to gson/ --- gson/pom.xml | 9 +++------ .../java/com/google/gson/DefaultDateTypeAdapter.java | 3 ++- gson/src/main/java/com/google/gson/FieldAttributes.java | 5 +++-- gson/src/main/java/com/google/gson/JsonArray.java | 8 +++++--- gson/src/main/java/com/google/gson/JsonNull.java | 3 ++- gson/src/main/java/com/google/gson/JsonPrimitive.java | 3 ++- pom.xml | 9 +++------ 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/gson/pom.xml b/gson/pom.xml index 5bea2924e5..f7a075a346 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -29,13 +29,10 @@ maven-compiler-plugin 3.8.1 - - **/gson/Gson.java - **/gson/JsonObject.java - **/gson/GsonBuilder.java - **/gson/TypeAdapter.java + + **/gson/*.java module-info.java - + 11 10000 diff --git a/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java b/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java index 522963795a..77a44e2dcb 100644 --- a/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java @@ -33,6 +33,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; +import org.checkerframework.checker.nullness.qual.Nullable; /** * This type adapter supports three subclasses of date: Date, Timestamp, and @@ -120,7 +121,7 @@ public void write(JsonWriter out, Date value) throws IOException { } @Override - public Date read(JsonReader in) throws IOException { + public @Nullable Date read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; diff --git a/gson/src/main/java/com/google/gson/FieldAttributes.java b/gson/src/main/java/com/google/gson/FieldAttributes.java index 4ee906a60a..75d968e0d8 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.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A data object that stores attributes of a field. @@ -107,7 +108,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); } @@ -146,7 +147,7 @@ public boolean hasModifier(int modifier) { * @throws IllegalAccessException * @throws IllegalArgumentException */ - Object get(Object instance) throws IllegalAccessException { + @Nullable Object get(Object instance) throws IllegalAccessException { return field.get(instance); } diff --git a/gson/src/main/java/com/google/gson/JsonArray.java b/gson/src/main/java/com/google/gson/JsonArray.java index 4b61a90969..ad3826f627 100644 --- a/gson/src/main/java/com/google/gson/JsonArray.java +++ b/gson/src/main/java/com/google/gson/JsonArray.java @@ -22,6 +22,8 @@ import java.util.Iterator; import java.util.List; +import org.checkerframework.checker.nullness.qual.Nullable; + /** * A class representing an array type in Json. An array is a list of {@link JsonElement}s each of * which can be of a different type. This is an ordered list, meaning that the order in which @@ -39,7 +41,7 @@ public final class JsonArray extends JsonElement implements Iterable(); } - + public JsonArray(int capacity) { elements = new ArrayList(capacity); } @@ -171,7 +173,7 @@ public boolean contains(JsonElement element) { public int size() { return elements.size(); } - + /** * Returns true if the array is empty * @@ -382,7 +384,7 @@ public boolean getAsBoolean() { } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements)); } diff --git a/gson/src/main/java/com/google/gson/JsonNull.java b/gson/src/main/java/com/google/gson/JsonNull.java index 67cb9325b2..069257b819 100644 --- a/gson/src/main/java/com/google/gson/JsonNull.java +++ b/gson/src/main/java/com/google/gson/JsonNull.java @@ -16,6 +16,7 @@ package com.google.gson; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A class representing a Json {@code null} value. * @@ -61,7 +62,7 @@ public int hashCode() { * All instances of JsonNull are the same */ @Override - public boolean equals(Object other) { + public boolean equals(@Nullable Object other) { return this == other || other instanceof JsonNull; } } diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java index 5e95d5a82b..112df9bff8 100644 --- a/gson/src/main/java/com/google/gson/JsonPrimitive.java +++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java @@ -22,6 +22,7 @@ import com.google.gson.internal.LazilyParsedNumber; +import org.checkerframework.checker.nullness.qual.Nullable; /** * A class representing a Json primitive value. A primitive value * is either a String, a Java primitive, or a Java primitive @@ -256,7 +257,7 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } diff --git a/pom.xml b/pom.xml index ee6dbd9fa1..ed0ea4d920 100644 --- a/pom.xml +++ b/pom.xml @@ -81,13 +81,10 @@ 9 - - **/gson/Gson.java - **/gson/JsonObject.java - **/gson/GsonBuilder.java - **/gson/TypeAdapter.java + + **/gson/*.java module-info.java - + From 2354aa4ff2fd2748fd3004ee0a502e87eeea4524 Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Mon, 15 Jun 2020 09:30:38 +0530 Subject: [PATCH 4/8] Remove nullness annotations from master --- .../java/com/google/gson/FieldAttributes.java | 5 +- gson/src/main/java/com/google/gson/Gson.java | 47 ++++++++----------- .../java/com/google/gson/GsonBuilder.java | 5 +- .../main/java/com/google/gson/JsonArray.java | 8 ++-- .../main/java/com/google/gson/JsonNull.java | 3 +- .../main/java/com/google/gson/JsonObject.java | 13 +++-- .../java/com/google/gson/JsonPrimitive.java | 3 +- .../java/com/google/gson/TypeAdapter.java | 11 ++--- 8 files changed, 40 insertions(+), 55 deletions(-) diff --git a/gson/src/main/java/com/google/gson/FieldAttributes.java b/gson/src/main/java/com/google/gson/FieldAttributes.java index 75d968e0d8..4ee906a60a 100644 --- a/gson/src/main/java/com/google/gson/FieldAttributes.java +++ b/gson/src/main/java/com/google/gson/FieldAttributes.java @@ -22,7 +22,6 @@ import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collection; -import org.checkerframework.checker.nullness.qual.Nullable; /** * A data object that stores attributes of a field. @@ -108,7 +107,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 @Nullable T getAnnotation(Class annotation) { + public T getAnnotation(Class annotation) { return field.getAnnotation(annotation); } @@ -147,7 +146,7 @@ public boolean hasModifier(int modifier) { * @throws IllegalAccessException * @throws IllegalArgumentException */ - @Nullable Object get(Object instance) throws IllegalAccessException { + Object get(Object instance) throws IllegalAccessException { return field.get(instance); } diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index af6302825c..27f3ee9246 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -57,7 +57,6 @@ import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import com.google.gson.stream.MalformedJsonException; -import org.checkerframework.checker.nullness.qual.Nullable; /** * This is the main class for using Gson. Gson is typically used by first constructing a @@ -122,8 +121,8 @@ public final class Gson { * lookup would stack overflow. We cheat by returning a proxy type adapter. * The proxy is wired up once the initial adapter has been created. */ - private final ThreadLocal<@Nullable Map, FutureTypeAdapter>> calls - = new ThreadLocal<@Nullable Map, FutureTypeAdapter>>(); + private final ThreadLocal, FutureTypeAdapter>> calls + = new ThreadLocal, FutureTypeAdapter>>(); private final Map, TypeAdapter> typeTokenCache = new ConcurrentHashMap, TypeAdapter>(); @@ -142,7 +141,7 @@ public final class Gson { final boolean prettyPrinting; final boolean lenient; final boolean serializeSpecialFloatingPointValues; - final @Nullable String datePattern; + final String datePattern; final int dateStyle; final int timeStyle; final LongSerializationPolicy longSerializationPolicy; @@ -193,13 +192,11 @@ public Gson() { Collections.emptyList()); } - /*dangerous to call an instance method inside a constructor, framework could identify #1 and #2 out of 4 such errors*/ - @SuppressWarnings("method.invocation.invalid") Gson(Excluder excluder, FieldNamingStrategy fieldNamingStrategy, Map> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues, - LongSerializationPolicy longSerializationPolicy, @Nullable String datePattern, int dateStyle, + LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle, int timeStyle, List builderFactories, List builderHierarchyFactories, List factoriesToBeAdded) { @@ -242,9 +239,9 @@ public Gson() { TypeAdapter longAdapter = longAdapter(longSerializationPolicy); factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); factories.add(TypeAdapters.newFactory(double.class, Double.class, - doubleAdapter(serializeSpecialFloatingPointValues))); //#1 + doubleAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.newFactory(float.class, Float.class, - floatAdapter(serializeSpecialFloatingPointValues))); //#2 + floatAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.NUMBER_FACTORY); factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY); factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY); @@ -314,7 +311,7 @@ private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointV return TypeAdapters.DOUBLE; } return new TypeAdapter() { - @Override public @Nullable Double read(JsonReader in) throws IOException { + @Override public Double read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -338,7 +335,7 @@ private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointVa return TypeAdapters.FLOAT; } return new TypeAdapter() { - @Override public @Nullable Float read(JsonReader in) throws IOException { + @Override public Float read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -370,7 +367,7 @@ private static TypeAdapter longAdapter(LongSerializationPolicy longSeria return TypeAdapters.LONG; } return new TypeAdapter() { - @Override public @Nullable Number read(JsonReader in) throws IOException { + @Override public Number read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; @@ -392,10 +389,8 @@ private static TypeAdapter atomicLongAdapter(final TypeAdapter atomicLongArrayAdapter(final TypeAda } out.endArray(); } - /*in.hasNext() ensures read(in) doesnt return null in #4*/ - @SuppressWarnings({"dereference.of.nullable", "argument.type.incompatible"}) @Override public AtomicLongArray read(JsonReader in) throws IOException { List list = new ArrayList(); in.beginArray(); - while (in.hasNext()) { //#4 + while (in.hasNext()) { long value = longAdapter.read(in).longValue(); list.add(value); } @@ -820,7 +813,7 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce * @throws JsonSyntaxException if json is not a valid representation for an object of type * classOfT */ - public @Nullable T fromJson(String json, Class classOfT) throws JsonSyntaxException { + public T fromJson(String json, Class classOfT) throws JsonSyntaxException { Object object = fromJson(json, (Type) classOfT); return Primitives.wrap(classOfT).cast(object); } @@ -845,7 +838,7 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce * @throws JsonSyntaxException if json is not a valid representation for an object of type */ @SuppressWarnings("unchecked") - public @Nullable T fromJson(@Nullable String json, Type typeOfT) throws JsonSyntaxException { + public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { if (json == null) { return null; } @@ -872,7 +865,7 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce * @throws JsonSyntaxException if json is not a valid representation for an object of type * @since 1.2 */ - public @Nullable T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { + public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { JsonReader jsonReader = newJsonReader(json); Object object = fromJson(jsonReader, classOfT); assertFullConsumption(object, jsonReader); @@ -906,7 +899,7 @@ public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyn return object; } - private static void assertFullConsumption(@Nullable Object obj, JsonReader reader) { + private static void assertFullConsumption(Object obj, JsonReader reader) { try { if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { throw new JsonIOException("JSON document was not fully consumed."); @@ -927,7 +920,7 @@ private static void assertFullConsumption(@Nullable Object obj, JsonReader reade * @throws JsonSyntaxException if json is not a valid representation for an object of type */ @SuppressWarnings("unchecked") - public @Nullable T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { + public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { boolean isEmpty = true; boolean oldLenient = reader.isLenient(); reader.setLenient(true); @@ -978,7 +971,7 @@ private static void assertFullConsumption(@Nullable Object obj, JsonReader reade * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT * @since 1.3 */ - public @Nullable T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { + public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { Object object = fromJson(json, (Type) classOfT); return Primitives.wrap(classOfT).cast(object); } @@ -1003,7 +996,7 @@ private static void assertFullConsumption(@Nullable Object obj, JsonReader reade * @since 1.3 */ @SuppressWarnings("unchecked") - public @Nullable T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { + public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { if (json == null) { return null; } @@ -1011,7 +1004,7 @@ private static void assertFullConsumption(@Nullable Object obj, JsonReader reade } static class FutureTypeAdapter extends TypeAdapter { - private @Nullable TypeAdapter delegate; + private TypeAdapter delegate; public void setDelegate(TypeAdapter typeAdapter) { if (delegate != null) { @@ -1020,7 +1013,7 @@ public void setDelegate(TypeAdapter typeAdapter) { delegate = typeAdapter; } - @Override public @Nullable T read(JsonReader in) throws IOException { + @Override public T read(JsonReader in) throws IOException { if (delegate == null) { throw new IllegalStateException(); } diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index 1bba325052..b97be452be 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -40,7 +40,6 @@ import static com.google.gson.Gson.DEFAULT_PRETTY_PRINT; import static com.google.gson.Gson.DEFAULT_SERIALIZE_NULLS; import static com.google.gson.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES; -import org.checkerframework.checker.nullness.qual.Nullable; /** *

Use this builder to construct a {@link Gson} instance when you need to set configuration @@ -86,7 +85,7 @@ public final class GsonBuilder { /** tree-style hierarchy factories. These come after factories for backwards compatibility. */ private final List hierarchyFactories = new ArrayList(); private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; - private @Nullable String datePattern; + private String datePattern; private int dateStyle = DateFormat.DEFAULT; private int timeStyle = DateFormat.DEFAULT; private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; @@ -604,7 +603,7 @@ public Gson create() { } @SuppressWarnings("unchecked") - private void addTypeAdaptersForDate(@Nullable String datePattern, int dateStyle, int timeStyle, + private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, List factories) { DefaultDateTypeAdapter dateTypeAdapter; TypeAdapter timestampTypeAdapter; diff --git a/gson/src/main/java/com/google/gson/JsonArray.java b/gson/src/main/java/com/google/gson/JsonArray.java index ad3826f627..4b61a90969 100644 --- a/gson/src/main/java/com/google/gson/JsonArray.java +++ b/gson/src/main/java/com/google/gson/JsonArray.java @@ -22,8 +22,6 @@ import java.util.Iterator; import java.util.List; -import org.checkerframework.checker.nullness.qual.Nullable; - /** * A class representing an array type in Json. An array is a list of {@link JsonElement}s each of * which can be of a different type. This is an ordered list, meaning that the order in which @@ -41,7 +39,7 @@ public final class JsonArray extends JsonElement implements Iterable(); } - + public JsonArray(int capacity) { elements = new ArrayList(capacity); } @@ -173,7 +171,7 @@ public boolean contains(JsonElement element) { public int size() { return elements.size(); } - + /** * Returns true if the array is empty * @@ -384,7 +382,7 @@ public boolean getAsBoolean() { } @Override - public boolean equals(@Nullable Object o) { + public boolean equals(Object o) { return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements)); } diff --git a/gson/src/main/java/com/google/gson/JsonNull.java b/gson/src/main/java/com/google/gson/JsonNull.java index 069257b819..67cb9325b2 100644 --- a/gson/src/main/java/com/google/gson/JsonNull.java +++ b/gson/src/main/java/com/google/gson/JsonNull.java @@ -16,7 +16,6 @@ package com.google.gson; -import org.checkerframework.checker.nullness.qual.Nullable; /** * A class representing a Json {@code null} value. * @@ -62,7 +61,7 @@ public int hashCode() { * All instances of JsonNull are the same */ @Override - public boolean equals(@Nullable Object other) { + public boolean equals(Object other) { return this == other || other instanceof JsonNull; } } diff --git a/gson/src/main/java/com/google/gson/JsonObject.java b/gson/src/main/java/com/google/gson/JsonObject.java index b4bc672163..d4feb96e84 100644 --- a/gson/src/main/java/com/google/gson/JsonObject.java +++ b/gson/src/main/java/com/google/gson/JsonObject.java @@ -20,7 +20,6 @@ import java.util.Map; import java.util.Set; -import org.checkerframework.checker.nullness.qual.Nullable; /** * A class representing an object type in Json. An object consists of name-value pairs where names @@ -66,7 +65,7 @@ public void add(String property, JsonElement value) { * @return the {@link JsonElement} object that is being removed. * @since 1.3 */ - public @Nullable JsonElement remove(String property) { + public JsonElement remove(String property) { return members.remove(property); } @@ -159,7 +158,7 @@ public boolean has(String memberName) { * @param memberName name of the member that is being requested. * @return the member matching the name. Null if no such member exists. */ - public @Nullable JsonElement get(String memberName) { + public JsonElement get(String memberName) { return members.get(memberName); } @@ -169,7 +168,7 @@ public boolean has(String memberName) { * @param memberName name of the member being requested. * @return the JsonPrimitive corresponding to the specified member. */ - public @Nullable JsonPrimitive getAsJsonPrimitive(String memberName) { + public JsonPrimitive getAsJsonPrimitive(String memberName) { return (JsonPrimitive) members.get(memberName); } @@ -179,7 +178,7 @@ public boolean has(String memberName) { * @param memberName name of the member being requested. * @return the JsonArray corresponding to the specified member. */ - public @Nullable JsonArray getAsJsonArray(String memberName) { + public JsonArray getAsJsonArray(String memberName) { return (JsonArray) members.get(memberName); } @@ -189,12 +188,12 @@ public boolean has(String memberName) { * @param memberName name of the member being requested. * @return the JsonObject corresponding to the specified member. */ - public @Nullable JsonObject getAsJsonObject(String memberName) { + public JsonObject getAsJsonObject(String memberName) { return (JsonObject) members.get(memberName); } @Override - public boolean equals(@Nullable Object o) { + public boolean equals(Object o) { return (o == this) || (o instanceof JsonObject && ((JsonObject) o).members.equals(members)); } diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java index 112df9bff8..5e95d5a82b 100644 --- a/gson/src/main/java/com/google/gson/JsonPrimitive.java +++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java @@ -22,7 +22,6 @@ import com.google.gson.internal.LazilyParsedNumber; -import org.checkerframework.checker.nullness.qual.Nullable; /** * A class representing a Json primitive value. A primitive value * is either a String, a Java primitive, or a Java primitive @@ -257,7 +256,7 @@ public int hashCode() { } @Override - public boolean equals(@Nullable Object obj) { + public boolean equals(Object obj) { if (this == obj) { return true; } diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java index b5d02006c1..4646d271d7 100644 --- a/gson/src/main/java/com/google/gson/TypeAdapter.java +++ b/gson/src/main/java/com/google/gson/TypeAdapter.java @@ -26,7 +26,6 @@ import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; -import org.checkerframework.checker.nullness.qual.*; /** * Converts Java objects to and from JSON. @@ -192,7 +191,7 @@ public final TypeAdapter nullSafe() { TypeAdapter.this.write(out, value); } } - @Override public @Nullable T read(JsonReader reader) throws IOException { + @Override public T read(JsonReader reader) throws IOException { if (reader.peek() == JsonToken.NULL) { reader.nextNull(); return null; @@ -245,7 +244,7 @@ public final JsonElement toJsonTree(T value) { * * @return the converted Java object. May be null. */ - public abstract @Nullable T read(JsonReader in) throws IOException; + public abstract T read(JsonReader in) throws IOException; /** * Converts the JSON document in {@code in} to a Java object. Unlike Gson's @@ -256,7 +255,7 @@ public final JsonElement toJsonTree(T value) { * @return the converted Java object. May be null. * @since 2.2 */ - public final @Nullable T fromJson(Reader in) throws IOException { + public final T fromJson(Reader in) throws IOException { JsonReader reader = new JsonReader(in); return read(reader); } @@ -270,7 +269,7 @@ public final JsonElement toJsonTree(T value) { * @return the converted Java object. May be null. * @since 2.2 */ - public final @Nullable T fromJson(String json) throws IOException { + public final T fromJson(String json) throws IOException { return fromJson(new StringReader(json)); } @@ -280,7 +279,7 @@ public final JsonElement toJsonTree(T value) { * @param jsonTree the Java object to convert. May be {@link JsonNull}. * @since 2.2 */ - public final @Nullable T fromJsonTree(JsonElement jsonTree) { + public final T fromJsonTree(JsonElement jsonTree) { try { JsonReader jsonReader = new JsonTreeReader(jsonTree); return read(jsonReader); From 993d4bc16815012c618e315aab36787e8513c7a5 Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Mon, 29 Jun 2020 10:14:34 +0530 Subject: [PATCH 5/8] add interning annotations --- .../main/java/com/google/gson/JsonArray.java | 4 ++ .../main/java/com/google/gson/JsonNull.java | 4 ++ .../main/java/com/google/gson/JsonObject.java | 4 ++ .../com/google/gson/TypeAdapterFactory.java | 3 +- .../com/google/gson/internal/$Gson$Types.java | 23 ++++++++---- .../gson/internal/LinkedHashTreeMap.java | 37 +++++++++++++++---- .../google/gson/internal/LinkedTreeMap.java | 33 +++++++++++++---- .../gson/internal/bind/JsonTreeReader.java | 6 ++- .../bind/ReflectiveTypeAdapterFactory.java | 12 +++++- .../bind/TypeAdapterRuntimeTypeWrapper.java | 9 +++-- 10 files changed, 104 insertions(+), 31 deletions(-) diff --git a/gson/src/main/java/com/google/gson/JsonArray.java b/gson/src/main/java/com/google/gson/JsonArray.java index 4b61a90969..82f16a0549 100644 --- a/gson/src/main/java/com/google/gson/JsonArray.java +++ b/gson/src/main/java/com/google/gson/JsonArray.java @@ -381,6 +381,10 @@ public boolean getAsBoolean() { throw new IllegalStateException(); } + /*The equals function defined below is to compare two non-interned object + and only one of the condition to determine they are equal is a reference + equality test therefore its usage is safe*/ + @SuppressWarnings("not.interned") @Override public boolean equals(Object o) { return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements)); diff --git a/gson/src/main/java/com/google/gson/JsonNull.java b/gson/src/main/java/com/google/gson/JsonNull.java index 67cb9325b2..952eab545b 100644 --- a/gson/src/main/java/com/google/gson/JsonNull.java +++ b/gson/src/main/java/com/google/gson/JsonNull.java @@ -60,6 +60,10 @@ public int hashCode() { /** * All instances of JsonNull are the same */ + /*The equals function defined below is to compare two non-interned object + and only one of the condition to determine they are equal is a reference + equality test therefore its usage is safe*/ + @SuppressWarnings("not.interned") @Override public boolean equals(Object other) { return this == other || other instanceof JsonNull; diff --git a/gson/src/main/java/com/google/gson/JsonObject.java b/gson/src/main/java/com/google/gson/JsonObject.java index d4feb96e84..dc4a4f9f55 100644 --- a/gson/src/main/java/com/google/gson/JsonObject.java +++ b/gson/src/main/java/com/google/gson/JsonObject.java @@ -192,6 +192,10 @@ public JsonObject getAsJsonObject(String memberName) { return (JsonObject) members.get(memberName); } + /*The equals function defined below is to compare two non-interned object + and only one of the condition to determine they are equal is a reference + equality test therefore its usage is safe*/ + @SuppressWarnings("not.interned") @Override public boolean equals(Object o) { return (o == this) || (o instanceof JsonObject diff --git a/gson/src/main/java/com/google/gson/TypeAdapterFactory.java b/gson/src/main/java/com/google/gson/TypeAdapterFactory.java index e12a72dccd..3b3cd1a792 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.checkerframework.checker.interning.qual.UsesObjectEquals; /** * Creates type adapters for set of related types. Type adapter factories are @@ -160,7 +161,7 @@ * * @since 2.1 */ -public interface TypeAdapterFactory { +public @UsesObjectEquals interface TypeAdapterFactory { /** * Returns a type adapter for {@code type}, or null if this factory doesn't diff --git a/gson/src/main/java/com/google/gson/internal/$Gson$Types.java b/gson/src/main/java/com/google/gson/internal/$Gson$Types.java index adea605f59..c79fab0e20 100644 --- a/gson/src/main/java/com/google/gson/internal/$Gson$Types.java +++ b/gson/src/main/java/com/google/gson/internal/$Gson$Types.java @@ -29,7 +29,7 @@ import static com.google.gson.internal.$Gson$Preconditions.checkArgument; import static com.google.gson.internal.$Gson$Preconditions.checkNotNull; - +import org.checkerframework.checker.interning.qual.Interned; /** * Static methods for working with types. * @@ -165,6 +165,10 @@ static boolean equal(Object a, Object b) { /** * Returns true if {@code a} and {@code b} are equal. */ + /*The equals function defined below is to compare two non-interned object + and only one of the condition to determine they are equal is a reference + equality test therefore its usage is safe*/ + @SuppressWarnings("not.interned") public static boolean equals(Type a, Type b) { if (a == b) { // also handles (a == null && b == null) @@ -337,6 +341,9 @@ public static Type resolve(Type context, Class contextRawType, Type toResolve return resolve(context, contextRawType, toResolve, new HashSet()); } + /*#1-#7 equality checks are reference equality check and not value + * equality check, therefore usage of == is safe*/ + @SuppressWarnings("not.interned") private static Type resolve(Type context, Class contextRawType, Type toResolve, Collection visitedTypeVariables) { // this implementation is made a little more complicated in an attempt to avoid object-creation @@ -350,7 +357,7 @@ private static Type resolve(Type context, Class contextRawType, Type toResolv visitedTypeVariables.add(typeVariable); } toResolve = resolveTypeVariable(context, contextRawType, typeVariable); - if (toResolve == typeVariable) { + if (toResolve == typeVariable) { //#1 return toResolve; } @@ -358,7 +365,7 @@ private static Type resolve(Type context, Class contextRawType, Type toResolv Class original = (Class) toResolve; Type componentType = original.getComponentType(); Type newComponentType = resolve(context, contextRawType, componentType, visitedTypeVariables); - return componentType == newComponentType + return componentType == newComponentType //#2 ? original : arrayOf(newComponentType); @@ -366,7 +373,7 @@ private static Type resolve(Type context, Class contextRawType, Type toResolv GenericArrayType original = (GenericArrayType) toResolve; Type componentType = original.getGenericComponentType(); Type newComponentType = resolve(context, contextRawType, componentType, visitedTypeVariables); - return componentType == newComponentType + return componentType == newComponentType //#3 ? original : arrayOf(newComponentType); @@ -374,12 +381,12 @@ private static Type resolve(Type context, Class contextRawType, Type toResolv ParameterizedType original = (ParameterizedType) toResolve; Type ownerType = original.getOwnerType(); Type newOwnerType = resolve(context, contextRawType, ownerType, visitedTypeVariables); - boolean changed = newOwnerType != ownerType; + boolean changed = newOwnerType != ownerType; //#4 Type[] args = original.getActualTypeArguments(); for (int t = 0, length = args.length; t < length; t++) { Type resolvedTypeArgument = resolve(context, contextRawType, args[t], visitedTypeVariables); - if (resolvedTypeArgument != args[t]) { + if (resolvedTypeArgument != args[t]) { //#5 if (!changed) { args = args.clone(); changed = true; @@ -399,12 +406,12 @@ private static Type resolve(Type context, Class contextRawType, Type toResolv if (originalLowerBound.length == 1) { Type lowerBound = resolve(context, contextRawType, originalLowerBound[0], visitedTypeVariables); - if (lowerBound != originalLowerBound[0]) { + if (lowerBound != originalLowerBound[0]) { //#6 return supertypeOf(lowerBound); } } else if (originalUpperBound.length == 1) { Type upperBound = resolve(context, contextRawType, originalUpperBound[0], visitedTypeVariables); - if (upperBound != originalUpperBound[0]) { + if (upperBound != originalUpperBound[0]) { //#7 return subtypeOf(upperBound); } } diff --git a/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java b/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java index b2707c50da..a12fc9510a 100644 --- a/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java +++ b/gson/src/main/java/com/google/gson/internal/LinkedHashTreeMap.java @@ -28,6 +28,7 @@ import java.util.LinkedHashMap; import java.util.NoSuchElementException; import java.util.Set; +import org.checkerframework.checker.interning.qual.Interned; /** * A map of comparable keys to values. Unlike {@code TreeMap}, this class uses @@ -38,14 +39,16 @@ * LinkedHashMap classes. */ public final class LinkedHashTreeMap extends AbstractMap implements Serializable { - @SuppressWarnings({ "unchecked", "rawtypes" }) // to avoid Comparable>> - private static final Comparator NATURAL_ORDER = new Comparator() { + /*as the below Comparator implementing class definition creates an immutable + * object, therefore object created would be interned*/ + @SuppressWarnings({ "unchecked", "rawtypes", "interned.object.creation" }) // to avoid Comparable>> + private static @Interned final Comparator NATURAL_ORDER = new @Interned Comparator() { public int compare(Comparable a, Comparable b) { return a.compareTo(b); } }; - Comparator comparator; + @Interned Comparator comparator; Node[] table; final Node header; int size = 0; @@ -69,7 +72,7 @@ public LinkedHashTreeMap() { * use the natural ordering. */ @SuppressWarnings({ "unchecked", "rawtypes" }) // unsafe! if comparator is null, this assumes K is comparable - public LinkedHashTreeMap(Comparator comparator) { + public LinkedHashTreeMap(@Interned Comparator comparator) { this.comparator = comparator != null ? comparator : (Comparator) NATURAL_ORDER; @@ -101,6 +104,11 @@ public LinkedHashTreeMap(Comparator comparator) { return result; } + /*Here the usage of == to is safe as the logic of the below function + * is concerned with the reference equality check and not value equality. + * It tries to search for a particular object or element in a tree and + * not a value therefore is safe #1*/ + @SuppressWarnings("not.interned") @Override public void clear() { Arrays.fill(table, null); size = 0; @@ -108,7 +116,7 @@ public LinkedHashTreeMap(Comparator comparator) { // Clear all links to help GC Node header = this.header; - for (Node e = header.next; e != header; ) { + for (Node e = header.next; e != header; ) { //#1 Node next = e.next; e.next = e.prev = null; e = next; @@ -308,6 +316,11 @@ Node removeInternalByKey(Object key) { return node; } + /*Here the usage of == to is safe as the logic of the below function + * is concerned with the reference equality check and not value equality. + * It tries to search for a particular object or element in a tree and + * not a value therefore is safe #2 #3*/ + @SuppressWarnings("not.interned") private void replaceInParent(Node node, Node replacement) { Node parent = node.parent; node.parent = null; @@ -316,10 +329,10 @@ private void replaceInParent(Node node, Node replacement) { } if (parent != null) { - if (parent.left == node) { + if (parent.left == node) { //#2 parent.left = replacement; } else { - assert (parent.right == node); + assert (parent.right == node); //#3 parent.right = replacement; } } else { @@ -765,10 +778,18 @@ private abstract class LinkedTreeMapIterator implements Iterator { LinkedTreeMapIterator() { } + /*Here the usage of == to is safe as the logic of the below function + * is concerned with the reference equality check and not value equality.#4 + */ + @SuppressWarnings("not.interned") public final boolean hasNext() { - return next != header; + return next != header; //#4 } + /*Here the usage of == to is safe as the logic of the below function + * is concerned with the reference equality check and not value equality.#4 + */ + @SuppressWarnings("not.interned") final Node nextNode() { Node e = next; if (e == header) { diff --git a/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java b/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java index 80462742e3..c03729f988 100644 --- a/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java +++ b/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java @@ -27,6 +27,7 @@ import java.util.LinkedHashMap; import java.util.NoSuchElementException; import java.util.Set; +import org.checkerframework.checker.interning.qual.Interned; /** * A map of comparable keys to values. Unlike {@code TreeMap}, this class uses @@ -36,14 +37,16 @@ *

This implementation was derived from Android 4.1's TreeMap class. */ public final class LinkedTreeMap extends AbstractMap implements Serializable { - @SuppressWarnings({ "unchecked", "rawtypes" }) // to avoid Comparable>> - private static final Comparator NATURAL_ORDER = new Comparator() { + /*as the below Comparator implementing class definition creates an immutable + * object, therefore object created would be interned*/ + @SuppressWarnings({ "unchecked", "rawtypes", "interned.object.creation" }) // to avoid Comparable>> + private static final @Interned Comparator NATURAL_ORDER = new @Interned Comparator() { public int compare(Comparable a, Comparable b) { return a.compareTo(b); } }; - Comparator comparator; + @Interned Comparator comparator; Node root; int size = 0; int modCount = 0; @@ -68,7 +71,7 @@ public LinkedTreeMap() { * use the natural ordering. */ @SuppressWarnings({ "unchecked", "rawtypes" }) // unsafe! if comparator is null, this assumes K is comparable - public LinkedTreeMap(Comparator comparator) { + public LinkedTreeMap(@Interned Comparator comparator) { this.comparator = comparator != null ? comparator : (Comparator) NATURAL_ORDER; @@ -281,6 +284,11 @@ Node removeInternalByKey(Object key) { return node; } + /*Here the usage of == is safe as the logic of the below function + * is concerned with the reference equality check and not value equality. + * It tries to search for a particular object or element in a tree and + * not a value therefore is safe #1 #2*/ + @SuppressWarnings("not.interned") private void replaceInParent(Node node, Node replacement) { Node parent = node.parent; node.parent = null; @@ -289,10 +297,10 @@ private void replaceInParent(Node node, Node replacement) { } if (parent != null) { - if (parent.left == node) { + if (parent.left == node) { //#1 parent.left = replacement; } else { - assert (parent.right == node); + assert (parent.right == node); //#2 parent.right = replacement; } } else { @@ -531,13 +539,22 @@ private abstract class LinkedTreeMapIterator implements Iterator { LinkedTreeMapIterator() { } + /*Here the usage of == is safe as the logic of the below function + * is concerned with the reference equality check and not value equality.#3 + */ + @SuppressWarnings("not.interned") public final boolean hasNext() { - return next != header; + return next != header; //#3 } + /*Here the usage of == is safe as the logic of the below function + * is concerned with the reference equality check and not value equality. + * It tries to search for a particular object or element in a tree and + * not a value therefore is safe #4*/ + @SuppressWarnings("not.interned") final Node nextNode() { Node e = next; - if (e == header) { + if (e == header) { //#4 throw new NoSuchElementException(); } if (modCount != expectedModCount) { diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java b/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java index a223754aed..74b345403b 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java +++ b/gson/src/main/java/com/google/gson/internal/bind/JsonTreeReader.java @@ -104,6 +104,10 @@ public JsonTreeReader(JsonElement element) { return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY; } + /*Probable missing annotation in jdk, class Object should be annotated as + * UsesObjectEquals, therefore it is safe for objects of class Object to use + * reference equality check #1*/ + @SuppressWarnings("not.interned") @Override public JsonToken peek() throws IOException { if (stackSize == 0) { return JsonToken.END_DOCUMENT; @@ -140,7 +144,7 @@ public JsonTreeReader(JsonElement element) { } } else if (o instanceof JsonNull) { return JsonToken.NULL; - } else if (o == SENTINEL_CLOSED) { + } else if (o == SENTINEL_CLOSED) { //#1 throw new IllegalStateException("JsonReader is closed"); } else { throw new AssertionError(); 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 777e7dee35..15409925ee 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 @@ -126,17 +126,25 @@ private ReflectiveTypeAdapterFactory.BoundField createBoundField( : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType()); t.write(writer, fieldValue); } + /*#2 the fieldValue sent can be an instance of the wrapper classes like + * Integer Float etc which are not interned, probably wrong annotation + * of method set in jdk Field.java*/ + @SuppressWarnings("argument.type.incompatible") @Override void read(JsonReader reader, Object value) throws IOException, IllegalAccessException { Object fieldValue = typeAdapter.read(reader); if (fieldValue != null || !isPrimitive) { - field.set(value, fieldValue); + field.set(value, fieldValue); //#2 } } + /*Probable missing annotation in jdk class Object, Object should be + annotated as UsesObjectEquals, therefore below reference equality + check is safe #1*/ + @SuppressWarnings("not.interned") @Override public boolean writeField(Object value) throws IOException, IllegalAccessException { if (!serialized) return false; Object fieldValue = field.get(value); - return fieldValue != value; // avoid recursion for example for Throwable.cause + return fieldValue != value; //#1 // avoid recursion for example for Throwable.cause } }; } diff --git a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java index 2bf37ad0a0..8dae177a3f 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java +++ b/gson/src/main/java/com/google/gson/internal/bind/TypeAdapterRuntimeTypeWrapper.java @@ -41,7 +41,10 @@ public T read(JsonReader in) throws IOException { return delegate.read(in); } - @SuppressWarnings({"rawtypes", "unchecked"}) + /*the function getRuntimeTypeIfMoreSpecific returns either the same `type + * with same reference sent #1 or returns a different type which wouldn't + * be equal to `type`. Therefore using == or reference check is safe in #2*/ + @SuppressWarnings({"rawtypes", "unchecked","not.interned"}) @Override public void write(JsonWriter out, T value) throws IOException { // Order of preference for choosing type adapters @@ -51,8 +54,8 @@ public void write(JsonWriter out, T value) throws IOException { // Fourth preference: reflective type adapter for the declared type TypeAdapter chosen = delegate; - Type runtimeType = getRuntimeTypeIfMoreSpecific(type, value); - if (runtimeType != type) { + Type runtimeType = getRuntimeTypeIfMoreSpecific(type, value); //#1 + if (runtimeType != type) { //#2 TypeAdapter runtimeTypeAdapter = context.getAdapter(TypeToken.get(runtimeType)); if (!(runtimeTypeAdapter instanceof ReflectiveTypeAdapterFactory.Adapter)) { // The user registered a type adapter for the runtime type, so we will use that From e2e27c746a40273fe4142ea16bf04f0ea1ddd275 Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Mon, 29 Jun 2020 10:18:06 +0530 Subject: [PATCH 6/8] add build files --- gson/pom.xml | 6 +----- pom.xml | 6 +----- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/gson/pom.xml b/gson/pom.xml index f7a075a346..1153a6f8f0 100644 --- a/gson/pom.xml +++ b/gson/pom.xml @@ -29,10 +29,6 @@ maven-compiler-plugin 3.8.1 - - **/gson/*.java - module-info.java - 11 10000 @@ -46,7 +42,7 @@ - org.checkerframework.checker.nullness.NullnessChecker + org.checkerframework.checker.interning.InterningChecker -AprintErrorStack diff --git a/pom.xml b/pom.xml index ed0ea4d920..d82ad594e1 100644 --- a/pom.xml +++ b/pom.xml @@ -81,10 +81,6 @@ 9 - - **/gson/*.java - module-info.java - @@ -110,7 +106,7 @@ 10000 - org.checkerframework.checker.nullness.NullnessChecker + org.checkerframework.checker.interning.InterningChecker From 14d2de02a6818e04cbfa88aec6fee2010e3037d3 Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Mon, 29 Jun 2020 10:24:10 +0530 Subject: [PATCH 7/8] remove unwanted annotations --- gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java b/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java index 77a44e2dcb..522963795a 100644 --- a/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java +++ b/gson/src/main/java/com/google/gson/DefaultDateTypeAdapter.java @@ -33,7 +33,6 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; -import org.checkerframework.checker.nullness.qual.Nullable; /** * This type adapter supports three subclasses of date: Date, Timestamp, and @@ -121,7 +120,7 @@ public void write(JsonWriter out, Date value) throws IOException { } @Override - public @Nullable Date read(JsonReader in) throws IOException { + public Date read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; From 09922cb39372bd7db45cba9e4cafcce86f19ad9d Mon Sep 17 00:00:00 2001 From: pchattopadhyay Date: Tue, 30 Jun 2020 12:51:41 +0530 Subject: [PATCH 8/8] remove unnecessary import --- gson/src/main/java/com/google/gson/internal/$Gson$Types.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gson/src/main/java/com/google/gson/internal/$Gson$Types.java b/gson/src/main/java/com/google/gson/internal/$Gson$Types.java index c79fab0e20..9434cd46a3 100644 --- a/gson/src/main/java/com/google/gson/internal/$Gson$Types.java +++ b/gson/src/main/java/com/google/gson/internal/$Gson$Types.java @@ -29,7 +29,7 @@ import static com.google.gson.internal.$Gson$Preconditions.checkArgument; import static com.google.gson.internal.$Gson$Preconditions.checkNotNull; -import org.checkerframework.checker.interning.qual.Interned; + /** * Static methods for working with types. *