Skip to content

Commit

Permalink
Port Gson Types recursion fix for subtypeOf/supertypeOf
Browse files Browse the repository at this point in the history
From google/gson@a300148

First step in resolving #338
  • Loading branch information
ZacSweers committed Oct 13, 2019
1 parent dbed99d commit 7b73ce0
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 2 deletions.
16 changes: 14 additions & 2 deletions moshi/src/main/java/com/squareup/moshi/Types.java
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,27 @@ public static GenericArrayType arrayOf(Type componentType) {
* ? extends Object}.
*/
public static WildcardType subtypeOf(Type bound) {
return new WildcardTypeImpl(new Type[] { bound }, EMPTY_TYPE_ARRAY);
Type[] upperBounds;
if (bound instanceof WildcardType) {
upperBounds = ((WildcardType) bound).getUpperBounds();
} else {
upperBounds = new Type[] { bound };
}
return new WildcardTypeImpl(upperBounds, EMPTY_TYPE_ARRAY);
}

/**
* Returns a type that represents an unknown supertype of {@code bound}. For example, if {@code
* bound} is {@code String.class}, this returns {@code ? super String}.
*/
public static WildcardType supertypeOf(Type bound) {
return new WildcardTypeImpl(new Type[] { Object.class }, new Type[] { bound });
Type[] lowerBounds;
if (bound instanceof WildcardType) {
lowerBounds = ((WildcardType) bound).getLowerBounds();
} else {
lowerBounds = new Type[] { bound };
}
return new WildcardTypeImpl(new Type[] { Object.class }, lowerBounds);
}

public static Class<?> getRawType(Type type) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Copyright (C) 2017 Gson Authors
*
* 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.squareup.moshi.internal;

import com.squareup.moshi.JsonAdapter;
import com.squareup.moshi.Moshi;
import com.squareup.moshi.Types;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
* Test fixes for infinite recursion on {@link Util#resolve(java.lang.reflect.Type, Class,
* java.lang.reflect.Type)}, described at <a href="https://github.com/google/gson/issues/440">Issue #440</a>
* and similar issues.
* <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 ? extends ... ? extends A&gt;'
* <p>
* Adapted from https://github.com/google/gson/commit/a300148003e3a067875b1444e8268b6e0f0e0e02 in
* service of https://github.com/square/moshi/issues/338.
*/
public final class RecursiveTypesResolveTest {

private static class Foo1<A> {
public Foo2<? extends A> foo2;
}

private static class Foo2<B> {
public Foo1<? super B> foo1;
}

/**
* Test simplest case of recursion.
*/
@Test public void testRecursiveResolveSimple() {
JsonAdapter<Foo1> adapter = new Moshi.Builder().build().adapter(Foo1.class);
assertNotNull(adapter);
}

//
// Tests belows check the behaviour of the methods changed for the fix
//

@Test public void testDoubleSupertype() {
assertEquals(Types.supertypeOf(Number.class),
Types.supertypeOf(Types.supertypeOf(Number.class)));
}

@Test public void testDoubleSubtype() {
assertEquals(Types.subtypeOf(Number.class),
Types.subtypeOf(Types.subtypeOf(Number.class)));
}

@Test public void testSuperSubtype() {
assertEquals(Types.subtypeOf(Object.class),
Types.supertypeOf(Types.subtypeOf(Number.class)));
}

@Test public void testSubSupertype() {
assertEquals(Types.subtypeOf(Object.class),
Types.subtypeOf(Types.supertypeOf(Number.class)));
}
}

0 comments on commit 7b73ce0

Please sign in to comment.