Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/main' into marcono1234/p…
Browse files Browse the repository at this point in the history
…roguard-default-rules-improvements
  • Loading branch information
Marcono1234 committed Jul 4, 2023
2 parents 6feba4c + a589ef2 commit f5957a2
Show file tree
Hide file tree
Showing 10 changed files with 146 additions and 128 deletions.
2 changes: 1 addition & 1 deletion gson/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<dependency>
<groupId>com.google.errorprone</groupId>
<artifactId>error_prone_annotations</artifactId>
<version>2.19.1</version>
<version>2.20.0</version>
</dependency>

<dependency>
Expand Down
33 changes: 23 additions & 10 deletions gson/src/main/java/com/google/gson/internal/$Gson$Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Objects;
import java.util.Properties;

/**
* Static methods for working with types.
Expand Down Expand Up @@ -138,9 +138,8 @@ public static Class<?> getRawType(Type type) {
} else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;

// I'm not exactly sure why getRawType() returns Type instead of Class.
// Neal isn't either but suspects some pathological case related
// to nested classes exists.
// getRawType() returns Type instead of Class; that seems to be an API mistake,
// see https://bugs.openjdk.org/browse/JDK-8250659
Type rawType = parameterizedType.getRawType();
checkArgument(rawType instanceof Class);
return (Class<?>) rawType;
Expand Down Expand Up @@ -481,19 +480,33 @@ static void checkNotPrimitive(Type type) {
checkArgument(!(type instanceof Class<?>) || !((Class<?>) type).isPrimitive());
}

/**
* Whether an {@linkplain ParameterizedType#getOwnerType() owner type} must be specified when
* constructing a {@link ParameterizedType} for {@code rawType}.
*
* <p>Note that this method might not require an owner type for all cases where Java reflection
* would create parameterized types with owner type.
*/
public static boolean requiresOwnerType(Type rawType) {
if (rawType instanceof Class<?>) {
Class<?> rawTypeAsClass = (Class<?>) rawType;
return !Modifier.isStatic(rawTypeAsClass.getModifiers())
&& rawTypeAsClass.getDeclaringClass() != null;
}
return false;
}

private static final class ParameterizedTypeImpl implements ParameterizedType, Serializable {
private final Type ownerType;
private final Type rawType;
private final Type[] typeArguments;

public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
// TODO: Should this enforce that rawType is a Class? See JDK implementation of
// the ParameterizedType interface and https://bugs.openjdk.org/browse/JDK-8250659
requireNonNull(rawType);
// require an owner type if the raw type needs it
if (rawType instanceof Class<?>) {
Class<?> rawTypeAsClass = (Class<?>) rawType;
boolean isStaticOrTopLevelClass = Modifier.isStatic(rawTypeAsClass.getModifiers())
|| rawTypeAsClass.getEnclosingClass() == null;
checkArgument(ownerType != null || isStaticOrTopLevelClass);
if (ownerType == null && requiresOwnerType(rawType)) {
throw new IllegalArgumentException("Must specify owner type for " + rawType);
}

this.ownerType = ownerType == null ? null : canonicalize(ownerType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class NonNullElementWrapperList<E> extends AbstractList<E> implements Ran
// Explicitly specify ArrayList as type to guarantee that delegate implements RandomAccess
private final ArrayList<E> delegate;

@SuppressWarnings("NonApiType")
public NonNullElementWrapperList(ArrayList<E> delegate) {
this.delegate = Objects.requireNonNull(delegate);
}
Expand Down
22 changes: 17 additions & 5 deletions gson/src/main/java/com/google/gson/reflect/TypeToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ public static <T> TypeToken<T> get(Class<T> type) {
* and care must be taken to pass in the correct number of type arguments.
*
* @throws IllegalArgumentException
* If {@code rawType} is not of type {@code Class}, or if the type arguments are invalid for
* the raw type
* If {@code rawType} is not of type {@code Class}, if it is not a generic type, or if the
* type arguments are invalid for the raw type
*/
public static TypeToken<?> getParameterized(Type rawType, Type... typeArguments) {
Objects.requireNonNull(rawType);
Expand All @@ -354,6 +354,18 @@ public static TypeToken<?> getParameterized(Type rawType, Type... typeArguments)
Class<?> rawClass = (Class<?>) rawType;
TypeVariable<?>[] typeVariables = rawClass.getTypeParameters();

// Note: Does not check if owner type of rawType is generic because this factory method
// does not support specifying owner type
if (typeVariables.length == 0) {
throw new IllegalArgumentException(rawClass.getName() + " is not a generic type");
}

// Check for this here to avoid misleading exception thrown by ParameterizedTypeImpl
if ($Gson$Types.requiresOwnerType(rawType)) {
throw new IllegalArgumentException("Raw type " + rawClass.getName() + " is not supported because"
+ " it requires specifying an owner type");
}

int expectedArgsCount = typeVariables.length;
int actualArgsCount = typeArguments.length;
if (actualArgsCount != expectedArgsCount) {
Expand All @@ -362,16 +374,16 @@ public static TypeToken<?> getParameterized(Type rawType, Type... typeArguments)
}

for (int i = 0; i < expectedArgsCount; i++) {
Type typeArgument = typeArguments[i];
Type typeArgument = Objects.requireNonNull(typeArguments[i], "Type argument must not be null");
Class<?> rawTypeArgument = $Gson$Types.getRawType(typeArgument);
TypeVariable<?> typeVariable = typeVariables[i];

for (Type bound : typeVariable.getBounds()) {
Class<?> rawBound = $Gson$Types.getRawType(bound);

if (!rawBound.isAssignableFrom(rawTypeArgument)) {
throw new IllegalArgumentException("Type argument " + typeArgument + " does not satisfy bounds "
+ "for type variable " + typeVariable + " declared by " + rawType);
throw new IllegalArgumentException("Type argument " + typeArgument + " does not satisfy bounds"
+ " for type variable " + typeVariable + " declared by " + rawType);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,7 @@ public void testTreeSetDeserialization() {
assertThat(treeSet).contains("Value1");
}

@SuppressWarnings("UnnecessaryStringBuilder") // TODO: b/287969247 - remove when EP bug fixed
@Test
public void testStringBuilderSerialization() {
StringBuilder sb = new StringBuilder("abc");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ public void testArrayWithOneNullExposeFieldObjectSerialization() {
ClassWithExposedFields[] objects = { object1, object2, object3 };

String json = gson.toJson(objects);
String expected = new StringBuilder()
.append('[').append(object1.getExpectedJson()).append(',')
.append(object2.getExpectedJson()).append(',')
.append(object3.getExpectedJson()).append(']')
.toString();
String expected =
'['
+ object1.getExpectedJson()
+ ','
+ object2.getExpectedJson()
+ ','
+ object3.getExpectedJson()
+ ']';

assertThat(json).isEqualTo(expected);
}
Expand Down
32 changes: 24 additions & 8 deletions gson/src/test/java/com/google/gson/internal/GsonTypesTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
package com.google.gson.internal;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertThrows;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
Expand All @@ -29,20 +29,33 @@ public final class GsonTypesTest {
@Test
public void testNewParameterizedTypeWithoutOwner() throws Exception {
// List<A>. List is a top-level class
Type type = $Gson$Types.newParameterizedTypeWithOwner(null, List.class, A.class);
assertThat(getFirstTypeArgument(type)).isEqualTo(A.class);
ParameterizedType type = $Gson$Types.newParameterizedTypeWithOwner(null, List.class, A.class);
assertThat(type.getOwnerType()).isNull();
assertThat(type.getRawType()).isEqualTo(List.class);
assertThat(type.getActualTypeArguments()).asList().containsExactly(A.class);

// A<B>. A is a static inner class.
type = $Gson$Types.newParameterizedTypeWithOwner(null, A.class, B.class);
assertThat(getFirstTypeArgument(type)).isEqualTo(B.class);

IllegalArgumentException e = assertThrows(IllegalArgumentException.class,
// NonStaticInner<A> is not allowed without owner
() -> $Gson$Types.newParameterizedTypeWithOwner(null, NonStaticInner.class, A.class));
assertThat(e).hasMessageThat().isEqualTo("Must specify owner type for " + NonStaticInner.class);

type = $Gson$Types.newParameterizedTypeWithOwner(GsonTypesTest.class, NonStaticInner.class, A.class);
assertThat(type.getOwnerType()).isEqualTo(GsonTypesTest.class);
assertThat(type.getRawType()).isEqualTo(NonStaticInner.class);
assertThat(type.getActualTypeArguments()).asList().containsExactly(A.class);

final class D {
}
try {
// D<A> is not allowed since D is not a static inner class
$Gson$Types.newParameterizedTypeWithOwner(null, D.class, A.class);
fail();
} catch (IllegalArgumentException expected) {}

// D<A> is allowed since D has no owner type
type = $Gson$Types.newParameterizedTypeWithOwner(null, D.class, A.class);
assertThat(type.getOwnerType()).isNull();
assertThat(type.getRawType()).isEqualTo(D.class);
assertThat(type.getActualTypeArguments()).asList().containsExactly(A.class);

// A<D> is allowed.
type = $Gson$Types.newParameterizedTypeWithOwner(null, A.class, D.class);
Expand All @@ -63,6 +76,9 @@ private static final class B {
}
private static final class C {
}
@SuppressWarnings({"ClassCanBeStatic", "UnusedTypeParameter"})
private final class NonStaticInner<T> {
}

/**
* Given a parameterized type A&lt;B,C&gt;, returns B. If the specified type is not
Expand Down
Loading

0 comments on commit f5957a2

Please sign in to comment.