From 467e7cced827ea546a52c252f37bf4999e3e4675 Mon Sep 17 00:00:00 2001 From: Scott Blum Date: Tue, 19 Aug 2014 16:55:54 -0400 Subject: [PATCH] Remove TypeLiteral, test fixes. --- .../java/com/squareup/moshi/TypeLiteral.java | 105 ------------------ .../main/java/com/squareup/moshi/Types.java | 12 +- .../com/squareup/moshi/JsonReaderTest.java | 4 +- .../java/com/squareup/moshi/MoshiTest.java | 11 +- .../java/com/squareup/moshi/TypesTest.java | 40 ++++--- 5 files changed, 43 insertions(+), 129 deletions(-) delete mode 100644 moshi/src/main/java/com/squareup/moshi/TypeLiteral.java diff --git a/moshi/src/main/java/com/squareup/moshi/TypeLiteral.java b/moshi/src/main/java/com/squareup/moshi/TypeLiteral.java deleted file mode 100644 index 6172a55..0000000 --- a/moshi/src/main/java/com/squareup/moshi/TypeLiteral.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2008 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.squareup.moshi; - -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; - -/** - * Represents a generic type {@code T}. Java doesn't yet provide a way to represent generic types, - * so this class does. Forces clients to create a subclass of this class which enables retrieval the - * type information even at runtime. - * - *

For example, to create a type literal for {@code List}, you can create an empty - * anonymous inner class:

   {@code
- *
- *   TypeToken> list = new TypeToken>() {};
- * }
- * - *

This syntax cannot be used to create type literals that have wildcard parameters, such as - * {@code Class} or {@code List}. - * - * @author Bob Lee - * @author Sven Mawson - * @author Jesse Wilson - */ -public class TypeLiteral { - final Class rawType; - final Type type; - final int hashCode; - - /** - * Constructs a new type literal. Derives represented class from type parameter. - * - *

Clients create an empty anonymous subclass. Doing so embeds the type parameter in the - * anonymous class's type hierarchy so we can reconstitute it at runtime despite erasure. - */ - @SuppressWarnings("unchecked") - protected TypeLiteral() { - this.type = getSuperclassTypeParameter(getClass()); - this.rawType = (Class) Types.getRawType(type); - this.hashCode = type.hashCode(); - } - - /** Unsafe. Constructs a type literal manually. */ - @SuppressWarnings("unchecked") - TypeLiteral(Type type) { - if (type == null) throw new NullPointerException("type == null"); - this.type = Types.canonicalize(type); - this.rawType = (Class) Types.getRawType(this.type); - this.hashCode = this.type.hashCode(); - } - - /** Returns the type from super class's type parameter in canonical for}. */ - static Type getSuperclassTypeParameter(Class subclass) { - Type superclass = subclass.getGenericSuperclass(); - if (superclass instanceof Class) throw new IllegalArgumentException("Missing type parameter."); - ParameterizedType parameterized = (ParameterizedType) superclass; - return Types.canonicalize(parameterized.getActualTypeArguments()[0]); - } - - /** Returns the raw (non-generic) type for this type literal. */ - public final Class getRawType() { - return rawType; - } - - public final Type getType() { - return type; - } - - @Override public final int hashCode() { - return this.hashCode; - } - - @Override public final boolean equals(Object o) { - return o instanceof TypeLiteral - && Types.equals(type, ((TypeLiteral) o).type); - } - - @Override public final String toString() { - return Types.typeToString(type); - } - - /** Returns a type literal for {@code type}. */ - public static TypeLiteral get(Type type) { - return new TypeLiteral(type); - } - - /** Returns a type literal for {@code type}. */ - public static TypeLiteral get(Class type) { - return new TypeLiteral(type); - } -} diff --git a/moshi/src/main/java/com/squareup/moshi/Types.java b/moshi/src/main/java/com/squareup/moshi/Types.java index 0591724..0b3dc85 100644 --- a/moshi/src/main/java/com/squareup/moshi/Types.java +++ b/moshi/src/main/java/com/squareup/moshi/Types.java @@ -41,12 +41,22 @@ final class Types { private Types() { } + /** + * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType}. + */ + public static ParameterizedType newParameterizedType(Type rawType, Type... typeArguments) { + return new ParameterizedTypeImpl(null, rawType, typeArguments); + } + /** * Returns a new parameterized type, applying {@code typeArguments} to {@code rawType} and * enclosed by {@code ownerType}. */ public static ParameterizedType newParameterizedTypeWithOwner( Type ownerType, Type rawType, Type... typeArguments) { + if (ownerType == null) { + throw new NullPointerException("ownerType"); + } return new ParameterizedTypeImpl(ownerType, rawType, typeArguments); } @@ -334,7 +344,7 @@ final class Types { } return changed - ? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args) + ? new ParameterizedTypeImpl(newOwnerType, original.getRawType(), args) : original; } else if (toResolve instanceof WildcardType) { diff --git a/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java b/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java index 000c679..f971889 100644 --- a/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java +++ b/moshi/src/test/java/com/squareup/moshi/JsonReaderTest.java @@ -31,6 +31,7 @@ import static com.squareup.moshi.JsonToken.NAME; import static com.squareup.moshi.JsonToken.NULL; import static com.squareup.moshi.JsonToken.NUMBER; import static com.squareup.moshi.JsonToken.STRING; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -337,7 +338,8 @@ public final class JsonReaderTest { try { reader.nextDouble(); fail(); - } catch (IOException expected) { + } catch (NumberFormatException expected) { + assertThat(expected).hasMessageContaining("NaN"); } } diff --git a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java index 77c7bd3..ac83735 100644 --- a/moshi/src/test/java/com/squareup/moshi/MoshiTest.java +++ b/moshi/src/test/java/com/squareup/moshi/MoshiTest.java @@ -568,8 +568,8 @@ public final class MoshiTest { @Test public void listJsonAdapter() throws Exception { Moshi moshi = new Moshi.Builder().build(); - JsonAdapter> adapter = moshi.adapter(new TypeLiteral>() { - }.getType()); + JsonAdapter> adapter = + moshi.adapter(Types.newParameterizedType(List.class, String.class)); assertThat(adapter.toJson(Arrays.asList("a", "b"))).isEqualTo("[\"a\",\"b\"]"); assertThat(adapter.fromJson("[\"a\",\"b\"]")).isEqualTo(Arrays.asList("a", "b")); } @@ -580,7 +580,8 @@ public final class MoshiTest { set.add("b"); Moshi moshi = new Moshi.Builder().build(); - JsonAdapter> adapter = moshi.adapter(new TypeLiteral>() {}.getType()); + JsonAdapter> adapter = + moshi.adapter(Types.newParameterizedType(Set.class, String.class)); assertThat(adapter.toJson(set)).isEqualTo("[\"a\",\"b\"]"); assertThat(adapter.fromJson("[\"a\",\"b\"]")).isEqualTo(set); } @@ -591,8 +592,8 @@ public final class MoshiTest { collection.add("b"); Moshi moshi = new Moshi.Builder().build(); - JsonAdapter> adapter = moshi.adapter( - new TypeLiteral>() {}.getType()); + JsonAdapter> adapter = + moshi.adapter(Types.newParameterizedType(Collection.class, String.class)); assertThat(adapter.toJson(collection)).isEqualTo("[\"a\",\"b\"]"); assertThat(adapter.fromJson("[\"a\",\"b\"]")).containsExactly("a", "b"); } diff --git a/moshi/src/test/java/com/squareup/moshi/TypesTest.java b/moshi/src/test/java/com/squareup/moshi/TypesTest.java index b4e4c85..fa77ba1 100644 --- a/moshi/src/test/java/com/squareup/moshi/TypesTest.java +++ b/moshi/src/test/java/com/squareup/moshi/TypesTest.java @@ -28,36 +28,53 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; public class TypesTest { - @Test public void newParameterizedTypeWithoutOwner() throws Exception { + + @Test public void newParameterizedType() throws Exception { // List. List is a top-level class. - Type type = Types.newParameterizedTypeWithOwner(null, List.class, A.class); + Type type = Types.newParameterizedType(List.class, A.class); assertThat(getFirstTypeArgument(type)).isEqualTo(A.class); // A. A is a static inner class. - type = Types.newParameterizedTypeWithOwner(null, A.class, B.class); + type = Types.newParameterizedType(A.class, B.class); assertThat(getFirstTypeArgument(type)).isEqualTo(B.class); final class D { } try { // D is not allowed since D is not a static inner class. - Types.newParameterizedTypeWithOwner(null, D.class, A.class); + Types.newParameterizedType(D.class, A.class); fail(); } catch (IllegalArgumentException expected) { } // A is allowed. - type = Types.newParameterizedTypeWithOwner(null, A.class, D.class); + type = Types.newParameterizedType(A.class, D.class); assertThat(getFirstTypeArgument(type)).isEqualTo(D.class); } @Test public void getFirstTypeArgument() throws Exception { assertNull(getFirstTypeArgument(A.class)); - Type type = Types.newParameterizedTypeWithOwner(null, A.class, B.class, C.class); + Type type = Types.newParameterizedType(A.class, B.class, C.class); assertThat(getFirstTypeArgument(type)).isEqualTo(B.class); } + @Test public void newParameterizedTypeObjectMethods() throws Exception { + Type mapOfStringIntegerType = TypesTest.class.getDeclaredField( + "mapOfStringInteger").getGenericType(); + ParameterizedType newMapType = Types.newParameterizedType(Map.class, String.class, Integer.class); + assertThat(newMapType).isEqualTo(mapOfStringIntegerType); + assertThat(newMapType.hashCode()).isEqualTo(mapOfStringIntegerType.hashCode()); + assertThat(newMapType.toString()).isEqualTo(mapOfStringIntegerType.toString()); + + Type arrayListOfMapOfStringIntegerType = TypesTest.class.getDeclaredField( + "arrayListOfMapOfStringInteger").getGenericType(); + ParameterizedType newListType = Types.newParameterizedType(ArrayList.class, newMapType); + assertThat(newListType).isEqualTo(arrayListOfMapOfStringIntegerType); + assertThat(newListType.hashCode()).isEqualTo(arrayListOfMapOfStringIntegerType.hashCode()); + assertThat(newListType.toString()).isEqualTo(arrayListOfMapOfStringIntegerType.toString()); + } + private static final class A { } @@ -85,17 +102,6 @@ public class TypesTest { interface StringIntegerMap extends Map { } - @Test public void typeLiteral() throws Exception { - TypeLiteral> typeLiteral = new TypeLiteral>() {}; - TypeLiteral fromReflection = TypeLiteral.get( - TypesTest.class.getDeclaredField("mapOfStringInteger").getGenericType()); - assertThat(typeLiteral).isEqualTo(fromReflection); - assertThat(typeLiteral.hashCode()).isEqualTo(fromReflection.hashCode()); - assertThat(typeLiteral.toString()) - .isEqualTo("java.util.Map"); - assertThat(typeLiteral.getRawType()).isEqualTo(Map.class); - } - @Test public void arrayComponentType() throws Exception { assertThat(Types.arrayComponentType(String[][].class)).isEqualTo(String[].class); assertThat(Types.arrayComponentType(String[].class)).isEqualTo(String.class);