gson-comments/gson/src/test/java/com/google/gson/reflect/TypeTokenTest.java

280 lines
11 KiB
Java
Raw Normal View History

2011-01-11 23:21:41 +01:00
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.gson.reflect;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import java.lang.reflect.GenericArrayType;
2011-01-11 23:21:41 +01:00
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
2011-01-11 23:21:41 +01:00
import java.util.RandomAccess;
import java.util.Set;
import org.junit.Test;
2011-01-11 23:21:41 +01:00
/**
Fix error prone warns (#2320) * Adds `@SuppressWarnings("NarrowingCompoundAssignment")` * Adds `@SuppressWarnings("TypeParameterUnusedInFormals")` * Adds `@SuppressWarnings("JavaUtilDate")` * Adds a limit to `String.split()` * Add `error_prone_annotations` to the `pom.xml` * Adds `@InlineMe(...)` to deprecated methods * Adds `@SuppressWarnings("ImmutableEnumChecker")` * Adds `@SuppressWarnings("ModifiedButNotUsed")` * Adds `@SuppressWarnings("MixedMutabilityReturnType")` * Removes an unused import * Adds `requires` to `module-info.java` * Adds ErrorProne `link` into `pom.xml` * Remove unused imports Removed from: - ParseBenchmark * Adds `@SuppressWarnings("EqualsGetClass")` * Excludes from `proto` just the generated code. Replaces `.*proto.*` with `.*/generated-test-sources/protobuf/.*` in such way will be excluded just the generated code and not the whole `proto` directory * Removes an unused variable Removes the `descriptor` variable because is unused. * Fixes the `BadImport` warn into `ProtosWithAnnotationsTest` * Fixes the `BadImport` warns into `ProtosWithAnnotationsTest` * Enables ErrorProne in `gson/src/test.*` Removes the `gson/src/test.*` path from the `-XepExcludedPaths` parameter of the ErrorProne plugin * Fixes `UnusedVariable` warns This commit fix all `UnusedVariable` warns given by ErrorProne in the `gson/src/test.*` path. Some field is annotated with `@Keep` that means is used by reflection. In some other case the record is annotated with `@SuppressWarnings("unused")` * Fixes `JavaUtilDate` warns This commit fix all `JavaUtilDate` warns given by ErrorProne in the `gson/src/test.*` path. Classes/Methods are annotated with `@SuppressWarnings("JavaUtilDate")` because it's not possible use differente Date API. * Fixes `EqualsGetClass` warns This commit fix all `EqualsGetClass` warns given by ErrorProne in the `gson/src/test.*` path. I have rewrite the `equals()` methods to use `instanceof` * Replaces pattern matching for instanceof with casts * Fixes `JdkObsolete` warns This commit fix all `JdkObsolete` warns given by ErrorProne in the `gson/src/test.*` path. In some cases I have replaced the obsolete JDK classes with the newest alternatives. In other cases, I have added the `@SuppressWarnings("JdkObsolete")` * Fixes `ClassCanBeStatic` warns This commit fix all `ClassCanBeStatic` warns given by ErrorProne in the `gson/src/test.*` path. I have added the `static` keyword, or I have added `@SuppressWarnings("ClassCanBeStatic")` * Fixes `UndefinedEquals` warns This commit fix all `UndefinedEquals` warns given by ErrorProne in the `gson/src/test.*` path. I have added `@SuppressWarnings("UndefinedEquals")` or fixed the asserts Note: In this commit I have also renamed a test from `testRawCollectionDeserializationNotAlllowed` to `testRawCollectionDeserializationNotAllowed` * Fixes `GetClassOnEnum` warns This commit fix all `GetClassOnEnum` warns given by ErrorProne in the `gson/src/test.*` path. I have replaced the `.getClass()` with `.getDeclaringClass()` * Fixes `ImmutableEnumChecker` warns This commit fix all `ImmutableEnumChecker` warns given by ErrorProne in the `gson/src/test.*` path. I have added the `final` keyword, or I have added the `@SuppressWarnings("ImmutableEnumChecker")` annotation * Fixes `StaticAssignmentOfThrowable` warns This commit fix all `StaticAssignmentOfThrowable` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `AssertionFailureIgnored` warns This commit fix all `AssertionFailureIgnored` warns given by ErrorProne in the `gson/src/test.*` path. I have added the `@SuppressWarnings("AssertionFailureIgnored")` annotation * Fixes `ModifiedButNotUsed` warns This commit fix all `ModifiedButNotUsed` warns given by ErrorProne in the `gson/src/test.*` path. I have added the `@SuppressWarnings("ModifiedButNotUsed")` annotation * Fixes `MissingSummary` warns This commit fix all `MissingSummary` warns given by ErrorProne in the `gson/src/test.*` path. I have remove the Javadoc `@author` * Fixes `FloatingPointLiteralPrecision` warns This commit fix all `FloatingPointLiteralPrecision` warns given by ErrorProne in the `gson/src/test.*` path. I have added the `@SuppressWarnings("FloatingPointLiteralPrecision")` annotation * Fixes `StringSplitter` warns This commit fix all `StringSplitter` warns given by ErrorProne in the `gson/src/test.*` path. I have replaced the `String.split(...)` with `Splitter` * Fixes `EmptyCatch` warns This commit fix all `EmptyCatch` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `UnicodeEscape` warns This commit fix all `UnicodeEscape` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `EmptyBlockTag` warns This commit fix all `EmptyBlockTag` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `LongFloatConversion` warns This commit fix all `LongFloatConversion` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `LongDoubleConversion` warns This commit fix all `LongDoubleConversion` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `TruthAssertExpected` warns This commit fix all `TruthAssertExpected` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `UnusedMethod` warns This commit fix all `UnusedMethod` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `UnusedTypeParameter` warns This commit fix all `UnusedTypeParameter` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `CatchFail` warns This commit fix all `CatchFail` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `MathAbsoluteNegative` warns This commit fix all `MathAbsoluteNegative` warns given by ErrorProne in the `gson/src/test.*` path. * Fixes `LoopOverCharArray` warns This commit fix all `LoopOverCharArray` warns given by ErrorProne in the `gson/src/test.*` path. `toCharArray` allocates a new array, using `charAt` is more efficient * Fixes `HidingField` warns This commit fix all `HidingField` warns given by ErrorProne in the `gson/src/test.*` path. * Implements code review feedback * Implements code review feedback This commit implements some other code review feedback * Enable ErrorProne in `extra` Thi commit removes the `.*extras/src/test.*` path from the `-XepExcludedPaths` parameter of ErrorProne. * Fix the `JavaUtilDate` warns This commit fix all `JavaUtilDate` warns given by ErrorProne in the `extras/src/test.*` path. * Implements code review feedback * Removes redundant new-line * Implements code review feedback * Adds `JDK11` to run test with `--release 11` * Revert "Adds `JDK11` to run test with `--release 11`" This reverts commit a7cca386098ae847a10a31c09c3ab9b11eee5920.
2023-03-01 23:23:27 +01:00
* Tests for {@link TypeToken}.
*
2011-01-11 23:21:41 +01:00
* @author Jesse Wilson
*/
public final class TypeTokenTest {
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
// These fields are accessed using reflection by the tests below
2011-01-11 23:21:41 +01:00
List<Integer> listOfInteger = null;
List<Number> listOfNumber = null;
List<String> listOfString = null;
List<?> listOfUnknown = null;
List<Set<String>> listOfSetOfString = null;
List<Set<?>> listOfSetOfUnknown = null;
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
@SuppressWarnings({"deprecation"})
@Test
2011-01-11 23:21:41 +01:00
public void testIsAssignableFromRawTypes() {
assertThat(TypeToken.get(Object.class).isAssignableFrom(String.class)).isTrue();
assertThat(TypeToken.get(String.class).isAssignableFrom(Object.class)).isFalse();
assertThat(TypeToken.get(RandomAccess.class).isAssignableFrom(ArrayList.class)).isTrue();
assertThat(TypeToken.get(ArrayList.class).isAssignableFrom(RandomAccess.class)).isFalse();
2011-01-11 23:21:41 +01:00
}
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
@SuppressWarnings({"deprecation"})
@Test
2011-01-11 23:21:41 +01:00
public void testIsAssignableFromWithTypeParameters() throws Exception {
Type a = getClass().getDeclaredField("listOfInteger").getGenericType();
Type b = getClass().getDeclaredField("listOfNumber").getGenericType();
assertThat(TypeToken.get(a).isAssignableFrom(a)).isTrue();
assertThat(TypeToken.get(b).isAssignableFrom(b)).isTrue();
2011-01-11 23:21:41 +01:00
// listOfInteger = listOfNumber; // doesn't compile; must be false
assertThat(TypeToken.get(a).isAssignableFrom(b)).isFalse();
2011-01-11 23:21:41 +01:00
// listOfNumber = listOfInteger; // doesn't compile; must be false
assertThat(TypeToken.get(b).isAssignableFrom(a)).isFalse();
2011-01-11 23:21:41 +01:00
}
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
@SuppressWarnings({"deprecation"})
@Test
2011-01-11 23:21:41 +01:00
public void testIsAssignableFromWithBasicWildcards() throws Exception {
Type a = getClass().getDeclaredField("listOfString").getGenericType();
Type b = getClass().getDeclaredField("listOfUnknown").getGenericType();
assertThat(TypeToken.get(a).isAssignableFrom(a)).isTrue();
assertThat(TypeToken.get(b).isAssignableFrom(b)).isTrue();
2011-01-11 23:21:41 +01:00
// listOfString = listOfUnknown // doesn't compile; must be false
assertThat(TypeToken.get(a).isAssignableFrom(b)).isFalse();
2011-01-11 23:21:41 +01:00
listOfUnknown = listOfString; // compiles; must be true
// The following assertion is too difficult to support reliably, so disabling
// assertThat(TypeToken.get(b).isAssignableFrom(a)).isTrue();
2011-01-11 23:21:41 +01:00
}
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
@SuppressWarnings({"deprecation"})
@Test
2011-01-11 23:21:41 +01:00
public void testIsAssignableFromWithNestedWildcards() throws Exception {
Type a = getClass().getDeclaredField("listOfSetOfString").getGenericType();
Type b = getClass().getDeclaredField("listOfSetOfUnknown").getGenericType();
assertThat(TypeToken.get(a).isAssignableFrom(a)).isTrue();
assertThat(TypeToken.get(b).isAssignableFrom(b)).isTrue();
2011-01-11 23:21:41 +01:00
// listOfSetOfString = listOfSetOfUnknown; // doesn't compile; must be false
assertThat(TypeToken.get(a).isAssignableFrom(b)).isFalse();
2011-01-11 23:21:41 +01:00
// listOfSetOfUnknown = listOfSetOfString; // doesn't compile; must be false
assertThat(TypeToken.get(b).isAssignableFrom(a)).isFalse();
2011-01-11 23:21:41 +01:00
}
@Test
public void testArrayFactory() {
TypeToken<?> expectedStringArray = new TypeToken<String[]>() {};
assertThat(TypeToken.getArray(String.class)).isEqualTo(expectedStringArray);
TypeToken<?> expectedListOfStringArray = new TypeToken<List<String>[]>() {};
Type listOfString = new TypeToken<List<String>>() {}.getType();
assertThat(TypeToken.getArray(listOfString)).isEqualTo(expectedListOfStringArray);
try {
TypeToken.getArray(null);
fail();
} catch (NullPointerException e) {
}
}
@Test
public void testParameterizedFactory() {
TypeToken<?> expectedListOfString = new TypeToken<List<String>>() {};
assertThat(TypeToken.getParameterized(List.class, String.class)).isEqualTo(expectedListOfString);
TypeToken<?> expectedMapOfStringToString = new TypeToken<Map<String, String>>() {};
assertThat(TypeToken.getParameterized(Map.class, String.class, String.class)).isEqualTo(expectedMapOfStringToString);
TypeToken<?> expectedListOfListOfListOfString = new TypeToken<List<List<List<String>>>>() {};
Type listOfString = TypeToken.getParameterized(List.class, String.class).getType();
Type listOfListOfString = TypeToken.getParameterized(List.class, listOfString).getType();
assertThat(TypeToken.getParameterized(List.class, listOfListOfString)).isEqualTo(expectedListOfListOfListOfString);
TypeToken<?> expectedWithExactArg = new TypeToken<GenericWithBound<Number>>() {};
assertThat(TypeToken.getParameterized(GenericWithBound.class, Number.class)).isEqualTo(expectedWithExactArg);
TypeToken<?> expectedWithSubclassArg = new TypeToken<GenericWithBound<Integer>>() {};
assertThat(TypeToken.getParameterized(GenericWithBound.class, Integer.class)).isEqualTo(expectedWithSubclassArg);
TypeToken<?> expectedSatisfyingTwoBounds = new TypeToken<GenericWithMultiBound<ClassSatisfyingBounds>>() {};
assertThat(TypeToken.getParameterized(GenericWithMultiBound.class, ClassSatisfyingBounds.class)).isEqualTo(expectedSatisfyingTwoBounds);
}
@Test
public void testParameterizedFactory_Invalid() {
try {
TypeToken.getParameterized(null, new Type[0]);
fail();
} catch (NullPointerException e) {
}
GenericArrayType arrayType = (GenericArrayType) TypeToken.getArray(String.class).getType();
try {
TypeToken.getParameterized(arrayType, new Type[0]);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("rawType must be of type Class, but was java.lang.String[]");
}
try {
TypeToken.getParameterized(String.class, String.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("java.lang.String requires 0 type arguments, but got 1");
}
try {
TypeToken.getParameterized(List.class, new Type[0]);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("java.util.List requires 1 type arguments, but got 0");
}
try {
TypeToken.getParameterized(List.class, String.class, String.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("java.util.List requires 1 type arguments, but got 2");
}
try {
TypeToken.getParameterized(GenericWithBound.class, String.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("Type argument class java.lang.String does not satisfy bounds "
+ "for type variable T declared by " + GenericWithBound.class);
}
try {
TypeToken.getParameterized(GenericWithBound.class, Object.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("Type argument class java.lang.Object does not satisfy bounds "
+ "for type variable T declared by " + GenericWithBound.class);
}
try {
TypeToken.getParameterized(GenericWithMultiBound.class, Number.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("Type argument class java.lang.Number does not satisfy bounds "
+ "for type variable T declared by " + GenericWithMultiBound.class);
}
try {
TypeToken.getParameterized(GenericWithMultiBound.class, CharSequence.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("Type argument interface java.lang.CharSequence does not satisfy bounds "
+ "for type variable T declared by " + GenericWithMultiBound.class);
}
try {
TypeToken.getParameterized(GenericWithMultiBound.class, Object.class);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessageThat().isEqualTo("Type argument class java.lang.Object does not satisfy bounds "
+ "for type variable T declared by " + GenericWithMultiBound.class);
}
}
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
private static class CustomTypeToken extends TypeToken<String> {
}
@Test
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
public void testTypeTokenNonAnonymousSubclass() {
TypeToken<?> typeToken = new CustomTypeToken();
assertThat(typeToken.getRawType()).isEqualTo(String.class);
assertThat(typeToken.getType()).isEqualTo(String.class);
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
}
/**
* User must only create direct subclasses of TypeToken, but not subclasses
* of subclasses (...) of TypeToken.
*/
@Test
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
public void testTypeTokenSubSubClass() {
class SubTypeToken<T> extends TypeToken<String> {}
class SubSubTypeToken1<T> extends SubTypeToken<T> {}
class SubSubTypeToken2 extends SubTypeToken<Integer> {}
try {
new SubTypeToken<Integer>() {};
fail();
} catch (IllegalStateException expected) {
assertThat(expected).hasMessageThat().isEqualTo("Must only create direct subclasses of TypeToken");
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
}
try {
new SubSubTypeToken1<Integer>();
fail();
} catch (IllegalStateException expected) {
assertThat(expected).hasMessageThat().isEqualTo("Must only create direct subclasses of TypeToken");
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
}
try {
new SubSubTypeToken2();
fail();
} catch (IllegalStateException expected) {
assertThat(expected).hasMessageThat().isEqualTo("Must only create direct subclasses of TypeToken");
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
}
}
@SuppressWarnings("rawtypes")
@Test
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
public void testTypeTokenRaw() {
try {
new TypeToken() {};
fail();
} catch (IllegalStateException expected) {
assertThat(expected).hasMessageThat().isEqualTo("TypeToken must be created with a type argument: new TypeToken<...>() {};"
+ " When using code shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved."
+ "\nSee https://github.com/google/gson/blob/main/Troubleshooting.md#type-token-raw"
);
Improve `TypeToken` creation validation (#2072) * Add comments regarding multiple bounds of wildcard * Remove WildcardType check in getCollectionElementType The returned Type is never a wildcard due to the changes made to getSupertype by commit b1fb9ca9a1bea5440bc6a5b506ccf67236b08243. * Remove redundant getRawType call from MapTypeAdapterFactory getRawType(TypeToken.getType()) is the same as calling TypeToken.getRawType(). * Make TypeToken members private * Remove incorrect statement about TypeToken wildcards It is possible to use wildcards as part of the type argument, e.g.: `new TypeToken<List<? extends CharSequence>>() {}` * Only allow direct subclasses of TypeToken Previously subclasses of subclasses (...) of TypeToken were allowed which can behave incorrectly when retrieving the type argument, e.g.: class SubTypeToken<T> extends TypeToken<Integer> {} new SubTypeToken<String>() {}.getType() This returned `String` despite the class extending TypeToken<Integer>. * Throw exception when TypeToken captures type variable Due to type erasure the runtime type argument for a type variable is not available. Therefore there is no point in capturing a type variable and it might even give a false sense of type-safety. * Make $Gson$Types members private * Rename $Gson$Types.getGenericSupertype parameter Rename the method parameter to match the documentation of the method and to be similar to getSupertype(...). * Improve tests and handle raw TypeToken supertype better * Make some $Gson$Types members package-private again to prevent synthetic accessors * Remove TypeToken check for type variable As mentioned in review comments, there are cases during serialization where usage of the type variable is not so problematic (but still not ideal).
2022-04-19 17:20:58 +02:00
}
}
2011-01-11 23:21:41 +01:00
}
// Have to declare these classes here as top-level classes because otherwise tests for
// TypeToken.getParameterized fail due to owner type mismatch
class GenericWithBound<T extends Number> {
}
class GenericWithMultiBound<T extends Number & CharSequence> {
}
@SuppressWarnings("serial")
abstract class ClassSatisfyingBounds extends Number implements CharSequence {
}