Formatting follow-up (#2540)

* Formatting follow-up

- Adds formatting commits to .git-blame-ignore-revs so that they don't
  distract during Git blame
- Restores hard line breaks in Troubleshooting.md using `\` instead of
  trailing spaces
- Changes formatting of some string literals and comments
- Fixes accidental Javadoc and comment issues introduced by manual changes
  of formatting commit
- Fixes license header in $Gson$Types.java erroneously being a Javadoc
  comment and being reformatted
- Slightly changes `JsonReader` `getPath` and `getPreviousPath` documentation
  to help Javadoc detect first sentence as summary

* Remove `spotless:off` markers

* Add empty line before comment

* Check format for .github YAML files
This commit is contained in:
Marcono1234 2023-11-15 00:09:54 +01:00 committed by GitHub
parent d58e2c9382
commit c7c645db2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 167 additions and 127 deletions

5
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,5 @@
# Ignore commit which reformatted code
2c94c757a6a9426cc2fe47bc1c63f69e7c73b7b4
# Ignore commit which changed line endings consistently to LF
c2a0e4634a2100494159add78db2ee06f5eb9be6

View File

@ -19,7 +19,9 @@
### Checklist ### Checklist
<!-- The following checklist is mainly intended for yourself to verify that you did not miss anything --> <!-- The following checklist is mainly intended for yourself to verify that you did not miss anything -->
- [ ] New code follows the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html) - [ ] New code follows the [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html)\
This is automatically checked by `mvn verify`, but can also be checked on its own using `mvn spotless:check`.\
Style violations can be fixed using `mvn spotless:apply`; this can be done in a separate commit to verify that it did not cause undesired changes.
- [ ] If necessary, new public API validates arguments, for example rejects `null` - [ ] If necessary, new public API validates arguments, for example rejects `null`
- [ ] New public API has Javadoc - [ ] New public API has Javadoc
- [ ] Javadoc uses `@since $next-version$` - [ ] Javadoc uses `@since $next-version$`

View File

@ -127,8 +127,8 @@ For example, let's assume you want to deserialize the following JSON data:
} }
``` ```
This will fail with an exception similar to this one: `MalformedJsonException: Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON at line 5 column 4 path $.languages[2]` This will fail with an exception similar to this one: `MalformedJsonException: Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON at line 5 column 4 path $.languages[2]`\
The problem here is the trailing comma (`,`) after `"French"`, trailing commas are not allowed by the JSON specification. The location information "line 5 column 4" points to the `]` in the JSON data (with some slight inaccuracies) because Gson expected another value after `,` instead of the closing `]`. The JSONPath `$.languages[2]` in the exception message also points there: `$.` refers to the root object, `languages` refers to its member of that name and `[2]` refers to the (missing) third value in the JSON array value of that member (numbering starts at 0, so it is `[2]` instead of `[3]`). The problem here is the trailing comma (`,`) after `"French"`, trailing commas are not allowed by the JSON specification. The location information "line 5 column 4" points to the `]` in the JSON data (with some slight inaccuracies) because Gson expected another value after `,` instead of the closing `]`. The JSONPath `$.languages[2]` in the exception message also points there: `$.` refers to the root object, `languages` refers to its member of that name and `[2]` refers to the (missing) third value in the JSON array value of that member (numbering starts at 0, so it is `[2]` instead of `[3]`).\
The proper solution here is to fix the malformed JSON data. The proper solution here is to fix the malformed JSON data.
To spot syntax errors in the JSON data easily you can open it in an editor with support for JSON, for example Visual Studio Code. It will highlight within the JSON data the error location and show why the JSON data is considered invalid. To spot syntax errors in the JSON data easily you can open it in an editor with support for JSON, for example Visual Studio Code. It will highlight within the JSON data the error location and show why the JSON data is considered invalid.
@ -178,8 +178,8 @@ And you want to deserialize the following JSON data:
} }
``` ```
This will fail with an exception similar to this one: `IllegalStateException: Expected a string but was BEGIN_ARRAY at line 2 column 17 path $.languages` This will fail with an exception similar to this one: `IllegalStateException: Expected a string but was BEGIN_ARRAY at line 2 column 17 path $.languages`\
This means Gson expected a JSON string value but found the beginning of a JSON array (`[`). The location information "line 2 column 17" points to the `[` in the JSON data (with some slight inaccuracies), so does the JSONPath `$.languages` in the exception message. It refers to the `languages` member of the root object (`$.`). This means Gson expected a JSON string value but found the beginning of a JSON array (`[`). The location information "line 2 column 17" points to the `[` in the JSON data (with some slight inaccuracies), so does the JSONPath `$.languages` in the exception message. It refers to the `languages` member of the root object (`$.`).\
The solution here is to change in the `WebPage` class the field `String languages` to `List<String> languages`. The solution here is to change in the `WebPage` class the field `String languages` to `List<String> languages`.
## <a id="adapter-not-null-safe"></a> `IllegalStateException`: "Expected ... but was NULL" ## <a id="adapter-not-null-safe"></a> `IllegalStateException`: "Expected ... but was NULL"
@ -287,7 +287,7 @@ This will not initialize arbitrary classes, and it will throw a `ClassCastExcept
## <a id="type-token-raw"></a> `IllegalStateException`: 'TypeToken must be created with a type argument' <br> `RuntimeException`: 'Missing type parameter' ## <a id="type-token-raw"></a> `IllegalStateException`: 'TypeToken must be created with a type argument' <br> `RuntimeException`: 'Missing type parameter'
**Symptom:** An `IllegalStateException` with the message 'TypeToken must be created with a type argument' is thrown. **Symptom:** An `IllegalStateException` with the message 'TypeToken must be created with a type argument' is thrown.\
For older Gson versions a `RuntimeException` with message 'Missing type parameter' is thrown. For older Gson versions a `RuntimeException` with message 'Missing type parameter' is thrown.
**Reason:** **Reason:**

View File

@ -52,8 +52,8 @@ public class PostConstructAdapterFactoryTest {
// Throws NullPointerException without the fix in https://github.com/google/gson/pull/1103 // Throws NullPointerException without the fix in https://github.com/google/gson/pull/1103
String json = gson.toJson(sandwiches); String json = gson.toJson(sandwiches);
assertEquals( assertEquals(
"{\"sandwiches\":[{\"bread\":\"white\",\"cheese\":\"cheddar\"},{\"bread\":\"whole" "{\"sandwiches\":[{\"bread\":\"white\",\"cheese\":\"cheddar\"},"
+ " wheat\",\"cheese\":\"swiss\"}]}", + "{\"bread\":\"whole wheat\",\"cheese\":\"swiss\"}]}",
json); json);
MultipleSandwiches sandwichesFromJson = gson.fromJson(json, MultipleSandwiches.class); MultipleSandwiches sandwichesFromJson = gson.fromJson(json, MultipleSandwiches.class);

View File

@ -90,8 +90,8 @@ class ReflectionTest {
assertThat(c.i).isEqualTo(1); assertThat(c.i).isEqualTo(1);
c = gson.fromJson("{}", ClassWithoutDefaultConstructor.class); c = gson.fromJson("{}", ClassWithoutDefaultConstructor.class);
// Class is instantiated with JDK Unsafe, so field keeps its default value instead of assigned // Class is instantiated with JDK Unsafe, therefore field keeps its default value instead of
// -1 // assigned -1
assertThat(c.i).isEqualTo(0); assertThat(c.i).isEqualTo(0);
} }

View File

@ -139,11 +139,11 @@
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
<configuration> <configuration>
<!-- Deny illegal access, this is required for ReflectionAccessTest --> <!-- Deny illegal access, this is required for ReflectionAccessTest -->
<!-- Requires Java >= 9; Important: In case future Java versions <!-- Requires Java >= 9; Important: In case future Java versions
don't support this flag anymore, don't remove it unless CI also runs with don't support this flag anymore, don't remove it unless CI also runs with
that Java version. Ideally would use toolchain to specify that this should that Java version. Ideally would use toolchain to specify that this should
run with e.g. Java 11, but Maven toolchain requirements (unlike Gradle ones) run with e.g. Java 11, but Maven toolchain requirements (unlike Gradle ones)
don't seem to be portable (every developer would have to set up toolchain don't seem to be portable (every developer would have to set up toolchain
configuration locally). --> configuration locally). -->
<argLine>--illegal-access=deny</argLine> <argLine>--illegal-access=deny</argLine>
</configuration> </configuration>
@ -239,7 +239,7 @@
</configuration> </configuration>
</plugin> </plugin>
<!-- Add module-info to JAR, see https://github.com/moditect/moditect#adding-module-descriptors-to-existing-jar-files --> <!-- Add module-info to JAR, see https://github.com/moditect/moditect#adding-module-descriptors-to-existing-jar-files -->
<!-- Uses ModiTect instead of separate maven-compiler-plugin executions <!-- Uses ModiTect instead of separate maven-compiler-plugin executions
for better Eclipse IDE support, see https://github.com/eclipse-m2e/m2e-core/issues/393 --> for better Eclipse IDE support, see https://github.com/eclipse-m2e/m2e-core/issues/393 -->
<!-- Note: For some reason this has to be executed before javadoc plugin; otherwise `javadoc:jar` goal fails <!-- Note: For some reason this has to be executed before javadoc plugin; otherwise `javadoc:jar` goal fails
to find source files --> to find source files -->

View File

@ -163,7 +163,8 @@ public final class JsonArray extends JsonElement implements Iterable<JsonElement
/** /**
* Removes the element at the specified position in this array. Shifts any subsequent elements to * Removes the element at the specified position in this array. Shifts any subsequent elements to
* the left (subtracts one from their indices). Returns the element removed from the array. * the left (subtracts one from their indices). Returns the element that was removed from the
* array.
* *
* @param index index the index of the element to be removed * @param index index the index of the element to be removed
* @return the element previously at the specified position * @return the element previously at the specified position

View File

@ -1,16 +1,19 @@
/** /*
* Copyright (C) 2008 Google Inc. * Copyright (C) 2008 Google Inc.
* *
* <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * Licensed under the Apache License, Version 2.0 (the "License");
* except in compliance with the License. You may obtain a copy of the License at * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* *
* <p>http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* <p>Unless required by applicable law or agreed to in writing, software distributed under the * Unless required by applicable law or agreed to in writing, software
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * distributed under the License is distributed on an "AS IS" BASIS,
* express or implied. See the License for the specific language governing permissions and * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.google.gson.internal; package com.google.gson.internal;
import static com.google.gson.internal.$Gson$Preconditions.checkArgument; import static com.google.gson.internal.$Gson$Preconditions.checkArgument;
@ -156,8 +159,7 @@ public final class $Gson$Types {
} else { } else {
String className = type == null ? "null" : type.getClass().getName(); String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Expected a Class, ParameterizedType, or " "Expected a Class, ParameterizedType, or GenericArrayType, but <"
+ "GenericArrayType, but <"
+ type + type
+ "> is of type " + "> is of type "
+ className); + className);

View File

@ -303,8 +303,7 @@ public final class ConstructorConstructor {
throw new RuntimeException( throw new RuntimeException(
"Failed to invoke constructor '" "Failed to invoke constructor '"
+ ReflectionHelper.constructorToString(constructor) + ReflectionHelper.constructorToString(constructor)
+ "'" + "' with no args",
+ " with no args",
e); e);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
// TODO: don't wrap if cause is unchecked? // TODO: don't wrap if cause is unchecked?
@ -312,8 +311,7 @@ public final class ConstructorConstructor {
throw new RuntimeException( throw new RuntimeException(
"Failed to invoke constructor '" "Failed to invoke constructor '"
+ ReflectionHelper.constructorToString(constructor) + ReflectionHelper.constructorToString(constructor)
+ "'" + "' with no args",
+ " with no args",
e.getCause()); e.getCause());
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw ReflectionHelper.createExceptionForUnexpectedIllegalAccess(e); throw ReflectionHelper.createExceptionForUnexpectedIllegalAccess(e);

View File

@ -37,7 +37,7 @@ public final class JavaVersion {
version = extractBeginningInt(javaVersion); version = extractBeginningInt(javaVersion);
} }
if (version == -1) { if (version == -1) {
return 6; // Choose a minimum supported JDK version as default return 6; // Choose minimum supported JDK version as default
} }
return version; return version;
} }

View File

@ -121,8 +121,8 @@ public abstract class UnsafeAllocator {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"Cannot allocate " "Cannot allocate "
+ c + c
+ ". Usage of JDK sun.misc.Unsafe is enabled, " + ". Usage of JDK sun.misc.Unsafe is enabled, but it could not be used."
+ "but it could not be used. Make sure your runtime is configured correctly."); + " Make sure your runtime is configured correctly.");
} }
}; };
} }

View File

@ -71,7 +71,7 @@ public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapte
return rawType.getAnnotation(JsonAdapter.class); return rawType.getAnnotation(JsonAdapter.class);
} }
// this is not safe; requires that user has specified correct adapter class for @JsonAdapter // this is not safe; requires that user has specified correct adapter class for @JsonAdapter
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> targetType) { public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> targetType) {

View File

@ -228,8 +228,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
throw new JsonParseException( throw new JsonParseException(
"null is not allowed as value for record component '" "null is not allowed as value for record component '"
+ fieldName + fieldName
+ "'" + "' of primitive type; at path "
+ " of primitive type; at path "
+ reader.getPath()); + reader.getPath());
} }
target[index] = fieldValue; target[index] = fieldValue;
@ -244,8 +243,8 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
checkAccessible(target, field); checkAccessible(target, field);
} else if (isStaticFinalField) { } else if (isStaticFinalField) {
// Reflection does not permit setting value of `static final` field, even after calling // Reflection does not permit setting value of `static final` field, even after calling
// `setAccessible` Handle this here to avoid causing IllegalAccessException when calling // `setAccessible`
// `Field.set` // Handle this here to avoid causing IllegalAccessException when calling `Field.set`
String fieldDescription = ReflectionHelper.getAccessibleObjectDescription(field, false); String fieldDescription = ReflectionHelper.getAccessibleObjectDescription(field, false);
throw new JsonIOException("Cannot set value of 'static final' " + fieldDescription); throw new JsonIOException("Cannot set value of 'static final' " + fieldDescription);
} }
@ -279,8 +278,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
+ declaringType.getName() + declaringType.getName()
+ " declares multiple JSON fields named '" + " declares multiple JSON fields named '"
+ duplicateName + duplicateName
+ "'; conflict is caused" + "'; conflict is caused by fields "
+ " by fields "
+ ReflectionHelper.fieldToString(field1) + ReflectionHelper.fieldToString(field1)
+ " and " + " and "
+ ReflectionHelper.fieldToString(field2) + ReflectionHelper.fieldToString(field2)
@ -313,8 +311,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
+ raw + raw
+ " (supertype of " + " (supertype of "
+ originalRaw + originalRaw
+ "). Register a TypeAdapter for this type" + "). Register a TypeAdapter for this type or adjust the access filter.");
+ " or adjust the access filter.");
} }
blockInaccessible = filterResult == FilterResult.BLOCK_INACCESSIBLE; blockInaccessible = filterResult == FilterResult.BLOCK_INACCESSIBLE;
} }
@ -603,8 +600,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
throw new IllegalStateException( throw new IllegalStateException(
"Could not find the index in the constructor '" "Could not find the index in the constructor '"
+ ReflectionHelper.constructorToString(constructor) + ReflectionHelper.constructorToString(constructor)
+ "'" + "' for field with name '"
+ " for field with name '"
+ field.fieldName + field.fieldName
+ "', unable to determine which argument in the constructor the field corresponds" + "', unable to determine which argument in the constructor the field corresponds"
+ " to. This is unexpected behavior, as we expect the RecordComponents to have the" + " to. This is unexpected behavior, as we expect the RecordComponents to have the"
@ -624,13 +620,12 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
} }
// Note: InstantiationException should be impossible because record class is not abstract; // Note: InstantiationException should be impossible because record class is not abstract;
// IllegalArgumentException should not be possible unless a bad adapter returns objects of // IllegalArgumentException should not be possible unless a bad adapter returns objects of
// the wrong type // the wrong type
catch (InstantiationException | IllegalArgumentException e) { catch (InstantiationException | IllegalArgumentException e) {
throw new RuntimeException( throw new RuntimeException(
"Failed to invoke constructor '" "Failed to invoke constructor '"
+ ReflectionHelper.constructorToString(constructor) + ReflectionHelper.constructorToString(constructor)
+ "'" + "' with args "
+ " with args "
+ Arrays.toString(accumulator), + Arrays.toString(accumulator),
e); e);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
@ -638,8 +633,7 @@ public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory {
throw new RuntimeException( throw new RuntimeException(
"Failed to invoke constructor '" "Failed to invoke constructor '"
+ ReflectionHelper.constructorToString(constructor) + ReflectionHelper.constructorToString(constructor)
+ "'" + "' with args "
+ " with args "
+ Arrays.toString(accumulator), + Arrays.toString(accumulator),
e.getCause()); e.getCause());
} }

View File

@ -45,8 +45,8 @@ final class TypeAdapterRuntimeTypeWrapper<T> extends TypeAdapter<T> {
// Order of preference for choosing type adapters // Order of preference for choosing type adapters
// First preference: a type adapter registered for the runtime type // First preference: a type adapter registered for the runtime type
// Second preference: a type adapter registered for the declared type // Second preference: a type adapter registered for the declared type
// Third preference: reflective type adapter for the runtime type (if it is a subclass of the // Third preference: reflective type adapter for the runtime type
// declared type) // (if it is a subclass of the declared type)
// Fourth preference: reflective type adapter for the declared type // Fourth preference: reflective type adapter for the declared type
TypeAdapter<T> chosen = delegate; TypeAdapter<T> chosen = delegate;

View File

@ -401,8 +401,8 @@ public final class TypeAdapters {
out.nullValue(); out.nullValue();
} else { } else {
// For backward compatibility don't call `JsonWriter.value(float)` because that method // For backward compatibility don't call `JsonWriter.value(float)` because that method
// has // has been newly added and not all custom JsonWriter implementations might override
// been newly added and not all custom JsonWriter implementations might override it yet // it yet
Number floatNumber = value instanceof Float ? value : value.floatValue(); Number floatNumber = value instanceof Float ? value : value.floatValue();
out.value(floatNumber); out.value(floatNumber);
} }
@ -952,7 +952,8 @@ public final class TypeAdapters {
public EnumTypeAdapter(final Class<T> classOfT) { public EnumTypeAdapter(final Class<T> classOfT) {
try { try {
// Uses reflection to find enum constants to work around name mismatches for obfuscated // Uses reflection to find enum constants to work around name mismatches for obfuscated
// classes Reflection access might throw SecurityException, therefore run this in privileged // classes
// Reflection access might throw SecurityException, therefore run this in privileged
// context; should be acceptable because this only retrieves enum constants, but does not // context; should be acceptable because this only retrieves enum constants, but does not
// expose anything else // expose anything else
Field[] constantFields = Field[] constantFields =

View File

@ -160,12 +160,14 @@ public class ISO8601Utils {
// extract day // extract day
int day = parseInt(date, offset, offset += 2); int day = parseInt(date, offset, offset += 2);
// default time value // default time value
int hour = 0; int hour = 0;
int minutes = 0; int minutes = 0;
int seconds = 0; int seconds = 0;
int milliseconds =
0; // always use 0 otherwise returned date will include millis of current time // always use 0 otherwise returned date will include millis of current time
int milliseconds = 0;
// if the value has no time component (and no time zone), we are done // if the value has no time component (and no time zone), we are done
boolean hasT = checkOffset(date, offset, 'T'); boolean hasT = checkOffset(date, offset, 'T');

View File

@ -159,10 +159,9 @@ public class ReflectionHelper {
} catch (Exception exception) { } catch (Exception exception) {
return "Failed making constructor '" return "Failed making constructor '"
+ constructorToString(constructor) + constructorToString(constructor)
+ "' accessible;" + "' accessible; either increase its visibility or write a custom InstanceCreator or"
+ " either increase its visibility or write a custom InstanceCreator or TypeAdapter for" + " TypeAdapter for its declaring type: "
// Include the message since it might contain more detailed information // Include the message since it might contain more detailed information
+ " its declaring type: "
+ exception.getMessage() + exception.getMessage()
+ getInaccessibleTroubleshootingSuffix(exception); + getInaccessibleTroubleshootingSuffix(exception);
} }

View File

@ -109,8 +109,8 @@ public class TypeToken<T> {
else if (superclass == TypeToken.class) { else if (superclass == TypeToken.class) {
throw new IllegalStateException( throw new IllegalStateException(
"TypeToken must be created with a type argument: new TypeToken<...>() {}; When using code" "TypeToken must be created with a type argument: new TypeToken<...>() {}; When using code"
+ " shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved.\n" + " shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved."
+ "See " + "\nSee "
+ TroubleshootingGuide.createUrl("type-token-raw")); + TroubleshootingGuide.createUrl("type-token-raw"));
} }
@ -416,8 +416,7 @@ public class TypeToken<T> {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Raw type " "Raw type "
+ rawClass.getName() + rawClass.getName()
+ " is not supported because" + " is not supported because it requires specifying an owner type");
+ " it requires specifying an owner type");
} }
for (int i = 0; i < expectedArgsCount; i++) { for (int i = 0; i < expectedArgsCount; i++) {
@ -433,8 +432,7 @@ public class TypeToken<T> {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Type argument " "Type argument "
+ typeArgument + typeArgument
+ " does not satisfy bounds" + " does not satisfy bounds for type variable "
+ " for type variable "
+ typeVariable + typeVariable
+ " declared by " + " declared by "
+ rawType); + rawType);

View File

@ -1339,8 +1339,8 @@ public class JsonReader implements Closeable {
// Only update when object end is explicitly skipped, otherwise stack is not updated // Only update when object end is explicitly skipped, otherwise stack is not updated
// anyways // anyways
if (count == 0) { if (count == 0) {
pathNames[stackSize - 1] = // Free the last path name so that it can be garbage collected
null; // Free the last path name so that it can be garbage collected pathNames[stackSize - 1] = null;
} }
stackSize--; stackSize--;
count--; count--;
@ -1616,7 +1616,7 @@ public class JsonReader implements Closeable {
/** /**
* Returns a <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> in <i>dot-notation</i> * Returns a <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> in <i>dot-notation</i>
* to the previous (or current) location in the JSON document: * to the previous (or current) location in the JSON document. That means:
* *
* <ul> * <ul>
* <li>For JSON arrays the path points to the index of the previous element.<br> * <li>For JSON arrays the path points to the index of the previous element.<br>
@ -1634,7 +1634,7 @@ public class JsonReader implements Closeable {
/** /**
* Returns a <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> in <i>dot-notation</i> * Returns a <a href="https://goessner.net/articles/JsonPath/">JSONPath</a> in <i>dot-notation</i>
* to the next (or current) location in the JSON document: * to the next (or current) location in the JSON document. That means:
* *
* <ul> * <ul>
* <li>For JSON arrays the path points to the index of the next element (even if there are no * <li>For JSON arrays the path points to the index of the next element (even if there are no

View File

@ -306,9 +306,9 @@ public class JsonWriter implements Closeable, Flushable {
* @see #setStrictness(Strictness) * @see #setStrictness(Strictness)
*/ */
@Deprecated @Deprecated
@SuppressWarnings( // Don't specify @InlineMe, so caller with `setLenient(false)` becomes aware of new
"InlineMeSuggester") // Don't specify @InlineMe, so caller with `setLenient(false)` becomes // Strictness.STRICT
// aware of new Strictness.STRICT @SuppressWarnings("InlineMeSuggester")
public final void setLenient(boolean lenient) { public final void setLenient(boolean lenient) {
setStrictness(lenient ? Strictness.LENIENT : Strictness.LEGACY_STRICT); setStrictness(lenient ? Strictness.LENIENT : Strictness.LEGACY_STRICT);
} }

View File

@ -648,8 +648,8 @@ public class DefaultTypeAdaptersTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.isEqualTo( .isEqualTo(
"Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive; at path" "Expected a com.google.gson.JsonObject but was com.google.gson.JsonPrimitive;"
+ " $"); + " at path $");
} }
} }

View File

@ -113,7 +113,14 @@ public class FormattingStyleTest {
String expectedJson = buildExpected("\n", " ", true); String expectedJson = buildExpected("\n", " ", true);
assertThat(json).isEqualTo(expectedJson); assertThat(json).isEqualTo(expectedJson);
// Sanity check to verify that `buildExpected` works correctly // Sanity check to verify that `buildExpected` works correctly
assertThat(json).isEqualTo("{\n" + " \"a\": [\n" + " 1,\n" + " 2\n" + " ]\n" + "}"); assertThat(json)
.isEqualTo(
"{\n" //
+ " \"a\": [\n" //
+ " 1,\n" //
+ " 2\n" //
+ " ]\n" //
+ "}");
} }
@Test @Test

View File

@ -474,9 +474,8 @@ public final class JsonAdapterAnnotationOnClassesTest {
@Override @Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return new TypeAdapter<T>() { return new TypeAdapter<T>() {
@SuppressWarnings( // suppress Error Prone warning; should be clear that `Factory` refers to enclosing class
"SameNameButDifferent") // suppress Error Prone warning; should be clear that @SuppressWarnings("SameNameButDifferent")
// `Factory` refers to enclosing class
private TypeAdapter<T> delegate() { private TypeAdapter<T> delegate() {
return gson.getDelegateAdapter(Factory.this, type); return gson.getDelegateAdapter(Factory.this, type);
} }

View File

@ -604,8 +604,7 @@ public final class JsonAdapterAnnotationOnFieldsTest {
assertThat(new Gson().toJson(serialized)).isEqualTo("{\"f\":\"value-custom\"}"); assertThat(new Gson().toJson(serialized)).isEqualTo("{\"f\":\"value-custom\"}");
} }
// suppress Error Prone warning; should be clear that `Factory` refers to nested class to nested // suppress Error Prone warning; should be clear that `Factory` refers to nested class
// class
@SuppressWarnings("SameNameButDifferent") @SuppressWarnings("SameNameButDifferent")
private static class WithDelayedDelegatingFactory { private static class WithDelayedDelegatingFactory {
@JsonAdapter(Factory.class) @JsonAdapter(Factory.class)

View File

@ -40,7 +40,9 @@ public class LeniencyTest {
public void testLenientFromJson() { public void testLenientFromJson() {
List<String> json = List<String> json =
gson.fromJson( gson.fromJson(
"" + "[ # One!\n" + " 'Hi' #Element!\n" + "] # Array!", "[ # One!\n" //
+ " 'Hi' #Element!\n" //
+ "] # Array!",
new TypeToken<List<String>>() {}.getType()); new TypeToken<List<String>>() {}.getType());
assertThat(json).isEqualTo(singletonList("Hi")); assertThat(json).isEqualTo(singletonList("Hi"));
} }

View File

@ -500,7 +500,7 @@ public class MapTest {
String subTypeJson = new Gson().toJson(subType); String subTypeJson = new Gson().toJson(subType);
String expected = String expected =
"{\"bases\":{\"Test\":" + subTypeJson + "}," + "\"subs\":{\"Test\":" + subTypeJson + "}}"; "{\"bases\":{\"Test\":" + subTypeJson + "},\"subs\":{\"Test\":" + subTypeJson + "}}";
Gson gsonWithComplexKeys = new GsonBuilder().enableComplexMapKeySerialization().create(); Gson gsonWithComplexKeys = new GsonBuilder().enableComplexMapKeySerialization().create();
String json = gsonWithComplexKeys.toJson(element); String json = gsonWithComplexKeys.toJson(element);
@ -523,7 +523,7 @@ public class MapTest {
final JsonElement baseTypeJsonElement = tempGson.toJsonTree(subType, TestTypes.Base.class); final JsonElement baseTypeJsonElement = tempGson.toJsonTree(subType, TestTypes.Base.class);
String baseTypeJson = tempGson.toJson(baseTypeJsonElement); String baseTypeJson = tempGson.toJson(baseTypeJsonElement);
String expected = String expected =
"{\"bases\":{\"Test\":" + baseTypeJson + "}," + "\"subs\":{\"Test\":" + subTypeJson + "}}"; "{\"bases\":{\"Test\":" + baseTypeJson + "},\"subs\":{\"Test\":" + subTypeJson + "}}";
JsonSerializer<TestTypes.Base> baseTypeAdapter = JsonSerializer<TestTypes.Base> baseTypeAdapter =
new JsonSerializer<TestTypes.Base>() { new JsonSerializer<TestTypes.Base>() {

View File

@ -100,8 +100,8 @@ public class PrimitiveTest {
assertThat(e) assertThat(e)
.hasMessageThat() .hasMessageThat()
.isEqualTo( .isEqualTo(
"java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column" "java.lang.NumberFormatException: Expected an int but was 2147483648"
+ " 11 path $"); + " at line 1 column 11 path $");
} }
@Test @Test
@ -143,8 +143,8 @@ public class PrimitiveTest {
assertThat(e) assertThat(e)
.hasMessageThat() .hasMessageThat()
.isEqualTo( .isEqualTo(
"java.lang.NumberFormatException: Expected an int but was 2147483648 at line 1 column" "java.lang.NumberFormatException: Expected an int but was 2147483648"
+ " 11 path $"); + " at line 1 column 11 path $");
} }
@Test @Test

View File

@ -447,7 +447,7 @@ public class ReflectionAccessFilterTest {
} }
/** /**
* Should not fail when deserializing collection interface (Even though this goes through {@link * Should not fail when deserializing collection interface (even though this goes through {@link
* ConstructorConstructor} as well) * ConstructorConstructor} as well)
*/ */
@Test @Test
@ -467,7 +467,7 @@ public class ReflectionAccessFilterTest {
} }
/** /**
* Should not fail when deserializing specific collection implementation (Even though this goes * Should not fail when deserializing specific collection implementation (even though this goes
* through {@link ConstructorConstructor} as well) * through {@link ConstructorConstructor} as well)
*/ */
@Test @Test

View File

@ -30,20 +30,20 @@ public class JavaVersionTest {
@Test @Test
public void testGetMajorJavaVersion() { public void testGetMajorJavaVersion() {
assertThat(JavaVersion.getMajorJavaVersion() >= 7) // Gson currently requires at least Java 7
.isTrue(); // Gson currently requires at least Java 7 assertThat(JavaVersion.getMajorJavaVersion() >= 7).isTrue();
} }
@Test @Test
public void testJava6() { public void testJava6() {
assertThat(JavaVersion.getMajorJavaVersion("1.6.0")) // http://www.oracle.com/technetwork/java/javase/version-6-141920.html
.isEqualTo(6); // http://www.oracle.com/technetwork/java/javase/version-6-141920.html assertThat(JavaVersion.getMajorJavaVersion("1.6.0")).isEqualTo(6);
} }
@Test @Test
public void testJava7() { public void testJava7() {
assertThat(JavaVersion.getMajorJavaVersion("1.7.0")) // http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html
.isEqualTo(7); // http://www.oracle.com/technetwork/java/javase/jdk7-naming-418744.html assertThat(JavaVersion.getMajorJavaVersion("1.7.0")).isEqualTo(7);
} }
@Test @Test
@ -63,8 +63,9 @@ public class JavaVersionTest {
public void testJava9() { public void testJava9() {
// Legacy style // Legacy style
assertThat(JavaVersion.getMajorJavaVersion("9.0.4")).isEqualTo(9); // Oracle JDK 9 assertThat(JavaVersion.getMajorJavaVersion("9.0.4")).isEqualTo(9); // Oracle JDK 9
assertThat(JavaVersion.getMajorJavaVersion("9-Debian")) // Debian as reported in https://github.com/google/gson/issues/1310
.isEqualTo(9); // Debian as reported in https://github.com/google/gson/issues/1310 assertThat(JavaVersion.getMajorJavaVersion("9-Debian")).isEqualTo(9);
// New style // New style
assertThat(JavaVersion.getMajorJavaVersion("9-ea+19")).isEqualTo(9); assertThat(JavaVersion.getMajorJavaVersion("9-ea+19")).isEqualTo(9);
assertThat(JavaVersion.getMajorJavaVersion("9+100")).isEqualTo(9); assertThat(JavaVersion.getMajorJavaVersion("9+100")).isEqualTo(9);

View File

@ -29,8 +29,8 @@ import org.junit.Test;
* #440</a> and similar issues. * #440</a> and similar issues.
* *
* <p>These tests originally caused {@link StackOverflowError} because of infinite recursion on * <p>These tests originally caused {@link StackOverflowError} because of infinite recursion on
* attempts to resolve generics on types, with an intermediate types like 'Foo2&lt;? extends ? super * attempts to resolve generics on types, with intermediate types like {@code Foo2<? extends ? super
* ? extends ... ? extends A&gt;' * ? extends ... ? extends A>}
*/ */
public class RecursiveTypesResolveTest { public class RecursiveTypesResolveTest {
@ -52,7 +52,7 @@ public class RecursiveTypesResolveTest {
assertThat(adapter).isNotNull(); assertThat(adapter).isNotNull();
} }
/** Tests belows check the behaviour of the methods changed for the fix. */ /** Tests below check the behavior of the methods changed for the fix. */
@Test @Test
public void testDoubleSupertype() { public void testDoubleSupertype() {
assertThat($Gson$Types.supertypeOf($Gson$Types.supertypeOf(Number.class))) assertThat($Gson$Types.supertypeOf($Gson$Types.supertypeOf(Number.class)))

View File

@ -207,8 +207,7 @@ public final class TypeTokenTest {
assertThat(e) assertThat(e)
.hasMessageThat() .hasMessageThat()
.isEqualTo( .isEqualTo(
"Type argument int does not satisfy bounds" "Type argument int does not satisfy bounds for type variable E declared by "
+ " for type variable E declared by "
+ List.class); + List.class);
e = e =

View File

@ -148,8 +148,8 @@ public final class JsonReaderTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.startsWith( .startsWith(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed" "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"
+ " JSON at line 1 column 1 path $"); + " at line 1 column 1 path $");
reader = new JsonReader(reader("True")); reader = new JsonReader(reader("True"));
reader.setStrictness(Strictness.STRICT); reader.setStrictness(Strictness.STRICT);
@ -158,8 +158,8 @@ public final class JsonReaderTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.startsWith( .startsWith(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed" "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"
+ " JSON at line 1 column 1 path $"); + " at line 1 column 1 path $");
} }
@Test @Test
@ -171,8 +171,8 @@ public final class JsonReaderTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.startsWith( .startsWith(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed" "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"
+ " JSON at line 1 column 1 path $"); + " at line 1 column 1 path $");
reader = new JsonReader(reader("FaLse")); reader = new JsonReader(reader("FaLse"));
reader.setStrictness(Strictness.STRICT); reader.setStrictness(Strictness.STRICT);
@ -181,8 +181,8 @@ public final class JsonReaderTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.startsWith( .startsWith(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed" "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"
+ " JSON at line 1 column 1 path $"); + " at line 1 column 1 path $");
} }
@Test @Test
@ -194,8 +194,8 @@ public final class JsonReaderTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.startsWith( .startsWith(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed" "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"
+ " JSON at line 1 column 1 path $"); + " at line 1 column 1 path $");
reader = new JsonReader(reader("nulL")); reader = new JsonReader(reader("nulL"));
reader.setStrictness(Strictness.STRICT); reader.setStrictness(Strictness.STRICT);
@ -204,8 +204,8 @@ public final class JsonReaderTest {
assertThat(expected) assertThat(expected)
.hasMessageThat() .hasMessageThat()
.startsWith( .startsWith(
"Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed" "Use JsonReader.setStrictness(Strictness.LENIENT) to accept malformed JSON"
+ " JSON at line 1 column 1 path $"); + " at line 1 column 1 path $");
} }
@Test @Test
@ -416,7 +416,11 @@ public final class JsonReaderTest {
@Test @Test
public void testHelloWorld() throws IOException { public void testHelloWorld() throws IOException {
String json = "{\n" + " \"hello\": true,\n" + " \"foo\": [\"world\"]\n" + "}"; String json =
"{\n" //
+ " \"hello\": true,\n" //
+ " \"foo\": [\"world\"]\n" //
+ "}";
JsonReader reader = new JsonReader(reader(json)); JsonReader reader = new JsonReader(reader(json));
reader.beginObject(); reader.beginObject();
assertThat(reader.nextName()).isEqualTo("hello"); assertThat(reader.nextName()).isEqualTo("hello");
@ -431,7 +435,11 @@ public final class JsonReaderTest {
@Test @Test
public void testInvalidJsonInput() throws IOException { public void testInvalidJsonInput() throws IOException {
String json = "{\n" + " \"h\\ello\": true,\n" + " \"foo\": [\"world\"]\n" + "}"; String json =
"{\n" //
+ " \"h\\ello\": true,\n" //
+ " \"foo\": [\"world\"]\n" //
+ "}";
JsonReader reader = new JsonReader(reader(json)); JsonReader reader = new JsonReader(reader(json));
reader.beginObject(); reader.beginObject();

View File

@ -1045,7 +1045,12 @@ public final class JsonWriterTest {
jsonWriter.endArray(); jsonWriter.endArray();
String expected = String expected =
"[\r\n" + " \t true,\r\n" + " \t \"text\",\r\n" + " \t 5.0,\r\n" + " \t null\r\n" + "]"; "[\r\n" //
+ " \t true,\r\n" //
+ " \t \"text\",\r\n" //
+ " \t 5.0,\r\n" //
+ " \t null\r\n" //
+ "]";
assertThat(stringWriter.toString()).isEqualTo(expected); assertThat(stringWriter.toString()).isEqualTo(expected);
assertThat(jsonWriter.getFormattingStyle().getNewline()).isEqualTo(lineSeparator); assertThat(jsonWriter.getFormattingStyle().getNewline()).isEqualTo(lineSeparator);
@ -1067,7 +1072,13 @@ public final class JsonWriterTest {
jsonWriter.endArray(); jsonWriter.endArray();
jsonWriter.endObject(); jsonWriter.endObject();
String expected = "{\n" + " \"a\": [\n" + " 1,\n" + " 2\n" + " ]\n" + "}"; String expected =
"{\n" //
+ " \"a\": [\n" //
+ " 1,\n" //
+ " 2\n" //
+ " ]\n" //
+ "}";
assertThat(stringWriter.toString()).isEqualTo(expected); assertThat(stringWriter.toString()).isEqualTo(expected);
} }
} }

30
pom.xml
View File

@ -124,6 +124,7 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<!-- Spotless plugin: keeps the code formatted following the google-java-styleguide --> <!-- Spotless plugin: keeps the code formatted following the google-java-styleguide -->
<plugin> <plugin>
<groupId>com.diffplug.spotless</groupId> <groupId>com.diffplug.spotless</groupId>
@ -136,22 +137,34 @@
</goals> </goals>
</execution> </execution>
</executions> </executions>
<!-- Note: The configuration here is not specific to the `<execution>` above to allow users to run
`mvn spotless:apply` from the command line, using the same configuration -->
<configuration> <configuration>
<!-- Perform some basic formatting for non-Java code -->
<formats> <formats>
<format> <format>
<includes> <includes>
<include>*.md</include> <include>*.md</include>
<include>*.xml</include>
<include>.github/**/*.yml</include>
<include>.gitignore</include> <include>.gitignore</include>
</includes> </includes>
<!-- For Markdown files removing trailing whitespace causes issues for hard line breaks,
which use two trailing spaces. However, the trailing spaces are difficult to notice anyway;
prefer a trailing `\` instead of two spaces. -->
<trimTrailingWhitespace/> <trimTrailingWhitespace/>
<endWithNewline/> <endWithNewline/>
<indent> <indent>
<spaces>true</spaces> <spaces>true</spaces>
<spacesPerTab>4</spacesPerTab> <!-- This seems to mostly (or only?) affect the suggested fix in case code contains tabs -->
<spacesPerTab>2</spacesPerTab>
</indent> </indent>
</format> </format>
</formats> </formats>
<java> <java>
<!-- Exclude classes which need Java 17 for compilation; Google Java Format internally relies on javac,
so formatting will fail if build is executed with JDK 11 -->
<excludes> <excludes>
<exclude>src/test/java/com/google/gson/functional/Java17RecordTest.java</exclude> <exclude>src/test/java/com/google/gson/functional/Java17RecordTest.java</exclude>
<exclude>src/test/java/com/google/gson/native_test/Java17RecordReflectionTest.java</exclude> <exclude>src/test/java/com/google/gson/native_test/Java17RecordReflectionTest.java</exclude>
@ -159,11 +172,10 @@
<googleJavaFormat> <googleJavaFormat>
<style>GOOGLE</style> <style>GOOGLE</style>
<reflowLongStrings>true</reflowLongStrings> <reflowLongStrings>true</reflowLongStrings>
<reorderImports>true</reorderImports>
<formatJavadoc>true</formatJavadoc> <formatJavadoc>true</formatJavadoc>
</googleJavaFormat> </googleJavaFormat>
<importOrder/> <formatAnnotations/> <!-- Puts type annotations immediately before types. -->
<removeUnusedImports/>
<formatAnnotations/> <!-- Puts type annotations immediately before types. -->.
</java> </java>
</configuration> </configuration>
</plugin> </plugin>
@ -209,17 +221,17 @@
<release>11</release> <release>11</release>
<!-- Exclude `missing` group because some tags have been omitted when they are redundant --> <!-- Exclude `missing` group because some tags have been omitted when they are redundant -->
<doclint>all,-missing</doclint> <doclint>all,-missing</doclint>
<!-- Link against newer Java API Javadoc because most users likely <!-- Link against newer Java API Javadoc because most users likely
use a newer Java version than the one used for building this project --> use a newer Java version than the one used for building this project -->
<detectJavaApiLink>false</detectJavaApiLink> <detectJavaApiLink>false</detectJavaApiLink>
<links> <links>
<link>https://docs.oracle.com/en/java/javase/11/docs/api/</link> <link>https://docs.oracle.com/en/java/javase/11/docs/api/</link>
<link>https://errorprone.info/api/latest/</link> <link>https://errorprone.info/api/latest/</link>
</links> </links>
<!-- Disable detection of offline links between Maven modules: <!-- Disable detection of offline links between Maven modules:
(1) Only `gson` module is published, so for other modules Javadoc links don't (1) Only `gson` module is published, so for other modules Javadoc links don't
matter much at the moment; (2) The derived URL for the modules is based on matter much at the moment; (2) The derived URL for the modules is based on
the project URL (= Gson GitHub repo) which is incorrect because it is not the project URL (= Gson GitHub repo) which is incorrect because it is not
hosting the Javadoc (3) It might fail due to https://bugs.openjdk.java.net/browse/JDK-8212233 --> hosting the Javadoc (3) It might fail due to https://bugs.openjdk.java.net/browse/JDK-8212233 -->
<detectOfflineLinks>false</detectOfflineLinks> <detectOfflineLinks>false</detectOfflineLinks>
<!-- Only show warnings and errors --> <!-- Only show warnings and errors -->