Skip to content

Commit b51d128

Browse files
committed
Cleanup and test exposed utility behavior.
1 parent 9de61e0 commit b51d128

File tree

2 files changed

+116
-20
lines changed

2 files changed

+116
-20
lines changed

retrofit/src/main/java/retrofit2/Utils.java

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,41 +36,41 @@ private Utils() {
3636
// No instances.
3737
}
3838

39-
public static Class<?> getRawType(Type type) {
39+
static Class<?> getRawType(Type type) {
40+
if (type == null) throw new NullPointerException("type == null");
41+
4042
if (type instanceof Class<?>) {
4143
// Type is a normal class.
4244
return (Class<?>) type;
43-
44-
} else if (type instanceof ParameterizedType) {
45+
}
46+
if (type instanceof ParameterizedType) {
4547
ParameterizedType parameterizedType = (ParameterizedType) type;
4648

4749
// I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
4850
// suspects some pathological case related to nested classes exists.
4951
Type rawType = parameterizedType.getRawType();
5052
if (!(rawType instanceof Class)) throw new IllegalArgumentException();
5153
return (Class<?>) rawType;
52-
53-
} else if (type instanceof GenericArrayType) {
54+
}
55+
if (type instanceof GenericArrayType) {
5456
Type componentType = ((GenericArrayType) type).getGenericComponentType();
5557
return Array.newInstance(getRawType(componentType), 0).getClass();
56-
57-
} else if (type instanceof TypeVariable) {
58+
}
59+
if (type instanceof TypeVariable) {
5860
// We could use the variable's bounds, but that won't work if there are multiple. Having a raw
5961
// type that's more general than necessary is okay.
6062
return Object.class;
61-
62-
} else if (type instanceof WildcardType) {
63+
}
64+
if (type instanceof WildcardType) {
6365
return getRawType(((WildcardType) type).getUpperBounds()[0]);
64-
65-
} else {
66-
String className = type == null ? "null" : type.getClass().getName();
67-
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
68-
+ "GenericArrayType, but <" + type + "> is of type " + className);
6966
}
67+
68+
throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
69+
+ "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
7070
}
7171

7272
/** Returns true if {@code a} and {@code b} are equal. */
73-
public static boolean equals(Type a, Type b) {
73+
static boolean equals(Type a, Type b) {
7474
if (a == b) {
7575
return true; // Also handles (a == null && b == null).
7676

@@ -162,7 +162,7 @@ static int hashCodeOrZero(Object o) {
162162
return o != null ? o.hashCode() : 0;
163163
}
164164

165-
public static String typeToString(Type type) {
165+
static String typeToString(Type type) {
166166
return type instanceof Class ? ((Class<?>) type).getName() : type.toString();
167167
}
168168

@@ -173,13 +173,13 @@ public static String typeToString(Type type) {
173173
*
174174
* @param supertype a superclass of, or interface implemented by, this.
175175
*/
176-
public static Type getSupertype(Type context, Class<?> contextRawType, Class<?> supertype) {
176+
static Type getSupertype(Type context, Class<?> contextRawType, Class<?> supertype) {
177177
if (!supertype.isAssignableFrom(contextRawType)) throw new IllegalArgumentException();
178178
return resolve(context, contextRawType,
179179
getGenericSupertype(context, contextRawType, supertype));
180180
}
181181

182-
public static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
182+
static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {
183183
// This implementation is made a little more complicated in an attempt to avoid object-creation.
184184
while (true) {
185185
if (toResolve instanceof TypeVariable) {
@@ -318,9 +318,9 @@ static <T> void validateServiceInterface(Class<T> service) {
318318

319319
static Type getParameterUpperBound(int index, ParameterizedType type) {
320320
Type[] types = type.getActualTypeArguments();
321-
if (types.length <= index) {
321+
if (index < 0 || index >= types.length) {
322322
throw new IllegalArgumentException(
323-
"Expected at least " + index + " type argument(s) but got: " + Arrays.toString(types));
323+
"Index " + index + " not in range [0," + types.length + ") for " + type);
324324
}
325325
Type paramType = types[index];
326326
if (paramType instanceof WildcardType) {
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* Copyright (C) 2016 Square, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package retrofit2;
17+
18+
import com.google.common.reflect.TypeToken;
19+
import java.lang.reflect.ParameterizedType;
20+
import java.lang.reflect.Type;
21+
import java.util.List;
22+
import java.util.Map;
23+
import org.junit.Test;
24+
25+
import static org.assertj.core.api.Assertions.assertThat;
26+
import static org.junit.Assert.fail;
27+
import static retrofit2.CallAdapter.Factory.getParameterUpperBound;
28+
import static retrofit2.CallAdapter.Factory.getRawType;
29+
30+
public final class CallAdapterTest {
31+
@Test public void parameterizedTypeInvalidIndex() {
32+
ParameterizedType listOfString = (ParameterizedType) new TypeToken<List<String>>() {}.getType();
33+
try {
34+
getParameterUpperBound(-1, listOfString);
35+
fail();
36+
} catch (IllegalArgumentException e) {
37+
assertThat(e).hasMessage("Index -1 not in range [0,1) for java.util.List<java.lang.String>");
38+
}
39+
try {
40+
getParameterUpperBound(1, listOfString);
41+
fail();
42+
} catch (IllegalArgumentException e) {
43+
assertThat(e).hasMessage("Index 1 not in range [0,1) for java.util.List<java.lang.String>");
44+
}
45+
}
46+
47+
@Test public void parameterizedTypes() {
48+
ParameterizedType one = (ParameterizedType) new TypeToken<List<String>>() {}.getType();
49+
assertThat(getParameterUpperBound(0, one)).isSameAs(String.class);
50+
51+
ParameterizedType two = (ParameterizedType) new TypeToken<Map<String, String>>() {}.getType();
52+
assertThat(getParameterUpperBound(0, two)).isSameAs(String.class);
53+
assertThat(getParameterUpperBound(1, two)).isSameAs(String.class);
54+
55+
ParameterizedType wild = (ParameterizedType) new TypeToken<List<? extends CharSequence>>() {
56+
}.getType();
57+
assertThat(getParameterUpperBound(0, wild)).isSameAs(CharSequence.class);
58+
}
59+
60+
@Test public void rawTypeThrowsOnNull() {
61+
try {
62+
getRawType(null);
63+
fail();
64+
} catch (NullPointerException e) {
65+
assertThat(e).hasMessage("type == null");
66+
}
67+
}
68+
69+
@Test public void rawTypes() throws NoSuchMethodException {
70+
assertThat(getRawType(String.class)).isSameAs(String.class);
71+
72+
Type listOfString = new TypeToken<List<String>>() {}.getType();
73+
assertThat(getRawType(listOfString)).isSameAs(List.class);
74+
75+
Type stringArray = new TypeToken<String[]>() {}.getType();
76+
assertThat(getRawType(stringArray)).isSameAs(String[].class);
77+
78+
Type wild = ((ParameterizedType) new TypeToken<List<? extends CharSequence>>() {
79+
}.getType()).getActualTypeArguments()[0];
80+
assertThat(getRawType(wild)).isSameAs(CharSequence.class);
81+
82+
Type wildParam = ((ParameterizedType) new TypeToken<List<? extends List<String>>>() {
83+
}.getType()).getActualTypeArguments()[0];
84+
assertThat(getRawType(wildParam)).isSameAs(List.class);
85+
86+
Type typeVar = A.class.getDeclaredMethod("method").getGenericReturnType();
87+
assertThat(getRawType(typeVar)).isSameAs(Object.class);
88+
}
89+
90+
@SuppressWarnings("unused") // Used reflectively.
91+
static class A<T> {
92+
T method() {
93+
return null;
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)