From aa992eac580915cc3180e82a89d434e70ecc960a Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Wed, 29 Nov 2023 23:11:01 +0100 Subject: [PATCH 1/2] Enable additional Error Prone checks & fix violations Some of them also enforce additional Google Java Format requirements which are not handled by google-java-format, such as disallowing wildcard imports. Not all experimental checks have been listed because some are not applicable, such as Dependency Injection framework checks, or checks related to Guava's immutable collections (since Gson's main code does not have a dependency on Guava). Other checks have been omitted because they are probably not relevant (this was a subjective choice), or would require larger refactoring or would flag issues with the public API, which cannot be changed easily. --- .../rawcollections/RawCollectionsExample.java | 1 + .../PostConstructAdapterFactory.java | 6 +- .../gson/typeadapters/UtcDateTypeAdapter.java | 2 +- .../gson/interceptors/InterceptorTest.java | 8 +- gson/src/main/java/com/google/gson/Gson.java | 142 +++++++++--------- .../java/com/google/gson/GsonBuilder.java | 20 +-- .../java/com/google/gson/JsonPrimitive.java | 10 +- .../java/com/google/gson/TypeAdapter.java | 126 ++++++++-------- .../com/google/gson/internal/Excluder.java | 6 +- .../com/google/gson/internal/JavaVersion.java | 4 +- .../internal/JsonReaderInternalAccess.java | 5 +- .../google/gson/internal/LinkedTreeMap.java | 2 +- .../internal/NonNullElementWrapperList.java | 1 + .../internal/PreJava9DateFormatProvider.java | 5 +- .../com/google/gson/internal/Primitives.java | 4 +- .../com/google/gson/internal/Streams.java | 1 + .../internal/bind/DefaultDateTypeAdapter.java | 4 +- ...onAdapterAnnotationTypeAdapterFactory.java | 2 +- .../gson/internal/bind/JsonTreeReader.java | 8 +- .../gson/internal/bind/JsonTreeWriter.java | 24 +-- .../internal/bind/MapTypeAdapterFactory.java | 2 +- .../gson/internal/bind/ObjectTypeAdapter.java | 2 +- .../bind/ReflectiveTypeAdapterFactory.java | 4 +- .../gson/internal/bind/TypeAdapters.java | 20 ++- .../gson/internal/bind/util/ISO8601Utils.java | 12 +- .../com/google/gson/stream/JsonReader.java | 38 +++-- .../com/google/gson/stream/JsonScope.java | 1 + .../com/google/gson/stream/JsonWriter.java | 132 ++++++++-------- .../google/gson/FieldNamingPolicyTest.java | 2 +- .../com/google/gson/GsonTypeAdapterTest.java | 2 +- .../google/gson/JavaSerializationTest.java | 2 +- .../gson/ParameterizedTypeFixtures.java | 3 +- .../com/google/gson/common/MoreAsserts.java | 1 + .../com/google/gson/common/TestTypes.java | 1 + .../functional/CustomTypeAdaptersTest.java | 2 +- .../google/gson/functional/EscapingTest.java | 4 +- .../gson/functional/FieldNamingTest.java | 5 +- .../GsonVersionDiagnosticsTest.java | 2 +- .../gson/functional/InheritanceTest.java | 2 +- .../gson/functional/Java17RecordTest.java | 1 + .../JsonAdapterAnnotationOnClassesTest.java | 4 +- ...JsonAdapterSerializerDeserializerTest.java | 1 + .../google/gson/functional/JsonTreeTest.java | 2 +- .../com/google/gson/functional/MapTest.java | 2 +- .../MoreSpecificTypeSerializationTest.java | 5 +- .../functional/NullObjectAndFieldTest.java | 5 +- .../google/gson/functional/ObjectTest.java | 2 + .../gson/functional/PrettyPrintingTest.java | 64 ++++++-- .../google/gson/functional/PrimitiveTest.java | 2 +- .../ReflectionAccessFilterTest.java | 2 +- .../functional/TypeAdapterPrecedenceTest.java | 6 +- .../gson/functional/VersioningTest.java | 5 + .../google/gson/internal/GsonTypesTest.java | 9 +- .../google/gson/internal/JavaVersionTest.java | 34 ++--- .../gson/internal/LinkedTreeMapTest.java | 2 +- .../bind/DefaultDateTypeAdapterTest.java | 2 +- .../gson/internal/sql/SqlTypesGsonTest.java | 5 +- .../google/gson/metrics/PerformanceTest.java | 9 +- .../google/gson/reflect/TypeTokenTest.java | 3 + .../google/gson/stream/JsonReaderTest.java | 11 +- .../metrics/NonUploadingCaliperRunner.java | 2 + .../google/gson/metrics/ParseBenchmark.java | 13 +- pom.xml | 61 ++++++++ .../gson/protobuf/ProtoTypeAdapter.java | 3 +- .../main/java/com/example/GenericClasses.java | 2 + .../src/main/java/com/example/Main.java | 2 + .../com/example/NoSerializedNameMain.java | 2 + .../main/java/com/example/TestExecutor.java | 2 + 68 files changed, 527 insertions(+), 354 deletions(-) diff --git a/extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java b/extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java index 6568c0b146..4d9cffa86e 100644 --- a/extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java +++ b/extras/src/main/java/com/google/gson/extras/examples/rawcollections/RawCollectionsExample.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; +@SuppressWarnings({"PrivateConstructorForUtilityClass", "SystemOut"}) public class RawCollectionsExample { static class Event { private String name; diff --git a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java index 7a3234073f..924a9089ff 100644 --- a/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java +++ b/extras/src/main/java/com/google/gson/typeadapters/PostConstructAdapterFactory.java @@ -61,9 +61,11 @@ public T read(JsonReader in) throws IOException { try { method.invoke(result); } catch (IllegalAccessException e) { - throw new AssertionError(); + throw new AssertionError(e); } catch (InvocationTargetException e) { - if (e.getCause() instanceof RuntimeException) throw (RuntimeException) e.getCause(); + if (e.getCause() instanceof RuntimeException) { + throw (RuntimeException) e.getCause(); + } throw new RuntimeException(e.getCause()); } } diff --git a/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java b/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java index b3e01a1881..4b2356c1b2 100644 --- a/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java +++ b/extras/src/main/java/com/google/gson/typeadapters/UtcDateTypeAdapter.java @@ -30,7 +30,7 @@ import java.util.TimeZone; public final class UtcDateTypeAdapter extends TypeAdapter { - private final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC"); + private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC"); @Override public void write(JsonWriter out, Date date) throws IOException { diff --git a/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java b/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java index 2030d337cd..9a957fc744 100644 --- a/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java +++ b/extras/src/test/java/com/google/gson/interceptors/InterceptorTest.java @@ -171,7 +171,9 @@ public void postDeserialize(User user) { if (user.name == null || user.password == null) { throw new JsonSyntaxException("name and password are required fields."); } - if (user.email == null) user.email = User.DEFAULT_EMAIL; + if (user.email == null) { + user.email = User.DEFAULT_EMAIL; + } } } @@ -192,7 +194,9 @@ public void postDeserialize(Address address) { if (address.city == null || address.state == null || address.zip == null) { throw new JsonSyntaxException("Address city, state and zip are required fields."); } - if (address.firstLine == null) address.firstLine = Address.DEFAULT_FIRST_LINE; + if (address.firstLine == null) { + address.firstLine = Address.DEFAULT_FIRST_LINE; + } } } } diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 80aa12888e..1171a227c9 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -447,7 +447,7 @@ public boolean htmlSafe() { return htmlSafe; } - private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { + private static TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { if (serializeSpecialFloatingPointValues) { return TypeAdapters.DOUBLE; } @@ -474,7 +474,7 @@ public void write(JsonWriter out, Number value) throws IOException { }; } - private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { + private static TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { if (serializeSpecialFloatingPointValues) { return TypeAdapters.FLOAT; } @@ -656,6 +656,16 @@ public TypeAdapter getAdapter(TypeToken type) { return candidate; } + /** + * Returns the type adapter for {@code type}. + * + * @throws IllegalArgumentException if this Gson instance cannot serialize and deserialize {@code + * type}. + */ + public TypeAdapter getAdapter(Class type) { + return getAdapter(TypeToken.get(type)); + } + /** * This method is used to get an alternate type adapter for the specified type. This is used to * access a type adapter that is overridden by a {@link TypeAdapterFactory} that you may have @@ -748,16 +758,6 @@ public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeTo } } - /** - * Returns the type adapter for {@code type}. - * - * @throws IllegalArgumentException if this Gson instance cannot serialize and deserialize {@code - * type}. - */ - public TypeAdapter getAdapter(Class type) { - return getAdapter(TypeToken.get(type)); - } - /** * This method serializes the specified object into its equivalent representation as a tree of * {@link JsonElement}s. This method should be used when the specified object is not a generic @@ -983,53 +983,6 @@ public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOExce } } - /** - * Returns a new JSON writer configured for the settings on this Gson instance. - * - *

The following settings are considered: - * - *

    - *
  • {@link GsonBuilder#disableHtmlEscaping()} - *
  • {@link GsonBuilder#generateNonExecutableJson()} - *
  • {@link GsonBuilder#serializeNulls()} - *
  • {@link GsonBuilder#setStrictness(Strictness)}. If no {@linkplain - * GsonBuilder#setStrictness(Strictness) explicit strictness has been set} the created - * writer will have a strictness of {@link Strictness#LEGACY_STRICT}. Otherwise, the - * strictness of the {@code Gson} instance will be used for the created writer. - *
  • {@link GsonBuilder#setPrettyPrinting()} - *
  • {@link GsonBuilder#setFormattingStyle(FormattingStyle)} - *
- */ - public JsonWriter newJsonWriter(Writer writer) throws IOException { - if (generateNonExecutableJson) { - writer.write(JSON_NON_EXECUTABLE_PREFIX); - } - JsonWriter jsonWriter = new JsonWriter(writer); - jsonWriter.setFormattingStyle(formattingStyle); - jsonWriter.setHtmlSafe(htmlSafe); - jsonWriter.setStrictness(strictness == null ? Strictness.LEGACY_STRICT : strictness); - jsonWriter.setSerializeNulls(serializeNulls); - return jsonWriter; - } - - /** - * Returns a new JSON reader configured for the settings on this Gson instance. - * - *

The following settings are considered: - * - *

    - *
  • {@link GsonBuilder#setStrictness(Strictness)}. If no {@linkplain - * GsonBuilder#setStrictness(Strictness) explicit strictness has been set} the created - * reader will have a strictness of {@link Strictness#LEGACY_STRICT}. Otherwise, the - * strictness of the {@code Gson} instance will be used for the created reader. - *
- */ - public JsonReader newJsonReader(Reader reader) { - JsonReader jsonReader = new JsonReader(reader); - jsonReader.setStrictness(strictness == null ? Strictness.LEGACY_STRICT : strictness); - return jsonReader; - } - /** * Writes the JSON for {@code jsonElement} to {@code writer}. * @@ -1078,6 +1031,53 @@ public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOExce } } + /** + * Returns a new JSON writer configured for the settings on this Gson instance. + * + *

The following settings are considered: + * + *

    + *
  • {@link GsonBuilder#disableHtmlEscaping()} + *
  • {@link GsonBuilder#generateNonExecutableJson()} + *
  • {@link GsonBuilder#serializeNulls()} + *
  • {@link GsonBuilder#setStrictness(Strictness)}. If no {@linkplain + * GsonBuilder#setStrictness(Strictness) explicit strictness has been set} the created + * writer will have a strictness of {@link Strictness#LEGACY_STRICT}. Otherwise, the + * strictness of the {@code Gson} instance will be used for the created writer. + *
  • {@link GsonBuilder#setPrettyPrinting()} + *
  • {@link GsonBuilder#setFormattingStyle(FormattingStyle)} + *
+ */ + public JsonWriter newJsonWriter(Writer writer) throws IOException { + if (generateNonExecutableJson) { + writer.write(JSON_NON_EXECUTABLE_PREFIX); + } + JsonWriter jsonWriter = new JsonWriter(writer); + jsonWriter.setFormattingStyle(formattingStyle); + jsonWriter.setHtmlSafe(htmlSafe); + jsonWriter.setStrictness(strictness == null ? Strictness.LEGACY_STRICT : strictness); + jsonWriter.setSerializeNulls(serializeNulls); + return jsonWriter; + } + + /** + * Returns a new JSON reader configured for the settings on this Gson instance. + * + *

The following settings are considered: + * + *

    + *
  • {@link GsonBuilder#setStrictness(Strictness)}. If no {@linkplain + * GsonBuilder#setStrictness(Strictness) explicit strictness has been set} the created + * reader will have a strictness of {@link Strictness#LEGACY_STRICT}. Otherwise, the + * strictness of the {@code Gson} instance will be used for the created reader. + *
+ */ + public JsonReader newJsonReader(Reader reader) { + JsonReader jsonReader = new JsonReader(reader); + jsonReader.setStrictness(strictness == null ? Strictness.LEGACY_STRICT : strictness); + return jsonReader; + } + /** * This method deserializes the specified JSON into an object of the specified class. It is not * suitable to use if the specified class is a generic type since it will not have the generic @@ -1262,18 +1262,6 @@ public T fromJson(Reader json, TypeToken typeOfT) return object; } - private static void assertFullConsumption(Object obj, JsonReader reader) { - try { - if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { - throw new JsonSyntaxException("JSON document was not fully consumed."); - } - } catch (MalformedJsonException e) { - throw new JsonSyntaxException(e); - } catch (IOException e) { - throw new JsonIOException(e); - } - } - // fromJson(JsonReader, Class) is unfortunately missing and cannot be added now without breaking // source compatibility in certain cases, see // https://github.com/google/gson/pull/1700#discussion_r973764414 @@ -1472,6 +1460,18 @@ public T fromJson(JsonElement json, TypeToken typeOfT) throws JsonSyntaxE return fromJson(new JsonTreeReader(json), typeOfT); } + private static void assertFullConsumption(Object obj, JsonReader reader) { + try { + if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { + throw new JsonSyntaxException("JSON document was not fully consumed."); + } + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + /** * Proxy type adapter for cyclic type graphs. * diff --git a/gson/src/main/java/com/google/gson/GsonBuilder.java b/gson/src/main/java/com/google/gson/GsonBuilder.java index c04dd5439e..0d9bef027d 100644 --- a/gson/src/main/java/com/google/gson/GsonBuilder.java +++ b/gson/src/main/java/com/google/gson/GsonBuilder.java @@ -614,14 +614,6 @@ public GsonBuilder setDateFormat(String pattern) { return this; } - private static int checkDateFormatStyle(int style) { - // Valid DateFormat styles are: 0, 1, 2, 3 (FULL, LONG, MEDIUM, SHORT) - if (style < 0 || style > 3) { - throw new IllegalArgumentException("Invalid style: " + style); - } - return style; - } - /** * Configures Gson to serialize {@code Date} objects according to the date style value provided. * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last @@ -669,6 +661,14 @@ public GsonBuilder setDateFormat(int dateStyle, int timeStyle) { return this; } + private static int checkDateFormatStyle(int style) { + // Valid DateFormat styles are: 0, 1, 2, 3 (FULL, LONG, MEDIUM, SHORT) + if (style < 0 || style > 3) { + throw new IllegalArgumentException("Invalid style: " + style); + } + return style; + } + /** * Configures Gson for custom serialization or deserialization. This method combines the * registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a @@ -722,7 +722,7 @@ public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { return this; } - private boolean isTypeObjectOrJsonElement(Type type) { + private static boolean isTypeObjectOrJsonElement(Type type) { return type instanceof Class && (type == Object.class || JsonElement.class.isAssignableFrom((Class) type)); } @@ -901,7 +901,7 @@ public Gson create() { new ArrayList<>(reflectionFilters)); } - private void addTypeAdaptersForDate( + private static void addTypeAdaptersForDate( String datePattern, int dateStyle, int timeStyle, List factories) { TypeAdapterFactory dateAdapterFactory; boolean sqlTypesSupported = SqlTypesSupport.SUPPORTS_SQL_TYPES; diff --git a/gson/src/main/java/com/google/gson/JsonPrimitive.java b/gson/src/main/java/com/google/gson/JsonPrimitive.java index 00530d5691..2985ce98ab 100644 --- a/gson/src/main/java/com/google/gson/JsonPrimitive.java +++ b/gson/src/main/java/com/google/gson/JsonPrimitive.java @@ -38,7 +38,10 @@ public final class JsonPrimitive extends JsonElement { * * @param bool the value to create the primitive with. */ - @SuppressWarnings("deprecation") // superclass constructor + // "deprecation" suppression for superclass constructor + // "UnnecessaryBoxedVariable" Error Prone warning is correct since method does not accept + // null, but cannot be changed anymore since this is public API + @SuppressWarnings({"deprecation", "UnnecessaryBoxedVariable"}) public JsonPrimitive(Boolean bool) { value = Objects.requireNonNull(bool); } @@ -69,7 +72,10 @@ public JsonPrimitive(String string) { * * @param c the value to create the primitive with. */ - @SuppressWarnings("deprecation") // superclass constructor + // "deprecation" suppression for superclass constructor + // "UnnecessaryBoxedVariable" Error Prone warning is correct since method does not accept + // null, but cannot be changed anymore since this is public API + @SuppressWarnings({"deprecation", "UnnecessaryBoxedVariable"}) public JsonPrimitive(Character c) { // convert characters to strings since in JSON, characters are represented as a single // character string diff --git a/gson/src/main/java/com/google/gson/TypeAdapter.java b/gson/src/main/java/com/google/gson/TypeAdapter.java index fe4ce8ecde..90d330e382 100644 --- a/gson/src/main/java/com/google/gson/TypeAdapter.java +++ b/gson/src/main/java/com/google/gson/TypeAdapter.java @@ -144,69 +144,6 @@ public final void toJson(Writer out, T value) throws IOException { write(writer, value); } - /** - * This wrapper method is used to make a type adapter null tolerant. In general, a type adapter is - * required to handle nulls in write and read methods. Here is how this is typically done:
- * - *
{@code
-   * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
-   *   new TypeAdapter() {
-   *     public Foo read(JsonReader in) throws IOException {
-   *       if (in.peek() == JsonToken.NULL) {
-   *         in.nextNull();
-   *         return null;
-   *       }
-   *       // read a Foo from in and return it
-   *     }
-   *     public void write(JsonWriter out, Foo src) throws IOException {
-   *       if (src == null) {
-   *         out.nullValue();
-   *         return;
-   *       }
-   *       // write src as JSON to out
-   *     }
-   *   }).create();
-   * }
- * - * You can avoid this boilerplate handling of nulls by wrapping your type adapter with this - * method. Here is how we will rewrite the above example: - * - *
{@code
-   * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
-   *   new TypeAdapter() {
-   *     public Foo read(JsonReader in) throws IOException {
-   *       // read a Foo from in and return it
-   *     }
-   *     public void write(JsonWriter out, Foo src) throws IOException {
-   *       // write src as JSON to out
-   *     }
-   *   }.nullSafe()).create();
-   * }
- * - * Note that we didn't need to check for nulls in our type adapter after we used nullSafe. - */ - public final TypeAdapter nullSafe() { - return new TypeAdapter() { - @Override - public void write(JsonWriter out, T value) throws IOException { - if (value == null) { - out.nullValue(); - } else { - TypeAdapter.this.write(out, value); - } - } - - @Override - public T read(JsonReader reader) throws IOException { - if (reader.peek() == JsonToken.NULL) { - reader.nextNull(); - return null; - } - return TypeAdapter.this.read(reader); - } - }; - } - /** * Converts {@code value} to a JSON document. * @@ -309,4 +246,67 @@ public final T fromJsonTree(JsonElement jsonTree) { throw new JsonIOException(e); } } + + /** + * This wrapper method is used to make a type adapter null tolerant. In general, a type adapter is + * required to handle nulls in write and read methods. Here is how this is typically done:
+ * + *
{@code
+   * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
+   *   new TypeAdapter() {
+   *     public Foo read(JsonReader in) throws IOException {
+   *       if (in.peek() == JsonToken.NULL) {
+   *         in.nextNull();
+   *         return null;
+   *       }
+   *       // read a Foo from in and return it
+   *     }
+   *     public void write(JsonWriter out, Foo src) throws IOException {
+   *       if (src == null) {
+   *         out.nullValue();
+   *         return;
+   *       }
+   *       // write src as JSON to out
+   *     }
+   *   }).create();
+   * }
+ * + * You can avoid this boilerplate handling of nulls by wrapping your type adapter with this + * method. Here is how we will rewrite the above example: + * + *
{@code
+   * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
+   *   new TypeAdapter() {
+   *     public Foo read(JsonReader in) throws IOException {
+   *       // read a Foo from in and return it
+   *     }
+   *     public void write(JsonWriter out, Foo src) throws IOException {
+   *       // write src as JSON to out
+   *     }
+   *   }.nullSafe()).create();
+   * }
+ * + * Note that we didn't need to check for nulls in our type adapter after we used nullSafe. + */ + public final TypeAdapter nullSafe() { + return new TypeAdapter() { + @Override + public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + TypeAdapter.this.write(out, value); + } + } + + @Override + public T read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + return TypeAdapter.this.read(reader); + } + }; + } } diff --git a/gson/src/main/java/com/google/gson/internal/Excluder.java b/gson/src/main/java/com/google/gson/internal/Excluder.java index dea3b851d7..b3d2288a00 100644 --- a/gson/src/main/java/com/google/gson/internal/Excluder.java +++ b/gson/src/main/java/com/google/gson/internal/Excluder.java @@ -216,17 +216,17 @@ private boolean excludeClassInStrategy(Class clazz, boolean serialize) { return false; } - private boolean isAnonymousOrNonStaticLocal(Class clazz) { + private static boolean isAnonymousOrNonStaticLocal(Class clazz) { return !Enum.class.isAssignableFrom(clazz) && !isStatic(clazz) && (clazz.isAnonymousClass() || clazz.isLocalClass()); } - private boolean isInnerClass(Class clazz) { + private static boolean isInnerClass(Class clazz) { return clazz.isMemberClass() && !isStatic(clazz); } - private boolean isStatic(Class clazz) { + private static boolean isStatic(Class clazz) { return (clazz.getModifiers() & Modifier.STATIC) != 0; } diff --git a/gson/src/main/java/com/google/gson/internal/JavaVersion.java b/gson/src/main/java/com/google/gson/internal/JavaVersion.java index af981d5699..fc08057dca 100644 --- a/gson/src/main/java/com/google/gson/internal/JavaVersion.java +++ b/gson/src/main/java/com/google/gson/internal/JavaVersion.java @@ -27,11 +27,11 @@ public final class JavaVersion { private static int determineMajorJavaVersion() { String javaVersion = System.getProperty("java.version"); - return getMajorJavaVersion(javaVersion); + return parseMajorJavaVersion(javaVersion); } // Visible for testing only - static int getMajorJavaVersion(String javaVersion) { + static int parseMajorJavaVersion(String javaVersion) { int version = parseDotted(javaVersion); if (version == -1) { version = extractBeginningInt(javaVersion); diff --git a/gson/src/main/java/com/google/gson/internal/JsonReaderInternalAccess.java b/gson/src/main/java/com/google/gson/internal/JsonReaderInternalAccess.java index 776b7639df..e3d4873d79 100644 --- a/gson/src/main/java/com/google/gson/internal/JsonReaderInternalAccess.java +++ b/gson/src/main/java/com/google/gson/internal/JsonReaderInternalAccess.java @@ -21,7 +21,10 @@ /** Internal-only APIs of JsonReader available only to other classes in Gson. */ public abstract class JsonReaderInternalAccess { - public static JsonReaderInternalAccess INSTANCE; + // Suppress warnings because field is initialized by `JsonReader` class during class loading + // (and therefore should be thread-safe), and any usage appears after `JsonReader` was loaded + @SuppressWarnings({"ConstantField", "NonFinalStaticField"}) + public static volatile JsonReaderInternalAccess INSTANCE; /** Changes the type of the current property name token to a string value. */ public abstract void promoteNameToValue(JsonReader reader) throws IOException; 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 5058b3667b..099dd573c0 100644 --- a/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java +++ b/gson/src/main/java/com/google/gson/internal/LinkedTreeMap.java @@ -233,7 +233,7 @@ Node findByEntry(Entry entry) { return valuesEqual ? mine : null; } - private boolean equal(Object a, Object b) { + private static boolean equal(Object a, Object b) { return Objects.equals(a, b); } diff --git a/gson/src/main/java/com/google/gson/internal/NonNullElementWrapperList.java b/gson/src/main/java/com/google/gson/internal/NonNullElementWrapperList.java index 294bf0a9e5..51008f840b 100644 --- a/gson/src/main/java/com/google/gson/internal/NonNullElementWrapperList.java +++ b/gson/src/main/java/com/google/gson/internal/NonNullElementWrapperList.java @@ -76,6 +76,7 @@ public void clear() { delegate.clear(); } + @SuppressWarnings("UngroupedOverloads") // this is intentionally ungrouped, see comment above @Override public boolean remove(Object o) { return delegate.remove(o); diff --git a/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java b/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java index 02367d9ee5..552503f25f 100644 --- a/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java +++ b/gson/src/main/java/com/google/gson/internal/PreJava9DateFormatProvider.java @@ -21,12 +21,13 @@ /** Provides DateFormats for US locale with patterns which were the default ones before Java 9. */ public class PreJava9DateFormatProvider { + private PreJava9DateFormatProvider() {} /** * Returns the same DateFormat as {@code DateFormat.getDateInstance(style, Locale.US)} in Java 8 * or below. */ - public static DateFormat getUSDateFormat(int style) { + public static DateFormat getUsDateFormat(int style) { return new SimpleDateFormat(getDateFormatPattern(style), Locale.US); } @@ -34,7 +35,7 @@ public static DateFormat getUSDateFormat(int style) { * Returns the same DateFormat as {@code DateFormat.getDateTimeInstance(dateStyle, timeStyle, * Locale.US)} in Java 8 or below. */ - public static DateFormat getUSDateTimeFormat(int dateStyle, int timeStyle) { + public static DateFormat getUsDateTimeFormat(int dateStyle, int timeStyle) { String pattern = getDatePartOfDateTimePattern(dateStyle) + " " + getTimePartOfDateTimePattern(timeStyle); return new SimpleDateFormat(pattern, Locale.US); diff --git a/gson/src/main/java/com/google/gson/internal/Primitives.java b/gson/src/main/java/com/google/gson/internal/Primitives.java index 47b0e0eedf..3397ea20e5 100644 --- a/gson/src/main/java/com/google/gson/internal/Primitives.java +++ b/gson/src/main/java/com/google/gson/internal/Primitives.java @@ -60,7 +60,7 @@ public static boolean isWrapperType(Type type) { * wrap(String.class) == String.class * */ - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "MissingBraces"}) public static Class wrap(Class type) { if (type == int.class) return (Class) Integer.class; if (type == float.class) return (Class) Float.class; @@ -84,7 +84,7 @@ public static Class wrap(Class type) { * unwrap(String.class) == String.class * */ - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "MissingBraces"}) public static Class unwrap(Class type) { if (type == Integer.class) return (Class) int.class; if (type == Float.class) return (Class) float.class; 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 2435522f85..46df853f5a 100644 --- a/gson/src/main/java/com/google/gson/internal/Streams.java +++ b/gson/src/main/java/com/google/gson/internal/Streams.java @@ -81,6 +81,7 @@ private static final class AppendableWriter extends Writer { this.appendable = appendable; } + @SuppressWarnings("UngroupedOverloads") // this is intentionally ungrouped, see comment below @Override public void write(char[] chars, int offset, int length) throws IOException { currentWrite.setChars(chars); 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 4a371348a0..3595e830ef 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 @@ -141,7 +141,7 @@ private DefaultDateTypeAdapter(DateType dateType, int style) { dateFormats.add(DateFormat.getDateInstance(style)); } if (JavaVersion.isJava9OrLater()) { - dateFormats.add(PreJava9DateFormatProvider.getUSDateFormat(style)); + dateFormats.add(PreJava9DateFormatProvider.getUsDateFormat(style)); } } @@ -152,7 +152,7 @@ private DefaultDateTypeAdapter(DateType dateType, int dateStyle, int timeStyl dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle)); } if (JavaVersion.isJava9OrLater()) { - dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(dateStyle, timeStyle)); + dateFormats.add(PreJava9DateFormatProvider.getUsDateTimeFormat(dateStyle, timeStyle)); } } 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 0ce1b0317a..822956742c 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 @@ -67,7 +67,7 @@ public JsonAdapterAnnotationTypeAdapterFactory(ConstructorConstructor constructo } // Separate helper method to make sure callers retrieve annotation in a consistent way - private JsonAdapter getAnnotation(Class rawType) { + private static JsonAdapter getAnnotation(Class rawType) { return rawType.getAnnotation(JsonAdapter.class); } 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 d8e1ebe759..fc23c2d53d 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 @@ -371,13 +371,13 @@ private String getPath(boolean usePreviousPath) { } @Override - public String getPreviousPath() { - return getPath(true); + public String getPath() { + return getPath(false); } @Override - public String getPath() { - return getPath(false); + public String getPreviousPath() { + return getPath(true); } private String locationString() { diff --git a/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java b/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java index 3aa8b22d46..fda2cf131c 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java +++ b/gson/src/main/java/com/google/gson/internal/bind/JsonTreeWriter.java @@ -167,18 +167,6 @@ public JsonWriter value(String value) throws IOException { return this; } - @Override - public JsonWriter jsonValue(String value) throws IOException { - throw new UnsupportedOperationException(); - } - - @CanIgnoreReturnValue - @Override - public JsonWriter nullValue() throws IOException { - put(JsonNull.INSTANCE); - return this; - } - @CanIgnoreReturnValue @Override public JsonWriter value(boolean value) throws IOException { @@ -241,6 +229,18 @@ public JsonWriter value(Number value) throws IOException { return this; } + @CanIgnoreReturnValue + @Override + public JsonWriter nullValue() throws IOException { + put(JsonNull.INSTANCE); + return this; + } + + @Override + public JsonWriter jsonValue(String value) throws IOException { + throw new UnsupportedOperationException(); + } + @Override public void flush() throws IOException {} 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 56de0ea3a8..7cf9387bd4 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 @@ -145,7 +145,7 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { } /** Returns a type adapter that writes the value as a string. */ - private TypeAdapter getKeyAdapter(Gson context, Type keyType) { + private static TypeAdapter getKeyAdapter(Gson context, Type keyType) { return (keyType == boolean.class || keyType == Boolean.class) ? TypeAdapters.BOOLEAN_AS_STRING : context.getAdapter(TypeToken.get(keyType)); 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 20d1606291..81c9e1e94e 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 @@ -74,7 +74,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 static Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { switch (peeked) { case BEGIN_ARRAY: in.beginArray(); 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 06925d9e8b..90869c6393 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 @@ -172,7 +172,9 @@ private BoundField createBoundField( constructorConstructor, context, fieldType, annotation, false); } final boolean jsonAdapterPresent = mapped != null; - if (mapped == null) mapped = context.getAdapter(fieldType); + if (mapped == null) { + mapped = context.getAdapter(fieldType); + } @SuppressWarnings("unchecked") final TypeAdapter typeAdapter = (TypeAdapter) mapped; 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 5d4bd1b5a2..2462546e4f 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 @@ -594,7 +594,7 @@ public URL read(JsonReader in) throws IOException { return null; } String nextString = in.nextString(); - return "null".equals(nextString) ? null : new URL(nextString); + return nextString.equals("null") ? null : new URL(nextString); } @Override @@ -615,7 +615,7 @@ public URI read(JsonReader in) throws IOException { } try { String nextString = in.nextString(); - return "null".equals(nextString) ? null : new URI(nextString); + return nextString.equals("null") ? null : new URI(nextString); } catch (URISyntaxException e) { throw new JsonIOException(e); } @@ -724,17 +724,17 @@ public Calendar read(JsonReader in) throws IOException { while (in.peek() != JsonToken.END_OBJECT) { String name = in.nextName(); int value = in.nextInt(); - if (YEAR.equals(name)) { + if (name.equals(YEAR)) { year = value; - } else if (MONTH.equals(name)) { + } else if (name.equals(MONTH)) { month = value; - } else if (DAY_OF_MONTH.equals(name)) { + } else if (name.equals(DAY_OF_MONTH)) { dayOfMonth = value; - } else if (HOUR_OF_DAY.equals(name)) { + } else if (name.equals(HOUR_OF_DAY)) { hourOfDay = value; - } else if (MINUTE.equals(name)) { + } else if (name.equals(MINUTE)) { minute = value; - } else if (SECOND.equals(name)) { + } else if (name.equals(SECOND)) { second = value; } } @@ -1030,6 +1030,7 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { } }; + @SuppressWarnings("TypeParameterNaming") public static TypeAdapterFactory newFactory( final TypeToken type, final TypeAdapter typeAdapter) { return new TypeAdapterFactory() { @@ -1041,6 +1042,7 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { }; } + @SuppressWarnings("TypeParameterNaming") public static TypeAdapterFactory newFactory( final Class type, final TypeAdapter typeAdapter) { return new TypeAdapterFactory() { @@ -1057,6 +1059,7 @@ public String toString() { }; } + @SuppressWarnings("TypeParameterNaming") public static TypeAdapterFactory newFactory( final Class unboxed, final Class boxed, final TypeAdapter typeAdapter) { return new TypeAdapterFactory() { @@ -1080,6 +1083,7 @@ public String toString() { }; } + @SuppressWarnings("TypeParameterNaming") public static TypeAdapterFactory newFactoryForMultipleTypes( final Class base, final Class sub, diff --git a/gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java b/gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java index 05dbafa096..28074a10d1 100644 --- a/gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java +++ b/gson/src/main/java/com/google/gson/internal/bind/util/ISO8601Utils.java @@ -36,6 +36,8 @@ // Date parsing code from Jackson databind ISO8601Utils.java // https://github.com/FasterXML/jackson-databind/blob/2.8/src/main/java/com/fasterxml/jackson/databind/util/ISO8601Utils.java public class ISO8601Utils { + private ISO8601Utils() {} + /** * ID to represent the 'UTC' string, default timezone since Jackson 2.7 * @@ -197,7 +199,9 @@ public static Date parse(String date, ParsePosition pos) throws ParseException { char c = date.charAt(offset); if (c != 'Z' && c != '+' && c != '-') { seconds = parseInt(date, offset, offset += 2); - if (seconds > 59 && seconds < 63) seconds = 59; // truncate up to 3 leap seconds + if (seconds > 59 && seconds < 63) { + seconds = 59; // truncate up to 3 leap seconds + } // milliseconds can be optional in the format if (checkOffset(date, offset, '.')) { offset += 1; @@ -241,7 +245,7 @@ public static Date parse(String date, ParsePosition pos) throws ParseException { offset += timezoneOffset.length(); // 18-Jun-2015, tatu: Minor simplification, skip offset of "+0000"/"+00:00" - if ("+0000".equals(timezoneOffset) || "+00:00".equals(timezoneOffset)) { + if (timezoneOffset.equals("+0000") || timezoneOffset.equals("+00:00")) { timezone = TIMEZONE_UTC; } else { // 18-Jun-2015, tatu: Looks like offsets only work from GMT, not UTC... @@ -372,7 +376,9 @@ private static void padInt(StringBuilder buffer, int value, int length) { private static int indexOfNonDigit(String string, int offset) { for (int i = offset; i < string.length(); i++) { char c = string.charAt(i); - if (c < '0' || c > '9') return i; + if (c < '0' || c > '9') { + return i; + } } return string.length(); } diff --git a/gson/src/main/java/com/google/gson/stream/JsonReader.java b/gson/src/main/java/com/google/gson/stream/JsonReader.java index 2f6cae5faf..2dc4e65402 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonReader.java +++ b/gson/src/main/java/com/google/gson/stream/JsonReader.java @@ -1141,6 +1141,8 @@ private String nextUnquotedValue() throws IOException { case '\r': case '\n': break findNonLiteralCharacter; + default: + // skip character to be included in string value } } @@ -1223,6 +1225,8 @@ private void skipUnquotedValue() throws IOException { case '\n': pos += i; return; + default: + // skip the character } } pos += i; @@ -1380,6 +1384,7 @@ public void skipValue() throws IOException { case PEEKED_EOF: // Do nothing return; + default: // For all other tokens there is nothing to do; token has already been consumed from // underlying reader } @@ -1586,7 +1591,8 @@ String locationString() { private String getPath(boolean usePreviousPath) { StringBuilder result = new StringBuilder().append('$'); for (int i = 0; i < stackSize; i++) { - switch (stack[i]) { + int scope = stack[i]; + switch (scope) { case JsonScope.EMPTY_ARRAY: case JsonScope.NONEMPTY_ARRAY: int pathIndex = pathIndices[i]; @@ -1608,6 +1614,8 @@ private String getPath(boolean usePreviousPath) { case JsonScope.EMPTY_DOCUMENT: case JsonScope.CLOSED: break; + default: + throw new AssertionError("Unknown scope value: " + scope); } } return result.toString(); @@ -1615,38 +1623,38 @@ private String getPath(boolean usePreviousPath) { /** * Returns a JSONPath in dot-notation - * to the previous (or current) location in the JSON document. That means: + * to the next (or current) location in the JSON document. That means: * *
    - *
  • For JSON arrays the path points to the index of the previous element.
    - * If no element has been consumed yet it uses the index 0 (even if there are no elements). + *
  • For JSON arrays the path points to the index of the next element (even if there are no + * further elements). *
  • For JSON objects the path points to the last property, or to the current property if its * name has already been consumed. *
* - *

This method can be useful to add additional context to exception messages after a - * value has been consumed. + *

This method can be useful to add additional context to exception messages before a + * value is consumed, for example when the {@linkplain #peek() peeked} token is unexpected. */ - public String getPreviousPath() { - return getPath(true); + public String getPath() { + return getPath(false); } /** * Returns a JSONPath in dot-notation - * to the next (or current) location in the JSON document. That means: + * to the previous (or current) location in the JSON document. That means: * *

    - *
  • For JSON arrays the path points to the index of the next element (even if there are no - * further elements). + *
  • For JSON arrays the path points to the index of the previous element.
    + * If no element has been consumed yet it uses the index 0 (even if there are no elements). *
  • For JSON objects the path points to the last property, or to the current property if its * name has already been consumed. *
* - *

This method can be useful to add additional context to exception messages before a - * value is consumed, for example when the {@linkplain #peek() peeked} token is unexpected. + *

This method can be useful to add additional context to exception messages after a + * value has been consumed. */ - public String getPath() { - return getPath(false); + public String getPreviousPath() { + return getPath(true); } /** diff --git a/gson/src/main/java/com/google/gson/stream/JsonScope.java b/gson/src/main/java/com/google/gson/stream/JsonScope.java index f77b53da7c..16259578c3 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonScope.java +++ b/gson/src/main/java/com/google/gson/stream/JsonScope.java @@ -23,6 +23,7 @@ * @since 1.6 */ final class JsonScope { + private JsonScope() {} /** An array with no elements requires no separator before the next element. */ static final int EMPTY_ARRAY = 1; diff --git a/gson/src/main/java/com/google/gson/stream/JsonWriter.java b/gson/src/main/java/com/google/gson/stream/JsonWriter.java index fd0b6b8a65..498a0ab4e1 100644 --- a/gson/src/main/java/com/google/gson/stream/JsonWriter.java +++ b/gson/src/main/java/com/google/gson/stream/JsonWriter.java @@ -396,7 +396,7 @@ public final boolean getSerializeNulls() { @CanIgnoreReturnValue public JsonWriter beginArray() throws IOException { writeDeferredName(); - return open(EMPTY_ARRAY, '['); + return openScope(EMPTY_ARRAY, '['); } /** @@ -406,7 +406,7 @@ public JsonWriter beginArray() throws IOException { */ @CanIgnoreReturnValue public JsonWriter endArray() throws IOException { - return close(EMPTY_ARRAY, NONEMPTY_ARRAY, ']'); + return closeScope(EMPTY_ARRAY, NONEMPTY_ARRAY, ']'); } /** @@ -418,7 +418,7 @@ public JsonWriter endArray() throws IOException { @CanIgnoreReturnValue public JsonWriter beginObject() throws IOException { writeDeferredName(); - return open(EMPTY_OBJECT, '{'); + return openScope(EMPTY_OBJECT, '{'); } /** @@ -428,12 +428,12 @@ public JsonWriter beginObject() throws IOException { */ @CanIgnoreReturnValue public JsonWriter endObject() throws IOException { - return close(EMPTY_OBJECT, NONEMPTY_OBJECT, '}'); + return closeScope(EMPTY_OBJECT, NONEMPTY_OBJECT, '}'); } /** Enters a new scope by appending any necessary whitespace and the given bracket. */ @CanIgnoreReturnValue - private JsonWriter open(int empty, char openBracket) throws IOException { + private JsonWriter openScope(int empty, char openBracket) throws IOException { beforeValue(); push(empty); out.write(openBracket); @@ -442,7 +442,7 @@ private JsonWriter open(int empty, char openBracket) throws IOException { /** Closes the current scope by appending any necessary whitespace and the given bracket. */ @CanIgnoreReturnValue - private JsonWriter close(int empty, int nonempty, char closeBracket) throws IOException { + private JsonWriter closeScope(int empty, int nonempty, char closeBracket) throws IOException { int context = peek(); if (context != nonempty && context != empty) { throw new IllegalStateException("Nesting problem."); @@ -524,47 +524,6 @@ public JsonWriter value(String value) throws IOException { return this; } - /** - * Writes {@code value} directly to the writer without quoting or escaping. This might not be - * supported by all implementations, if not supported an {@code UnsupportedOperationException} is - * thrown. - * - * @param value the literal string value, or null to encode a null literal. - * @return this writer. - * @throws UnsupportedOperationException if this writer does not support writing raw JSON values. - * @since 2.4 - */ - @CanIgnoreReturnValue - public JsonWriter jsonValue(String value) throws IOException { - if (value == null) { - return nullValue(); - } - writeDeferredName(); - beforeValue(); - out.append(value); - return this; - } - - /** - * Encodes {@code null}. - * - * @return this writer. - */ - @CanIgnoreReturnValue - public JsonWriter nullValue() throws IOException { - if (deferredName != null) { - if (serializeNulls) { - writeDeferredName(); - } else { - deferredName = null; - return this; // skip the name and the value - } - } - beforeValue(); - out.write("null"); - return this; - } - /** * Encodes {@code value}. * @@ -649,25 +608,6 @@ public JsonWriter value(long value) throws IOException { return this; } - /** - * Returns whether the {@code toString()} of {@code c} can be trusted to return a valid JSON - * number. - */ - private static boolean isTrustedNumberType(Class c) { - // Note: Don't consider LazilyParsedNumber trusted because it could contain - // an arbitrary malformed string - return c == Integer.class - || c == Long.class - || c == Double.class - || c == Float.class - || c == Byte.class - || c == Short.class - || c == BigDecimal.class - || c == BigInteger.class - || c == AtomicInteger.class - || c == AtomicLong.class; - } - /** * Encodes {@code value}. The value is written by directly writing the {@link Number#toString()} * result to JSON. Implementations must make sure that the result represents a valid JSON number. @@ -706,6 +646,47 @@ public JsonWriter value(Number value) throws IOException { return this; } + /** + * Encodes {@code null}. + * + * @return this writer. + */ + @CanIgnoreReturnValue + public JsonWriter nullValue() throws IOException { + if (deferredName != null) { + if (serializeNulls) { + writeDeferredName(); + } else { + deferredName = null; + return this; // skip the name and the value + } + } + beforeValue(); + out.write("null"); + return this; + } + + /** + * Writes {@code value} directly to the writer without quoting or escaping. This might not be + * supported by all implementations, if not supported an {@code UnsupportedOperationException} is + * thrown. + * + * @param value the literal string value, or null to encode a null literal. + * @return this writer. + * @throws UnsupportedOperationException if this writer does not support writing raw JSON values. + * @since 2.4 + */ + @CanIgnoreReturnValue + public JsonWriter jsonValue(String value) throws IOException { + if (value == null) { + return nullValue(); + } + writeDeferredName(); + beforeValue(); + out.append(value); + return this; + } + /** * Ensures all buffered data is written to the underlying {@link Writer} and flushes that writer. */ @@ -733,6 +714,25 @@ public void close() throws IOException { stackSize = 0; } + /** + * Returns whether the {@code toString()} of {@code c} can be trusted to return a valid JSON + * number. + */ + private static boolean isTrustedNumberType(Class c) { + // Note: Don't consider LazilyParsedNumber trusted because it could contain + // an arbitrary malformed string + return c == Integer.class + || c == Long.class + || c == Double.class + || c == Float.class + || c == Byte.class + || c == Short.class + || c == BigDecimal.class + || c == BigInteger.class + || c == AtomicInteger.class + || c == AtomicLong.class; + } + private void string(String value) throws IOException { String[] replacements = htmlSafe ? HTML_SAFE_REPLACEMENT_CHARS : REPLACEMENT_CHARS; out.write('\"'); diff --git a/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java b/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java index aefb2125fd..0d085269f8 100644 --- a/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java +++ b/gson/src/test/java/com/google/gson/FieldNamingPolicyTest.java @@ -115,7 +115,7 @@ class Dummy { @Test public void testLowerCasingLocaleIndependent() throws Exception { class Dummy { - @SuppressWarnings("unused") + @SuppressWarnings({"unused", "ConstantField"}) int I; } diff --git a/gson/src/test/java/com/google/gson/GsonTypeAdapterTest.java b/gson/src/test/java/com/google/gson/GsonTypeAdapterTest.java index 0825c8f8ed..6422bacc42 100644 --- a/gson/src/test/java/com/google/gson/GsonTypeAdapterTest.java +++ b/gson/src/test/java/com/google/gson/GsonTypeAdapterTest.java @@ -151,7 +151,7 @@ public void testDeserializerForAbstractClass() { assertSerialized("{\"b\":\"beep\",\"a\":\"android\"}", Concrete.class, false, false, instance); } - private void assertSerialized( + private static void assertSerialized( String expected, Class instanceType, boolean registerAbstractDeserializer, diff --git a/gson/src/test/java/com/google/gson/JavaSerializationTest.java b/gson/src/test/java/com/google/gson/JavaSerializationTest.java index d18a6f3658..219e16bb56 100644 --- a/gson/src/test/java/com/google/gson/JavaSerializationTest.java +++ b/gson/src/test/java/com/google/gson/JavaSerializationTest.java @@ -66,7 +66,7 @@ public void testNumberIsSerializable() throws Exception { } @SuppressWarnings("unchecked") // Serialization promises to return the same type. - private T serializedCopy(T object) throws IOException, ClassNotFoundException { + private static T serializedCopy(T object) throws IOException, ClassNotFoundException { ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bytesOut); out.writeObject(object); diff --git a/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java b/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java index fa4d96dbfb..9787558dd1 100644 --- a/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java +++ b/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java @@ -33,6 +33,7 @@ * @author Joel Leitch */ public class ParameterizedTypeFixtures { + private ParameterizedTypeFixtures() {} public static final class MyParameterizedType { public final T value; @@ -50,7 +51,7 @@ public String getExpectedJson() { return String.format("{\"value\":%s}", valueAsJson); } - private String getExpectedJson(Object obj) { + private static String getExpectedJson(Object obj) { Class clazz = obj.getClass(); if (Primitives.isWrapperType(Primitives.wrap(clazz))) { return obj.toString(); diff --git a/gson/src/test/java/com/google/gson/common/MoreAsserts.java b/gson/src/test/java/com/google/gson/common/MoreAsserts.java index 39128fbf3e..3b74056dcc 100644 --- a/gson/src/test/java/com/google/gson/common/MoreAsserts.java +++ b/gson/src/test/java/com/google/gson/common/MoreAsserts.java @@ -30,6 +30,7 @@ * @author Inderjeet Singh */ public class MoreAsserts { + private MoreAsserts() {} /** * Asserts that the specified {@code value} is not present in {@code collection} diff --git a/gson/src/test/java/com/google/gson/common/TestTypes.java b/gson/src/test/java/com/google/gson/common/TestTypes.java index a0fde26c77..b41f4b36da 100644 --- a/gson/src/test/java/com/google/gson/common/TestTypes.java +++ b/gson/src/test/java/com/google/gson/common/TestTypes.java @@ -36,6 +36,7 @@ * @author Joel Leitch */ public class TestTypes { + private TestTypes() {} public static class Base { public static final String BASE_NAME = Base.class.getSimpleName(); diff --git a/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java b/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java index 7499aa8a42..e94956e7dd 100644 --- a/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java +++ b/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java @@ -224,7 +224,7 @@ private static class Derived extends Base { int derivedValue = 3; } - private Gson createGsonObjectWithFooTypeAdapter() { + private static Gson createGsonObjectWithFooTypeAdapter() { return new GsonBuilder().registerTypeAdapter(Foo.class, new FooTypeAdapter()).create(); } diff --git a/gson/src/test/java/com/google/gson/functional/EscapingTest.java b/gson/src/test/java/com/google/gson/functional/EscapingTest.java index 1383c67cbe..1eeeb1768d 100644 --- a/gson/src/test/java/com/google/gson/functional/EscapingTest.java +++ b/gson/src/test/java/com/google/gson/functional/EscapingTest.java @@ -70,8 +70,8 @@ public void testEscapingObjectFields() { assertThat(jsonRepresentation).doesNotContain(">"); assertThat(jsonRepresentation).contains("\\\""); - BagOfPrimitives expectedObject = gson.fromJson(jsonRepresentation, BagOfPrimitives.class); - assertThat(objWithPrimitives.getExpectedJson()).isEqualTo(expectedObject.getExpectedJson()); + BagOfPrimitives deserialized = gson.fromJson(jsonRepresentation, BagOfPrimitives.class); + assertThat(deserialized.getExpectedJson()).isEqualTo(objWithPrimitives.getExpectedJson()); } @Test diff --git a/gson/src/test/java/com/google/gson/functional/FieldNamingTest.java b/gson/src/test/java/com/google/gson/functional/FieldNamingTest.java index 308fe1aa5d..36f03f2889 100644 --- a/gson/src/test/java/com/google/gson/functional/FieldNamingTest.java +++ b/gson/src/test/java/com/google/gson/functional/FieldNamingTest.java @@ -91,11 +91,12 @@ public void testLowerCaseWithDashes() { + "'annotatedName':7,'lower-id':8,'_9':9}"); } - private Gson getGsonWithNamingPolicy(FieldNamingPolicy fieldNamingPolicy) { + private static Gson getGsonWithNamingPolicy(FieldNamingPolicy fieldNamingPolicy) { return new GsonBuilder().setFieldNamingPolicy(fieldNamingPolicy).create(); } - @SuppressWarnings("unused") // fields are used reflectively + // Suppress because fields are used reflectively, and the names are intentionally unconventional + @SuppressWarnings({"unused", "MemberName", "ConstantField"}) private static class TestNames { int lowerCamel = 1; int UpperCamel = 2; diff --git a/gson/src/test/java/com/google/gson/functional/GsonVersionDiagnosticsTest.java b/gson/src/test/java/com/google/gson/functional/GsonVersionDiagnosticsTest.java index d47aed1aa8..1cbeb4156e 100644 --- a/gson/src/test/java/com/google/gson/functional/GsonVersionDiagnosticsTest.java +++ b/gson/src/test/java/com/google/gson/functional/GsonVersionDiagnosticsTest.java @@ -79,7 +79,7 @@ public void testAssertionErrorInDeserializationPrintsVersion() { ensureAssertionErrorPrintsGsonVersion(e); } - private void ensureAssertionErrorPrintsGsonVersion(AssertionError expected) { + private static void ensureAssertionErrorPrintsGsonVersion(AssertionError expected) { String msg = expected.getMessage(); // System.err.println(msg); int start = msg.indexOf("(GSON"); diff --git a/gson/src/test/java/com/google/gson/functional/InheritanceTest.java b/gson/src/test/java/com/google/gson/functional/InheritanceTest.java index b2268fcd77..f41b133fb3 100644 --- a/gson/src/test/java/com/google/gson/functional/InheritanceTest.java +++ b/gson/src/test/java/com/google/gson/functional/InheritanceTest.java @@ -275,7 +275,7 @@ public String getExpectedJson() { } @CanIgnoreReturnValue - private StringBuilder append(StringBuilder sb, Collection c) { + private static StringBuilder append(StringBuilder sb, Collection c) { sb.append("["); boolean first = true; for (Object o : c) { diff --git a/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java b/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java index 37a17f89d8..437fe8124e 100644 --- a/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java +++ b/gson/src/test/java/com/google/gson/functional/Java17RecordTest.java @@ -354,6 +354,7 @@ public void testStaticFieldDeserialization() { } private record RecordWithStaticField() { + @SuppressWarnings("NonFinalStaticField") static String s = "initial"; } diff --git a/gson/src/test/java/com/google/gson/functional/JsonAdapterAnnotationOnClassesTest.java b/gson/src/test/java/com/google/gson/functional/JsonAdapterAnnotationOnClassesTest.java index 7ca84d7a01..3a765f1352 100644 --- a/gson/src/test/java/com/google/gson/functional/JsonAdapterAnnotationOnClassesTest.java +++ b/gson/src/test/java/com/google/gson/functional/JsonAdapterAnnotationOnClassesTest.java @@ -44,6 +44,7 @@ import org.junit.Test; /** Functional tests for the {@link JsonAdapter} annotation on classes. */ +@SuppressWarnings("ClassNamedLikeTypeParameter") // for dummy classes A, B, ... public final class JsonAdapterAnnotationOnClassesTest { @Test @@ -305,7 +306,8 @@ private static final class ClassWithIncorrectJsonAdapter { // This class is used in JsonAdapter Javadoc as an example @JsonAdapter(UserJsonAdapter.class) private static class User { - final String firstName, lastName; + final String firstName; + final String lastName; User(String firstName, String lastName) { this.firstName = firstName; diff --git a/gson/src/test/java/com/google/gson/functional/JsonAdapterSerializerDeserializerTest.java b/gson/src/test/java/com/google/gson/functional/JsonAdapterSerializerDeserializerTest.java index 090db3ac62..393aebe4a6 100644 --- a/gson/src/test/java/com/google/gson/functional/JsonAdapterSerializerDeserializerTest.java +++ b/gson/src/test/java/com/google/gson/functional/JsonAdapterSerializerDeserializerTest.java @@ -240,6 +240,7 @@ public void write(JsonWriter out, User value) throws IOException { assertThat(deserialized.userDN).isNull(); } + @SuppressWarnings("MemberName") private static final class WithNullSafe { // "userS..." uses JsonSerializer @JsonAdapter(value = UserSerializer.class, nullSafe = false) diff --git a/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java b/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java index e02b0cc278..4a00f399d0 100644 --- a/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java +++ b/gson/src/test/java/com/google/gson/functional/JsonTreeTest.java @@ -89,7 +89,7 @@ public void testJsonTreeNull() { assertThat(jsonElement.has("stringValue")).isFalse(); } - private void assertContains(JsonObject json, JsonPrimitive child) { + private static void assertContains(JsonObject json, JsonPrimitive child) { for (Map.Entry entry : json.entrySet()) { JsonElement node = entry.getValue(); if (node.isJsonPrimitive()) { diff --git a/gson/src/test/java/com/google/gson/functional/MapTest.java b/gson/src/test/java/com/google/gson/functional/MapTest.java index cdc127ccc8..0bd11c4c7a 100644 --- a/gson/src/test/java/com/google/gson/functional/MapTest.java +++ b/gson/src/test/java/com/google/gson/functional/MapTest.java @@ -641,7 +641,7 @@ public void testDeserializeMapOfMaps() { assertThat(gson.fromJson(json, type)).isEqualTo(map); } - private Map newMap(K key1, V value1, K key2, V value2) { + private static Map newMap(K key1, V value1, K key2, V value2) { Map result = new LinkedHashMap<>(); result.put(key1, value1); result.put(key2, value2); diff --git a/gson/src/test/java/com/google/gson/functional/MoreSpecificTypeSerializationTest.java b/gson/src/test/java/com/google/gson/functional/MoreSpecificTypeSerializationTest.java index f9e1cb4c99..0702884143 100644 --- a/gson/src/test/java/com/google/gson/functional/MoreSpecificTypeSerializationTest.java +++ b/gson/src/test/java/com/google/gson/functional/MoreSpecificTypeSerializationTest.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Test; @@ -51,7 +52,7 @@ public void testSubclassFields() { @Test public void testListOfSubclassFields() { - Collection list = new ArrayList<>(); + List list = new ArrayList<>(); list.add(new Base(1)); list.add(new Sub(2, 3)); ClassWithContainersOfBaseFields target = new ClassWithContainersOfBaseFields(list, null); @@ -89,7 +90,7 @@ public void testParameterizedSubclassFields() { */ @Test public void testListOfParameterizedSubclassFields() { - Collection> list = new ArrayList<>(); + List> list = new ArrayList<>(); list.add(new ParameterizedBase<>("one")); list.add(new ParameterizedSub<>("two", "three")); ClassWithContainersOfParameterizedBaseFields target = diff --git a/gson/src/test/java/com/google/gson/functional/NullObjectAndFieldTest.java b/gson/src/test/java/com/google/gson/functional/NullObjectAndFieldTest.java index c0dfe1b613..d84baa4b62 100644 --- a/gson/src/test/java/com/google/gson/functional/NullObjectAndFieldTest.java +++ b/gson/src/test/java/com/google/gson/functional/NullObjectAndFieldTest.java @@ -177,12 +177,13 @@ public void testAbsentJsonElementsAreSetToNull() { public static class ClassWithInitializedMembers { // Using a mix of no-args constructor and field initializers - // Also, some fields are intialized and some are not (so initialized per JVM spec) + // Also, some fields are initialized and some are not (so initialized per JVM spec) public static final String MY_STRING_DEFAULT = "string"; private static final int MY_INT_DEFAULT = 2; private static final boolean MY_BOOLEAN_DEFAULT = true; int[] array; - String str1, str2; + String str1; + String str2; int int1 = MY_INT_DEFAULT; int int2; boolean bool1 = MY_BOOLEAN_DEFAULT; diff --git a/gson/src/test/java/com/google/gson/functional/ObjectTest.java b/gson/src/test/java/com/google/gson/functional/ObjectTest.java index 2ed8f47963..5e684ee84b 100644 --- a/gson/src/test/java/com/google/gson/functional/ObjectTest.java +++ b/gson/src/test/java/com/google/gson/functional/ObjectTest.java @@ -678,10 +678,12 @@ public void testStaticFieldDeserialization() { } } + @SuppressWarnings({"PrivateConstructorForUtilityClass", "NonFinalStaticField"}) static class ClassWithStaticField { static String s = "initial"; } + @SuppressWarnings("PrivateConstructorForUtilityClass") static class ClassWithStaticFinalField { static final String s = "initial"; } diff --git a/gson/src/test/java/com/google/gson/functional/PrettyPrintingTest.java b/gson/src/test/java/com/google/gson/functional/PrettyPrintingTest.java index 6f3def68ea..1671d50194 100644 --- a/gson/src/test/java/com/google/gson/functional/PrettyPrintingTest.java +++ b/gson/src/test/java/com/google/gson/functional/PrettyPrintingTest.java @@ -39,8 +39,6 @@ */ public class PrettyPrintingTest { - private static final boolean DEBUG = false; - private Gson gson; @Before @@ -52,31 +50,75 @@ public void setUp() throws Exception { public void testPrettyPrintList() { BagOfPrimitives b = new BagOfPrimitives(); List listOfB = new ArrayList<>(); - for (int i = 0; i < 15; ++i) { + for (int i = 0; i < 3; ++i) { listOfB.add(b); } Type typeOfSrc = new TypeToken>() {}.getType(); String json = gson.toJson(listOfB, typeOfSrc); - print(json); + assertThat(json) + .isEqualTo( + "[\n" + + " {\n" + + " \"longValue\": 0,\n" + + " \"intValue\": 0,\n" + + " \"booleanValue\": false,\n" + + " \"stringValue\": \"\"\n" + + " },\n" + + " {\n" + + " \"longValue\": 0,\n" + + " \"intValue\": 0,\n" + + " \"booleanValue\": false,\n" + + " \"stringValue\": \"\"\n" + + " },\n" + + " {\n" + + " \"longValue\": 0,\n" + + " \"intValue\": 0,\n" + + " \"booleanValue\": false,\n" + + " \"stringValue\": \"\"\n" + + " }\n" + + "]"); } @Test public void testPrettyPrintArrayOfObjects() { ArrayOfObjects target = new ArrayOfObjects(); String json = gson.toJson(target); - print(json); + assertThat(json) + .isEqualTo( + "{\n" + + " \"elements\": [\n" + + " {\n" + + " \"longValue\": 0,\n" + + " \"intValue\": 2,\n" + + " \"booleanValue\": false,\n" + + " \"stringValue\": \"i0\"\n" + + " },\n" + + " {\n" + + " \"longValue\": 1,\n" + + " \"intValue\": 3,\n" + + " \"booleanValue\": false,\n" + + " \"stringValue\": \"i1\"\n" + + " },\n" + + " {\n" + + " \"longValue\": 2,\n" + + " \"intValue\": 4,\n" + + " \"booleanValue\": false,\n" + + " \"stringValue\": \"i2\"\n" + + " }\n" + + " ]\n" + + "}"); } @Test public void testPrettyPrintArrayOfPrimitives() { - int[] ints = new int[] {1, 2, 3, 4, 5}; + int[] ints = {1, 2, 3, 4, 5}; String json = gson.toJson(ints); assertThat(json).isEqualTo("[\n 1,\n 2,\n 3,\n 4,\n 5\n]"); } @Test public void testPrettyPrintArrayOfPrimitiveArrays() { - int[][] ints = new int[][] {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}, {10}}; + int[][] ints = {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 0}, {10}}; String json = gson.toJson(ints); assertThat(json) .isEqualTo( @@ -121,14 +163,8 @@ private static class ClassWithMap { @Test public void testMultipleArrays() { - int[][][] ints = new int[][][] {{{1}, {2}}}; + int[][][] ints = {{{1}, {2}}}; String json = gson.toJson(ints); assertThat(json).isEqualTo("[\n [\n [\n 1\n ],\n [\n 2\n ]\n ]\n]"); } - - private void print(String msg) { - if (DEBUG) { - System.out.println(msg); - } - } } diff --git a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java index 175b2809ed..2c51f09750 100644 --- a/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java +++ b/gson/src/test/java/com/google/gson/functional/PrimitiveTest.java @@ -526,7 +526,7 @@ public void testMoreSpecificSerialization() { assertThat(actualJson).isNotEqualTo(expectedJson); } - private String extractElementFromArray(String json) { + private static String extractElementFromArray(String json) { return json.substring(json.indexOf('[') + 1, json.indexOf(']')); } diff --git a/gson/src/test/java/com/google/gson/functional/ReflectionAccessFilterTest.java b/gson/src/test/java/com/google/gson/functional/ReflectionAccessFilterTest.java index a3ea4340b9..ba06a190d2 100644 --- a/gson/src/test/java/com/google/gson/functional/ReflectionAccessFilterTest.java +++ b/gson/src/test/java/com/google/gson/functional/ReflectionAccessFilterTest.java @@ -152,7 +152,7 @@ public void testBlockAllJavaExtendingJdkClass() { } private static class ClassWithStaticField { - @SuppressWarnings("unused") + @SuppressWarnings({"unused", "NonFinalStaticField"}) private static int i = 1; } diff --git a/gson/src/test/java/com/google/gson/functional/TypeAdapterPrecedenceTest.java b/gson/src/test/java/com/google/gson/functional/TypeAdapterPrecedenceTest.java index fc51836f3e..0252ec5052 100644 --- a/gson/src/test/java/com/google/gson/functional/TypeAdapterPrecedenceTest.java +++ b/gson/src/test/java/com/google/gson/functional/TypeAdapterPrecedenceTest.java @@ -139,7 +139,7 @@ private Foo(String name) { } } - private JsonSerializer newSerializer(final String name) { + private static JsonSerializer newSerializer(final String name) { return new JsonSerializer() { @Override public JsonElement serialize(Foo src, Type typeOfSrc, JsonSerializationContext context) { @@ -148,7 +148,7 @@ public JsonElement serialize(Foo src, Type typeOfSrc, JsonSerializationContext c }; } - private JsonDeserializer newDeserializer(final String name) { + private static JsonDeserializer newDeserializer(final String name) { return new JsonDeserializer() { @Override public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { @@ -157,7 +157,7 @@ public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContex }; } - private TypeAdapter newTypeAdapter(final String name) { + private static TypeAdapter newTypeAdapter(final String name) { return new TypeAdapter() { @Override public Foo read(JsonReader in) throws IOException { diff --git a/gson/src/test/java/com/google/gson/functional/VersioningTest.java b/gson/src/test/java/com/google/gson/functional/VersioningTest.java index bfaca22286..698cf60ddd 100644 --- a/gson/src/test/java/com/google/gson/functional/VersioningTest.java +++ b/gson/src/test/java/com/google/gson/functional/VersioningTest.java @@ -85,9 +85,12 @@ public void testVersionedClassesSerialization() { public void testVersionedClassesDeserialization() { Gson gson = gsonWithVersion(1.0); String json = "{\"a\":3,\"b\":4,\"c\":5}"; + Version1 version1 = gson.fromJson(json, Version1.class); assertThat(version1.a).isEqualTo(3); assertThat(version1.b).isEqualTo(4); + + @SuppressWarnings("MemberName") Version1_1 version1_1 = gson.fromJson(json, Version1_1.class); assertThat(version1_1.a).isEqualTo(3); assertThat(version1_1.b).isEqualTo(4); @@ -104,6 +107,8 @@ public void testIgnoreLaterVersionClassSerialization() { public void testIgnoreLaterVersionClassDeserialization() { Gson gson = gsonWithVersion(1.0); String json = "{\"a\":3,\"b\":4,\"c\":5,\"d\":6}"; + + @SuppressWarnings("MemberName") Version1_2 version1_2 = gson.fromJson(json, Version1_2.class); // Since the class is versioned to be after 1.0, we expect null // This is the new behavior in Gson 2.0 diff --git a/gson/src/test/java/com/google/gson/internal/GsonTypesTest.java b/gson/src/test/java/com/google/gson/internal/GsonTypesTest.java index 8c133a7888..1e9d613e4a 100644 --- a/gson/src/test/java/com/google/gson/internal/GsonTypesTest.java +++ b/gson/src/test/java/com/google/gson/internal/GsonTypesTest.java @@ -24,6 +24,7 @@ import java.util.List; import org.junit.Test; +@SuppressWarnings("ClassNamedLikeTypeParameter") // for dummy classes A, B, ... public final class GsonTypesTest { @Test @@ -87,10 +88,14 @@ private final class NonStaticInner {} * type, returns null. */ public static Type getFirstTypeArgument(Type type) throws Exception { - if (!(type instanceof ParameterizedType)) return null; + if (!(type instanceof ParameterizedType)) { + return null; + } ParameterizedType ptype = (ParameterizedType) type; Type[] actualTypeArguments = ptype.getActualTypeArguments(); - if (actualTypeArguments.length == 0) return null; + if (actualTypeArguments.length == 0) { + return null; + } return $Gson$Types.canonicalize(actualTypeArguments[0]); } } diff --git a/gson/src/test/java/com/google/gson/internal/JavaVersionTest.java b/gson/src/test/java/com/google/gson/internal/JavaVersionTest.java index 44a6dc85b7..28369ffe54 100644 --- a/gson/src/test/java/com/google/gson/internal/JavaVersionTest.java +++ b/gson/src/test/java/com/google/gson/internal/JavaVersionTest.java @@ -37,49 +37,49 @@ public void testGetMajorJavaVersion() { @Test public void testJava6() { // http://www.oracle.com/technetwork/java/javase/version-6-141920.html - assertThat(JavaVersion.getMajorJavaVersion("1.6.0")).isEqualTo(6); + assertThat(JavaVersion.parseMajorJavaVersion("1.6.0")).isEqualTo(6); } @Test public void testJava7() { // http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html - assertThat(JavaVersion.getMajorJavaVersion("1.7.0")).isEqualTo(7); + assertThat(JavaVersion.parseMajorJavaVersion("1.7.0")).isEqualTo(7); } @Test public void testJava8() { - assertThat(JavaVersion.getMajorJavaVersion("1.8")).isEqualTo(8); - assertThat(JavaVersion.getMajorJavaVersion("1.8.0")).isEqualTo(8); - assertThat(JavaVersion.getMajorJavaVersion("1.8.0_131")).isEqualTo(8); - assertThat(JavaVersion.getMajorJavaVersion("1.8.0_60-ea")).isEqualTo(8); - assertThat(JavaVersion.getMajorJavaVersion("1.8.0_111-internal")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8.0")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8.0_131")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8.0_60-ea")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8.0_111-internal")).isEqualTo(8); // openjdk8 per https://github.com/AdoptOpenJDK/openjdk-build/issues/93 - assertThat(JavaVersion.getMajorJavaVersion("1.8.0-internal")).isEqualTo(8); - assertThat(JavaVersion.getMajorJavaVersion("1.8.0_131-adoptopenjdk")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8.0-internal")).isEqualTo(8); + assertThat(JavaVersion.parseMajorJavaVersion("1.8.0_131-adoptopenjdk")).isEqualTo(8); } @Test public void testJava9() { // Legacy style - assertThat(JavaVersion.getMajorJavaVersion("9.0.4")).isEqualTo(9); // Oracle JDK 9 + assertThat(JavaVersion.parseMajorJavaVersion("9.0.4")).isEqualTo(9); // Oracle JDK 9 // Debian as reported in https://github.com/google/gson/issues/1310 - assertThat(JavaVersion.getMajorJavaVersion("9-Debian")).isEqualTo(9); + assertThat(JavaVersion.parseMajorJavaVersion("9-Debian")).isEqualTo(9); // New style - assertThat(JavaVersion.getMajorJavaVersion("9-ea+19")).isEqualTo(9); - assertThat(JavaVersion.getMajorJavaVersion("9+100")).isEqualTo(9); - assertThat(JavaVersion.getMajorJavaVersion("9.0.1+20")).isEqualTo(9); - assertThat(JavaVersion.getMajorJavaVersion("9.1.1+20")).isEqualTo(9); + assertThat(JavaVersion.parseMajorJavaVersion("9-ea+19")).isEqualTo(9); + assertThat(JavaVersion.parseMajorJavaVersion("9+100")).isEqualTo(9); + assertThat(JavaVersion.parseMajorJavaVersion("9.0.1+20")).isEqualTo(9); + assertThat(JavaVersion.parseMajorJavaVersion("9.1.1+20")).isEqualTo(9); } @Test public void testJava10() { - assertThat(JavaVersion.getMajorJavaVersion("10.0.1")).isEqualTo(10); // Oracle JDK 10.0.1 + assertThat(JavaVersion.parseMajorJavaVersion("10.0.1")).isEqualTo(10); // Oracle JDK 10.0.1 } @Test public void testUnknownVersionFormat() { - assertThat(JavaVersion.getMajorJavaVersion("Java9")).isEqualTo(6); // unknown format + assertThat(JavaVersion.parseMajorJavaVersion("Java9")).isEqualTo(6); // unknown format } } diff --git a/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java b/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java index 93f736286c..fd31817c83 100644 --- a/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java +++ b/gson/src/test/java/com/google/gson/internal/LinkedTreeMapTest.java @@ -237,7 +237,7 @@ public void testJavaSerialization() throws IOException, ClassNotFoundException { @SuppressWarnings("varargs") @SafeVarargs - private final void assertIterationOrder(Iterable actual, T... expected) { + private static final void assertIterationOrder(Iterable actual, T... expected) { ArrayList actualList = new ArrayList<>(); for (T t : actual) { actualList.add(t); diff --git a/gson/src/test/java/com/google/gson/internal/bind/DefaultDateTypeAdapterTest.java b/gson/src/test/java/com/google/gson/internal/bind/DefaultDateTypeAdapterTest.java index 1aac71d2c0..3bf1568c23 100644 --- a/gson/src/test/java/com/google/gson/internal/bind/DefaultDateTypeAdapterTest.java +++ b/gson/src/test/java/com/google/gson/internal/bind/DefaultDateTypeAdapterTest.java @@ -51,7 +51,7 @@ public void testFormattingInFr() { assertFormattingAlwaysEmitsUsLocale(Locale.FRANCE); } - private void assertFormattingAlwaysEmitsUsLocale(Locale locale) { + private static void assertFormattingAlwaysEmitsUsLocale(Locale locale) { TimeZone defaultTimeZone = TimeZone.getDefault(); TimeZone.setDefault(TimeZone.getTimeZone("UTC")); Locale defaultLocale = Locale.getDefault(); diff --git a/gson/src/test/java/com/google/gson/internal/sql/SqlTypesGsonTest.java b/gson/src/test/java/com/google/gson/internal/sql/SqlTypesGsonTest.java index afc6373698..883b530a03 100644 --- a/gson/src/test/java/com/google/gson/internal/sql/SqlTypesGsonTest.java +++ b/gson/src/test/java/com/google/gson/internal/sql/SqlTypesGsonTest.java @@ -21,7 +21,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.functional.DefaultTypeAdaptersTest; -import java.sql.Date; import java.sql.Time; import java.sql.Timestamp; import java.util.Locale; @@ -30,6 +29,8 @@ import org.junit.Before; import org.junit.Test; +// Suppression for `java.sql.Date` to make it explicit that this is not `java.util.Date` +@SuppressWarnings("UnnecessarilyFullyQualified") public class SqlTypesGsonTest { private Gson gson; private TimeZone oldTimeZone; @@ -52,7 +53,7 @@ public void tearDown() throws Exception { @Test public void testNullSerializationAndDeserialization() { - testNullSerializationAndDeserialization(Date.class); + testNullSerializationAndDeserialization(java.sql.Date.class); testNullSerializationAndDeserialization(Time.class); testNullSerializationAndDeserialization(Timestamp.class); } diff --git a/gson/src/test/java/com/google/gson/metrics/PerformanceTest.java b/gson/src/test/java/com/google/gson/metrics/PerformanceTest.java index f54c70f35a..2e2add3050 100644 --- a/gson/src/test/java/com/google/gson/metrics/PerformanceTest.java +++ b/gson/src/test/java/com/google/gson/metrics/PerformanceTest.java @@ -39,6 +39,7 @@ * @author Inderjeet Singh * @author Joel Leitch */ +@SuppressWarnings("SystemOut") // allow System.out because test is for manual execution anyway public class PerformanceTest { private static final int COLLECTION_SIZE = 5000; @@ -292,7 +293,7 @@ public void testLargeGsonMapRoundTrip() throws Exception { Map unused = gson.fromJson(json, longToLong); } - private String buildJsonForClassWithList() { + private static String buildJsonForClassWithList() { StringBuilder sb = new StringBuilder("{"); sb.append("field:").append("'str',"); sb.append("list:["); @@ -301,12 +302,12 @@ private String buildJsonForClassWithList() { if (first) { first = false; } else { - sb.append(","); + sb.append(','); } sb.append("{field:'element-" + i + "'}"); } - sb.append("]"); - sb.append("}"); + sb.append(']'); + sb.append('}'); String json = sb.toString(); return json; } diff --git a/gson/src/test/java/com/google/gson/reflect/TypeTokenTest.java b/gson/src/test/java/com/google/gson/reflect/TypeTokenTest.java index aa1e2b6b20..e0277a406f 100644 --- a/gson/src/test/java/com/google/gson/reflect/TypeTokenTest.java +++ b/gson/src/test/java/com/google/gson/reflect/TypeTokenTest.java @@ -37,6 +37,9 @@ * * @author Jesse Wilson */ +// Suppress because these classes are only needed for this test, but must be top-level classes +// to not have an enclosing type +@SuppressWarnings("MultipleTopLevelClasses") public final class TypeTokenTest { // These fields are accessed using reflection by the tests below List listOfInteger = null; diff --git a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java index f6629669c6..45c14920ef 100644 --- a/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java +++ b/gson/src/test/java/com/google/gson/stream/JsonReaderTest.java @@ -884,7 +884,7 @@ public void testMalformedNumbers() throws IOException { assertNotANumber("-.0e1"); } - private void assertNotANumber(String s) throws IOException { + private static void assertNotANumber(String s) throws IOException { JsonReader reader = new JsonReader(reader(s)); reader.setStrictness(Strictness.LENIENT); assertThat(reader.peek()).isEqualTo(JsonToken.STRING); @@ -1858,6 +1858,7 @@ public void testBomForbiddenAsOtherCharacterInDocument() throws IOException { } } + @SuppressWarnings("UngroupedOverloads") @Test public void testFailWithPosition() throws IOException { testFailWithPosition("Expected value at line 6 column 5 path $[1]", "[\n\n\n\n\n\"a\",}]"); @@ -1909,7 +1910,7 @@ public void testFailWithPositionIsOffsetByBom() throws IOException { testFailWithPosition("Expected value at line 1 column 6 path $[1]", "\ufeff[\"a\",}]"); } - private void testFailWithPosition(String message, String json) throws IOException { + private static void testFailWithPosition(String message, String json) throws IOException { // Validate that it works reading the string normally. JsonReader reader1 = new JsonReader(reader(json)); reader1.setStrictness(Strictness.LENIENT); @@ -2264,7 +2265,7 @@ public void testLenientExtraCommasInMaps() throws IOException { } } - private String repeat(char c, int count) { + private static String repeat(char c, int count) { char[] array = new char[count]; Arrays.fill(array, c); return new String(array); @@ -2382,7 +2383,7 @@ private static void assertUnexpectedStructureError( + troubleshootingId); } - private void assertDocument(String document, Object... expectations) throws IOException { + private static void assertDocument(String document, Object... expectations) throws IOException { JsonReader reader = new JsonReader(reader(document)); reader.setStrictness(Strictness.LENIENT); for (Object expectation : expectations) { @@ -2419,7 +2420,7 @@ private void assertDocument(String document, Object... expectations) throws IOEx } /** Returns a reader that returns one character at a time. */ - private Reader reader(final String s) { + private static Reader reader(final String s) { /* if (true) */ return new StringReader(s); /* return new Reader() { int position = 0; diff --git a/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java b/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java index 69acaed9ff..57a2a6a18b 100644 --- a/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java +++ b/metrics/src/main/java/com/google/gson/metrics/NonUploadingCaliperRunner.java @@ -19,6 +19,8 @@ import com.google.caliper.runner.CaliperMain; class NonUploadingCaliperRunner { + private NonUploadingCaliperRunner() {} + private static String[] concat(String first, String... others) { if (others.length == 0) { return new String[] {first}; diff --git a/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java b/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java index ec8c3ffc68..4151b2abb5 100644 --- a/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java +++ b/metrics/src/main/java/com/google/gson/metrics/ParseBenchmark.java @@ -32,6 +32,7 @@ import com.google.gson.JsonParser; import com.google.gson.annotations.SerializedName; import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; import java.io.CharArrayReader; import java.io.File; import java.io.IOException; @@ -173,13 +174,12 @@ interface Parser { private static class GsonStreamParser implements Parser { @Override public void parse(char[] data, Document document) throws Exception { - com.google.gson.stream.JsonReader jsonReader = - new com.google.gson.stream.JsonReader(new CharArrayReader(data)); + JsonReader jsonReader = new JsonReader(new CharArrayReader(data)); readToken(jsonReader); jsonReader.close(); } - private void readToken(com.google.gson.stream.JsonReader reader) throws IOException { + private static void readToken(JsonReader reader) throws IOException { while (true) { switch (reader.peek()) { case BEGIN_ARRAY: @@ -211,8 +211,6 @@ private void readToken(com.google.gson.stream.JsonReader reader) throws IOExcept break; case END_DOCUMENT: return; - default: - throw new IllegalArgumentException("Unexpected token" + reader.peek()); } } } @@ -221,8 +219,7 @@ private void readToken(com.google.gson.stream.JsonReader reader) throws IOExcept private static class GsonSkipParser implements Parser { @Override public void parse(char[] data, Document document) throws Exception { - com.google.gson.stream.JsonReader jsonReader = - new com.google.gson.stream.JsonReader(new CharArrayReader(data)); + JsonReader jsonReader = new JsonReader(new CharArrayReader(data)); jsonReader.skipValue(); jsonReader.close(); } @@ -309,6 +306,7 @@ public void parse(char[] data, Document document) throws Exception { } } + @SuppressWarnings("MemberName") static class Tweet { @JsonProperty String coordinates; @JsonProperty boolean favorited; @@ -332,6 +330,7 @@ static class Tweet { @JsonProperty String in_reply_to_user_id_str; } + @SuppressWarnings("MemberName") static class User { @JsonProperty String name; @JsonProperty String profile_sidebar_border_color; diff --git a/pom.xml b/pom.xml index a3e158638a..bb896c98b8 100644 --- a/pom.xml +++ b/pom.xml @@ -226,6 +226,67 @@ -Xplugin:ErrorProne -XepExcludedPaths:.*/generated-test-sources/protobuf/.* -Xep:NotJavadoc:OFF + + -XepAllSuggestionsAsWarnings + + -Xep:AnnotationPosition + -Xep:AssertFalse + -Xep:ClassName + -Xep:ClassNamedLikeTypeParameter:WARN + -Xep:ComparisonContractViolated + -Xep:ConstantField:WARN + -Xep:DepAnn + -Xep:DifferentNameButSame + -Xep:EmptyIf + -Xep:EqualsBrokenForNull + -Xep:ForEachIterable:WARN + -Xep:FunctionalInterfaceClash + -Xep:InitializeInline + -Xep:InterfaceWithOnlyStatics + -Xep:LambdaFunctionalInterface:WARN + -Xep:LongLiteralLowerCaseSuffix + -Xep:MemberName + -Xep:MethodCanBeStatic:WARN + -Xep:MissingBraces:WARN + -Xep:MissingDefault + -Xep:MixedArrayDimensions:WARN + -Xep:MultiVariableDeclaration:WARN + -Xep:MultipleTopLevelClasses:WARN + -Xep:NonCanonicalStaticMemberImport + -Xep:NonFinalStaticField + -Xep:PackageLocation:WARN + -Xep:PrimitiveArrayPassedToVarargsMethod + -Xep:PrivateConstructorForUtilityClass:WARN + -Xep:RemoveUnusedImports:WARN + -Xep:StatementSwitchToExpressionSwitch:OFF + -Xep:StaticQualifiedUsingExpression + -Xep:SwitchDefault:WARN + -Xep:SystemExitOutsideMain + -Xep:SystemOut + -Xep:TestExceptionChecker + -Xep:ThrowSpecificExceptions:OFF + -Xep:TryFailRefactoring:OFF + -Xep:TypeParameterNaming:WARN + -Xep:UnescapedEntity + -Xep:UngroupedOverloads:WARN + -Xep:UnnecessarilyFullyQualified + -Xep:UnnecessarilyUsedValue + -Xep:UnnecessaryAnonymousClass:OFF + -Xep:UnnecessaryBoxedVariable:WARN + -Xep:UnnecessaryDefaultInEnumSwitch + -Xep:UnnecessaryFinal:OFF + -Xep:UnnecessaryStaticImport:WARN + -Xep:UnusedException + -Xep:UrlInSee + -Xep:UseCorrectAssertInTests + -Xep:UseEnumSwitch:WARN + -Xep:WildcardImport:WARN + -Xep:YodaCondition diff --git a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java index c00a272aef..a943c2f0d1 100644 --- a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java +++ b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java @@ -194,8 +194,7 @@ public static Builder newBuilder() { return new Builder(EnumSerialization.NAME, CaseFormat.LOWER_UNDERSCORE, CaseFormat.LOWER_CAMEL); } - private static final com.google.protobuf.Descriptors.FieldDescriptor.Type ENUM_TYPE = - com.google.protobuf.Descriptors.FieldDescriptor.Type.ENUM; + private static final FieldDescriptor.Type ENUM_TYPE = FieldDescriptor.Type.ENUM; private static final ConcurrentMap, Method>> mapOfMapOfMethods = new MapMaker().makeMap(); diff --git a/shrinker-test/src/main/java/com/example/GenericClasses.java b/shrinker-test/src/main/java/com/example/GenericClasses.java index cd91149be4..10d8659f18 100644 --- a/shrinker-test/src/main/java/com/example/GenericClasses.java +++ b/shrinker-test/src/main/java/com/example/GenericClasses.java @@ -8,6 +8,8 @@ import java.io.IOException; public class GenericClasses { + private GenericClasses() {} + static class GenericClass { @SerializedName("t") T t; diff --git a/shrinker-test/src/main/java/com/example/Main.java b/shrinker-test/src/main/java/com/example/Main.java index e7bf6bdacd..745200a026 100644 --- a/shrinker-test/src/main/java/com/example/Main.java +++ b/shrinker-test/src/main/java/com/example/Main.java @@ -15,6 +15,8 @@ import java.util.function.Supplier; public class Main { + private Main() {} + /** * Main entrypoint, called by {@code ShrinkingIT.test()}. * diff --git a/shrinker-test/src/main/java/com/example/NoSerializedNameMain.java b/shrinker-test/src/main/java/com/example/NoSerializedNameMain.java index 6b0d3704c7..33aa320a28 100644 --- a/shrinker-test/src/main/java/com/example/NoSerializedNameMain.java +++ b/shrinker-test/src/main/java/com/example/NoSerializedNameMain.java @@ -10,6 +10,8 @@ * therefore not matched by the default {@code gson.pro} rules. */ public class NoSerializedNameMain { + private NoSerializedNameMain() {} + static class TestClassNoArgsConstructor { // Has a no-args default constructor. public String s; diff --git a/shrinker-test/src/main/java/com/example/TestExecutor.java b/shrinker-test/src/main/java/com/example/TestExecutor.java index 09b0c94486..c5f38227db 100644 --- a/shrinker-test/src/main/java/com/example/TestExecutor.java +++ b/shrinker-test/src/main/java/com/example/TestExecutor.java @@ -5,6 +5,8 @@ import java.util.function.Supplier; public class TestExecutor { + private TestExecutor() {} + /** * Helper method for running individual tests. In case of an exception wraps it and includes the * {@code name} of the test to make debugging issues with the obfuscated JARs a bit easier. From 9f6813fa9ef62eea5c3c1303d8bf9dc26a8d67c2 Mon Sep 17 00:00:00 2001 From: Marcono1234 Date: Sun, 10 Dec 2023 22:18:54 +0100 Subject: [PATCH 2/2] Address review feedback --- gson/src/main/java/com/google/gson/Gson.java | 4 +- .../internal/bind/MapTypeAdapterFactory.java | 2 +- .../gson/internal/bind/ObjectTypeAdapter.java | 2 +- .../gson/internal/bind/TypeAdapters.java | 33 ++++--- .../gson/ParameterizedTypeFixtures.java | 11 +-- .../com/google/gson/PrimitiveTypeAdapter.java | 15 +-- .../functional/CustomTypeAdaptersTest.java | 2 +- pom.xml | 1 - .../gson/protobuf/ProtoTypeAdapter.java | 96 ++++++++----------- 9 files changed, 70 insertions(+), 96 deletions(-) diff --git a/gson/src/main/java/com/google/gson/Gson.java b/gson/src/main/java/com/google/gson/Gson.java index 1171a227c9..058d0bef82 100644 --- a/gson/src/main/java/com/google/gson/Gson.java +++ b/gson/src/main/java/com/google/gson/Gson.java @@ -447,7 +447,7 @@ public boolean htmlSafe() { return htmlSafe; } - private static TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { + private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { if (serializeSpecialFloatingPointValues) { return TypeAdapters.DOUBLE; } @@ -474,7 +474,7 @@ public void write(JsonWriter out, Number value) throws IOException { }; } - private static TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { + private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { if (serializeSpecialFloatingPointValues) { return TypeAdapters.FLOAT; } 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 7cf9387bd4..56de0ea3a8 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 @@ -145,7 +145,7 @@ public TypeAdapter create(Gson gson, TypeToken typeToken) { } /** Returns a type adapter that writes the value as a string. */ - private static TypeAdapter getKeyAdapter(Gson context, Type keyType) { + private TypeAdapter getKeyAdapter(Gson context, Type keyType) { return (keyType == boolean.class || keyType == Boolean.class) ? TypeAdapters.BOOLEAN_AS_STRING : context.getAdapter(TypeToken.get(keyType)); 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 81c9e1e94e..20d1606291 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 @@ -74,7 +74,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 static Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { + private Object tryBeginNesting(JsonReader in, JsonToken peeked) throws IOException { switch (peeked) { case BEGIN_ARRAY: in.beginArray(); 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 2462546e4f..53803bea32 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 @@ -724,18 +724,27 @@ public Calendar read(JsonReader in) throws IOException { while (in.peek() != JsonToken.END_OBJECT) { String name = in.nextName(); int value = in.nextInt(); - if (name.equals(YEAR)) { - year = value; - } else if (name.equals(MONTH)) { - month = value; - } else if (name.equals(DAY_OF_MONTH)) { - dayOfMonth = value; - } else if (name.equals(HOUR_OF_DAY)) { - hourOfDay = value; - } else if (name.equals(MINUTE)) { - minute = value; - } else if (name.equals(SECOND)) { - second = value; + switch (name) { + case YEAR: + year = value; + break; + case MONTH: + month = value; + break; + case DAY_OF_MONTH: + dayOfMonth = value; + break; + case HOUR_OF_DAY: + hourOfDay = value; + break; + case MINUTE: + minute = value; + break; + case SECOND: + second = value; + break; + default: + // Ignore unknown JSON property } } in.endObject(); diff --git a/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java b/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java index 9787558dd1..34b7adc70c 100644 --- a/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java +++ b/gson/src/test/java/com/google/gson/ParameterizedTypeFixtures.java @@ -19,7 +19,6 @@ import com.google.common.base.Objects; import com.google.gson.internal.$Gson$Types; import com.google.gson.internal.Primitives; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -63,15 +62,7 @@ private static String getExpectedJson(Object obj) { Method method = clazz.getMethod("getExpectedJson"); Object results = method.invoke(obj); return (String) results; - } catch (SecurityException e) { - throw new RuntimeException(e); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { + } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } diff --git a/gson/src/test/java/com/google/gson/PrimitiveTypeAdapter.java b/gson/src/test/java/com/google/gson/PrimitiveTypeAdapter.java index bc626c2c41..8b9ae41545 100644 --- a/gson/src/test/java/com/google/gson/PrimitiveTypeAdapter.java +++ b/gson/src/test/java/com/google/gson/PrimitiveTypeAdapter.java @@ -18,7 +18,6 @@ import com.google.gson.internal.Primitives; import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** @@ -45,13 +44,7 @@ public T adaptType(Object from, Class to) { try { Constructor constructor = aClass.getConstructor(String.class); return (T) constructor.newInstance(from.toString()); - } catch (NoSuchMethodException e) { - throw new JsonParseException(e); - } catch (IllegalAccessException e) { - throw new JsonParseException(e); - } catch (InvocationTargetException e) { - throw new JsonParseException(e); - } catch (InstantiationException e) { + } catch (ReflectiveOperationException e) { throw new JsonParseException(e); } } else if (Enum.class.isAssignableFrom(to)) { @@ -60,11 +53,7 @@ public T adaptType(Object from, Class to) { try { Method valuesMethod = to.getMethod("valueOf", String.class); return (T) valuesMethod.invoke(null, from.toString()); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { + } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } } else { diff --git a/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java b/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java index e94956e7dd..7499aa8a42 100644 --- a/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java +++ b/gson/src/test/java/com/google/gson/functional/CustomTypeAdaptersTest.java @@ -224,7 +224,7 @@ private static class Derived extends Base { int derivedValue = 3; } - private static Gson createGsonObjectWithFooTypeAdapter() { + private Gson createGsonObjectWithFooTypeAdapter() { return new GsonBuilder().registerTypeAdapter(Foo.class, new FooTypeAdapter()).create(); } diff --git a/pom.xml b/pom.xml index da15fb6286..c0393dcdea 100644 --- a/pom.xml +++ b/pom.xml @@ -249,7 +249,6 @@ -Xep:LambdaFunctionalInterface:WARN -Xep:LongLiteralLowerCaseSuffix -Xep:MemberName - -Xep:MethodCanBeStatic:WARN -Xep:MissingBraces:WARN -Xep:MissingDefault -Xep:MixedArrayDimensions:WARN diff --git a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java index a943c2f0d1..7b872f1885 100644 --- a/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java +++ b/proto/src/main/java/com/google/gson/protobuf/ProtoTypeAdapter.java @@ -39,7 +39,6 @@ import com.google.protobuf.Extension; import com.google.protobuf.Message; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; @@ -262,69 +261,56 @@ public Message deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo throw new IllegalStateException("only generated messages are supported"); } - try { - // Invoke the ProtoClass.newBuilder() method - Message.Builder protoBuilder = - (Message.Builder) getCachedMethod(protoClass, "newBuilder").invoke(null); + // Invoke the ProtoClass.newBuilder() method + Message.Builder protoBuilder = + (Message.Builder) getCachedMethod(protoClass, "newBuilder").invoke(null); - Message defaultInstance = - (Message) getCachedMethod(protoClass, "getDefaultInstance").invoke(null); + Message defaultInstance = + (Message) getCachedMethod(protoClass, "getDefaultInstance").invoke(null); - Descriptor protoDescriptor = - (Descriptor) getCachedMethod(protoClass, "getDescriptor").invoke(null); - // Call setters on all of the available fields - for (FieldDescriptor fieldDescriptor : protoDescriptor.getFields()) { - String jsonFieldName = - getCustSerializedName(fieldDescriptor.getOptions(), fieldDescriptor.getName()); + Descriptor protoDescriptor = + (Descriptor) getCachedMethod(protoClass, "getDescriptor").invoke(null); + // Call setters on all of the available fields + for (FieldDescriptor fieldDescriptor : protoDescriptor.getFields()) { + String jsonFieldName = + getCustSerializedName(fieldDescriptor.getOptions(), fieldDescriptor.getName()); - JsonElement jsonElement = jsonObject.get(jsonFieldName); - if (jsonElement != null && !jsonElement.isJsonNull()) { - // Do not reuse jsonFieldName here, it might have a custom value - Object fieldValue; - if (fieldDescriptor.getType() == ENUM_TYPE) { - if (jsonElement.isJsonArray()) { - // Handling array - Collection enumCollection = - new ArrayList<>(jsonElement.getAsJsonArray().size()); - for (JsonElement element : jsonElement.getAsJsonArray()) { - enumCollection.add( - findValueByNameAndExtension(fieldDescriptor.getEnumType(), element)); - } - fieldValue = enumCollection; - } else { - // No array, just a plain value - fieldValue = - findValueByNameAndExtension(fieldDescriptor.getEnumType(), jsonElement); + JsonElement jsonElement = jsonObject.get(jsonFieldName); + if (jsonElement != null && !jsonElement.isJsonNull()) { + // Do not reuse jsonFieldName here, it might have a custom value + Object fieldValue; + if (fieldDescriptor.getType() == ENUM_TYPE) { + if (jsonElement.isJsonArray()) { + // Handling array + Collection enumCollection = + new ArrayList<>(jsonElement.getAsJsonArray().size()); + for (JsonElement element : jsonElement.getAsJsonArray()) { + enumCollection.add( + findValueByNameAndExtension(fieldDescriptor.getEnumType(), element)); } - protoBuilder.setField(fieldDescriptor, fieldValue); - } else if (fieldDescriptor.isRepeated()) { - // If the type is an array, then we have to grab the type from the class. - // protobuf java field names are always lower camel case - String protoArrayFieldName = - protoFormat.to(CaseFormat.LOWER_CAMEL, fieldDescriptor.getName()) + "_"; - Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName); - Type protoArrayFieldType = protoArrayField.getGenericType(); - fieldValue = context.deserialize(jsonElement, protoArrayFieldType); - protoBuilder.setField(fieldDescriptor, fieldValue); + fieldValue = enumCollection; } else { - Object field = defaultInstance.getField(fieldDescriptor); - fieldValue = context.deserialize(jsonElement, field.getClass()); - protoBuilder.setField(fieldDescriptor, fieldValue); + // No array, just a plain value + fieldValue = findValueByNameAndExtension(fieldDescriptor.getEnumType(), jsonElement); } + protoBuilder.setField(fieldDescriptor, fieldValue); + } else if (fieldDescriptor.isRepeated()) { + // If the type is an array, then we have to grab the type from the class. + // protobuf java field names are always lower camel case + String protoArrayFieldName = + protoFormat.to(CaseFormat.LOWER_CAMEL, fieldDescriptor.getName()) + "_"; + Field protoArrayField = protoClass.getDeclaredField(protoArrayFieldName); + Type protoArrayFieldType = protoArrayField.getGenericType(); + fieldValue = context.deserialize(jsonElement, protoArrayFieldType); + protoBuilder.setField(fieldDescriptor, fieldValue); + } else { + Object field = defaultInstance.getField(fieldDescriptor); + fieldValue = context.deserialize(jsonElement, field.getClass()); + protoBuilder.setField(fieldDescriptor, fieldValue); } } - return protoBuilder.build(); - } catch (SecurityException e) { - throw new JsonParseException(e); - } catch (NoSuchMethodException e) { - throw new JsonParseException(e); - } catch (IllegalArgumentException e) { - throw new JsonParseException(e); - } catch (IllegalAccessException e) { - throw new JsonParseException(e); - } catch (InvocationTargetException e) { - throw new JsonParseException(e); } + return protoBuilder.build(); } catch (Exception e) { throw new JsonParseException("Error while parsing proto", e); }