Small cleanups from a few past PRs (#1509)

This commit is contained in:
Zac Sweers
2022-01-20 10:23:22 -05:00
committed by GitHub
parent c5be69a93c
commit c5e98e5be8
4 changed files with 65 additions and 53 deletions

View File

@@ -95,7 +95,7 @@ internal class AdapterMethodsFactory(
} }
companion object { companion object {
fun get(adapter: Any): AdapterMethodsFactory { operator fun invoke(adapter: Any): AdapterMethodsFactory {
val toAdapters = mutableListOf<AdapterMethod>() val toAdapters = mutableListOf<AdapterMethod>()
val fromAdapters = mutableListOf<AdapterMethod>() val fromAdapters = mutableListOf<AdapterMethod>()
@@ -132,7 +132,7 @@ internal class AdapterMethodsFactory(
* Returns an object that calls a `method` method on `adapter` in service of * Returns an object that calls a `method` method on `adapter` in service of
* converting an object to JSON. * converting an object to JSON.
*/ */
fun toAdapter(adapter: Any, method: Method): AdapterMethod { private fun toAdapter(adapter: Any, method: Method): AdapterMethod {
method.isAccessible = true method.isAccessible = true
val returnType = method.genericReturnType val returnType = method.genericReturnType
val parameterTypes = method.genericParameterTypes val parameterTypes = method.genericParameterTypes
@@ -142,10 +142,11 @@ internal class AdapterMethodsFactory(
returnType == Void.TYPE && returnType == Void.TYPE &&
parametersAreJsonAdapters(2, parameterTypes) parametersAreJsonAdapters(2, parameterTypes)
return when { return when {
methodSignatureIncludesJsonWriterAndJsonAdapter -> {
// void pointToJson(JsonWriter jsonWriter, Point point) { // void pointToJson(JsonWriter jsonWriter, Point point) {
// void pointToJson(JsonWriter jsonWriter, Point point, JsonAdapter<?> adapter, ...) { // void pointToJson(JsonWriter jsonWriter, Point point, JsonAdapter<?> adapter, ...) {
methodSignatureIncludesJsonWriterAndJsonAdapter -> {
val qualifierAnnotations = parameterAnnotations[1].jsonAnnotations val qualifierAnnotations = parameterAnnotations[1].jsonAnnotations
object : AdapterMethod( object : AdapterMethod(
adaptersOffset = 2, adaptersOffset = 2,
type = parameterTypes[1], type = parameterTypes[1],
@@ -156,7 +157,7 @@ internal class AdapterMethodsFactory(
nullable = true nullable = true
) { ) {
override fun toJson(moshi: Moshi, writer: JsonWriter, value: Any?) { override fun toJson(moshi: Moshi, writer: JsonWriter, value: Any?) {
invoke(writer, value) invokeMethod(writer, value)
} }
} }
} }
@@ -174,10 +175,14 @@ internal class AdapterMethodsFactory(
method = method, method = method,
nullable = nullable nullable = nullable
) { ) {
private lateinit var delegate: JsonAdapter<Any> private lateinit var delegate: JsonAdapter<Any>
override fun bind(moshi: Moshi, factory: JsonAdapter.Factory) { override fun bind(moshi: Moshi, factory: JsonAdapter.Factory) {
super.bind(moshi, factory) super.bind(moshi, factory)
delegate = if (Types.equals(parameterTypes[0], returnType) && qualifierAnnotations == returnTypeAnnotations) { val shouldSkip = Types.equals(parameterTypes[0], returnType) &&
qualifierAnnotations == returnTypeAnnotations
delegate = if (shouldSkip) {
moshi.nextAdapter(factory, returnType, returnTypeAnnotations) moshi.nextAdapter(factory, returnType, returnTypeAnnotations)
} else { } else {
moshi.adapter(returnType, returnTypeAnnotations) moshi.adapter(returnType, returnTypeAnnotations)
@@ -185,19 +190,20 @@ internal class AdapterMethodsFactory(
} }
override fun toJson(moshi: Moshi, writer: JsonWriter, value: Any?) { override fun toJson(moshi: Moshi, writer: JsonWriter, value: Any?) {
val intermediate = invoke(value) delegate.toJson(writer, invokeMethod(value))
delegate.toJson(writer, intermediate)
} }
} }
} }
else -> { else -> {
throw IllegalArgumentException( throw IllegalArgumentException(
"""Unexpected signature for $method. """
Unexpected signature for $method.
@ToJson method signatures may have one of the following structures: @ToJson method signatures may have one of the following structures:
<any access modifier> void toJson(JsonWriter writer, T value) throws <any>; <any access modifier> void toJson(JsonWriter writer, T value) throws <any>;
<any access modifier> void toJson(JsonWriter writer, T value, JsonAdapter<any> delegate, <any more delegates>) throws <any>; <any access modifier> void toJson(JsonWriter writer, T value, JsonAdapter<any> delegate, <any more delegates>) throws <any>;
<any access modifier> R toJson(T value) throws <any>; <any access modifier> R toJson(T value) throws <any>;
"""
""".trimIndent()
) )
} }
} }
@@ -217,7 +223,7 @@ internal class AdapterMethodsFactory(
* Returns an object that calls a `method` method on `adapter` in service of * Returns an object that calls a `method` method on `adapter` in service of
* converting an object from JSON. * converting an object from JSON.
*/ */
fun fromAdapter(adapter: Any, method: Method): AdapterMethod { private fun fromAdapter(adapter: Any, method: Method): AdapterMethod {
method.isAccessible = true method.isAccessible = true
val returnType = method.genericReturnType val returnType = method.genericReturnType
val returnTypeAnnotations = method.jsonAnnotations val returnTypeAnnotations = method.jsonAnnotations
@@ -240,7 +246,7 @@ internal class AdapterMethodsFactory(
method = method, method = method,
nullable = true nullable = true
) { ) {
override fun fromJson(moshi: Moshi, reader: JsonReader) = invoke(reader) override fun fromJson(moshi: Moshi, reader: JsonReader) = invokeMethod(reader)
} }
} }
parameterTypes.size == 1 && returnType != Void.TYPE -> { parameterTypes.size == 1 && returnType != Void.TYPE -> {
@@ -269,18 +275,20 @@ internal class AdapterMethodsFactory(
override fun fromJson(moshi: Moshi, reader: JsonReader): Any? { override fun fromJson(moshi: Moshi, reader: JsonReader): Any? {
val intermediate = delegate.fromJson(reader) val intermediate = delegate.fromJson(reader)
return invoke(intermediate) return invokeMethod(intermediate)
} }
} }
} }
else -> { else -> {
throw IllegalArgumentException( throw IllegalArgumentException(
"""Unexpected signature for $method. """
Unexpected signature for $method.
@FromJson method signatures may have one of the following structures: @FromJson method signatures may have one of the following structures:
<any access modifier> R fromJson(JsonReader jsonReader) throws <any>; <any access modifier> R fromJson(JsonReader jsonReader) throws <any>;
<any access modifier> R fromJson(JsonReader jsonReader, JsonAdapter<any> delegate, <any more delegates>) throws <any>; <any access modifier> R fromJson(JsonReader jsonReader, JsonAdapter<any> delegate, <any more delegates>) throws <any>;
<any access modifier> R fromJson(T value) throws <any>; <any access modifier> R fromJson(T value) throws <any>;
"""
""".trimIndent()
) )
} }
} }
@@ -322,9 +330,7 @@ internal class AdapterMethodsFactory(
val jsonAnnotations = parameterAnnotations[i].jsonAnnotations val jsonAnnotations = parameterAnnotations[i].jsonAnnotations
jsonAdapters[i - adaptersOffset] = jsonAdapters[i - adaptersOffset] =
if (Types.equals(this.type, type) && annotations == jsonAnnotations) { if (Types.equals(this.type, type) && annotations == jsonAnnotations) {
moshi.nextAdapter( moshi.nextAdapter(factory, type, jsonAnnotations)
factory, type, jsonAnnotations
)
} else { } else {
moshi.adapter<Any>(type, jsonAnnotations) moshi.adapter<Any>(type, jsonAnnotations)
} }
@@ -337,9 +343,9 @@ internal class AdapterMethodsFactory(
open fun fromJson(moshi: Moshi, reader: JsonReader): Any? = throw AssertionError() open fun fromJson(moshi: Moshi, reader: JsonReader): Any? = throw AssertionError()
/** Invoke the method with one fixed argument, plus any number of JSON adapter arguments. */ /** Invoke the method with one fixed argument, plus any number of JSON adapter arguments. */
protected fun invoke(initialFixedArgumentForAdapterMethod: Any?): Any? { protected fun invokeMethod(arg: Any?): Any? {
val args = arrayOfNulls<Any>(1 + jsonAdapters.size) val args = arrayOfNulls<Any>(1 + jsonAdapters.size)
args[0] = initialFixedArgumentForAdapterMethod args[0] = arg
jsonAdapters.copyInto(args, 1, 0, jsonAdapters.size) jsonAdapters.copyInto(args, 1, 0, jsonAdapters.size)
return try { return try {
@@ -350,10 +356,10 @@ internal class AdapterMethodsFactory(
} }
/** Invoke the method with two fixed arguments, plus any number of JSON adapter arguments. */ /** Invoke the method with two fixed arguments, plus any number of JSON adapter arguments. */
protected fun invoke(fixedArgument1: Any?, fixedArgument2: Any?): Any? { protected fun invokeMethod(arg0: Any?, arg1: Any?): Any? {
val args = arrayOfNulls<Any>(2 + jsonAdapters.size) val args = arrayOfNulls<Any>(2 + jsonAdapters.size)
args[0] = fixedArgument1 args[0] = arg0
args[1] = fixedArgument2 args[1] = arg1
jsonAdapters.copyInto(args, 2, 0, jsonAdapters.size) jsonAdapters.copyInto(args, 2, 0, jsonAdapters.size)
return try { return try {

View File

@@ -39,7 +39,6 @@ import java.lang.reflect.Type
* *
* Fields from platform classes are omitted from both serialization and deserialization unless they * Fields from platform classes are omitted from both serialization and deserialization unless they
* are either public or protected. This includes the following packages and their subpackages: * are either public or protected. This includes the following packages and their subpackages:
*
* * `android.*` * * `android.*`
* * `androidx.*` * * `androidx.*`
* * `java.*` * * `java.*`
@@ -47,7 +46,6 @@ import java.lang.reflect.Type
* * `kotlin.*` * * `kotlin.*`
* * `kotlinx.*` * * `kotlinx.*`
* * `scala.*` * * `scala.*`
*
*/ */
internal class ClassJsonAdapter<T>( internal class ClassJsonAdapter<T>(
private val classFactory: ClassFactory<T>, private val classFactory: ClassFactory<T>,
@@ -103,12 +101,12 @@ internal class ClassJsonAdapter<T>(
internal class FieldBinding<T>(val name: String, val field: Field, val adapter: JsonAdapter<T>) { internal class FieldBinding<T>(val name: String, val field: Field, val adapter: JsonAdapter<T>) {
fun read(reader: JsonReader, value: Any?) { fun read(reader: JsonReader, value: Any?) {
val fieldValue = adapter.fromJson(reader) val fieldValue = adapter.fromJson(reader)
field[value] = fieldValue field.set(value, fieldValue)
} }
@Suppress("UNCHECKED_CAST") // We require that field's values are of type T. @Suppress("UNCHECKED_CAST") // We require that field's values are of type T.
fun write(writer: JsonWriter, value: Any?) { fun write(writer: JsonWriter, value: Any?) {
val fieldValue = field[value] as T val fieldValue = field.get(value) as T
adapter.toJson(writer, fieldValue) adapter.toJson(writer, fieldValue)
} }
} }
@@ -145,19 +143,24 @@ internal class ClassJsonAdapter<T>(
require(!rawType.isAnonymousClass) { require(!rawType.isAnonymousClass) {
"Cannot serialize anonymous class ${rawType.name}" "Cannot serialize anonymous class ${rawType.name}"
} }
require(!rawType.isLocalClass) { require(!rawType.isLocalClass) {
"Cannot serialize local class ${rawType.name}" "Cannot serialize local class ${rawType.name}"
} }
val isNonStaticNestedClass = rawType.enclosingClass != null && !isStatic(rawType.modifiers) val isNonStaticNestedClass = rawType.enclosingClass != null && !isStatic(rawType.modifiers)
require(!isNonStaticNestedClass) { require(!isNonStaticNestedClass) {
"Cannot serialize non-static nested class ${rawType.name}" "Cannot serialize non-static nested class ${rawType.name}"
} }
require(!isAbstract(rawType.modifiers)) { require(!isAbstract(rawType.modifiers)) {
"Cannot serialize abstract class ${rawType.name}" "Cannot serialize abstract class ${rawType.name}"
} }
require(!rawType.isKotlin) { require(!rawType.isKotlin) {
"Cannot serialize Kotlin type ${rawType.name}. Reflective serialization of Kotlin classes without using kotlin-reflect has undefined and unexpected behavior. Please use KotlinJsonAdapterFactory from the moshi-kotlin artifact or use code gen from the moshi-kotlin-codegen artifact." "Cannot serialize Kotlin type ${rawType.name}. Reflective serialization of Kotlin classes without using kotlin-reflect has undefined and unexpected behavior. Please use KotlinJsonAdapterFactory from the moshi-kotlin artifact or use code gen from the moshi-kotlin-codegen artifact."
} }
val classFactory = ClassFactory.get<Any>(rawType) val classFactory = ClassFactory.get<Any>(rawType)
val fields = sortedMapOf<String, FieldBinding<*>>() val fields = sortedMapOf<String, FieldBinding<*>>()
var parentType = type var parentType = type
@@ -216,8 +219,11 @@ internal class ClassJsonAdapter<T>(
/** Returns true if fields with `modifiers` are included in the emitted JSON. */ /** Returns true if fields with `modifiers` are included in the emitted JSON. */
private fun includeField(platformType: Boolean, modifiers: Int): Boolean { private fun includeField(platformType: Boolean, modifiers: Int): Boolean {
if (isStatic(modifiers) || isTransient(modifiers)) return false return if (isStatic(modifiers) || isTransient(modifiers)) {
return isPublic(modifiers) || isProtected(modifiers) || !platformType false
} else {
isPublic(modifiers) || isProtected(modifiers) || !platformType
}
} }
} }
} }

View File

@@ -213,7 +213,7 @@ public class Moshi internal constructor(builder: Builder) {
} }
public fun add(adapter: Any): Builder = apply { public fun add(adapter: Any): Builder = apply {
add(AdapterMethodsFactory.get(adapter)) add(AdapterMethodsFactory(adapter))
} }
@Suppress("unused") @Suppress("unused")
@@ -236,7 +236,7 @@ public class Moshi internal constructor(builder: Builder) {
@Suppress("unused") @Suppress("unused")
public fun addLast(adapter: Any): Builder = apply { public fun addLast(adapter: Any): Builder = apply {
addLast(AdapterMethodsFactory.get(adapter)) addLast(AdapterMethodsFactory(adapter))
} }
@CheckReturnValue @CheckReturnValue

View File

@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
@file:Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN")
package com.squareup.moshi package com.squareup.moshi
import com.squareup.moshi.internal.EMPTY_TYPE_ARRAY import com.squareup.moshi.internal.EMPTY_TYPE_ARRAY
@@ -30,6 +31,7 @@ import java.lang.reflect.WildcardType
import java.util.Collections import java.util.Collections
import java.util.Properties import java.util.Properties
import javax.annotation.CheckReturnValue import javax.annotation.CheckReturnValue
import java.lang.annotation.Annotation as JavaAnnotation
/** Factory methods for types. */ /** Factory methods for types. */
@CheckReturnValue @CheckReturnValue
@@ -62,7 +64,7 @@ public object Types {
*/ */
@JvmStatic @JvmStatic
public fun generatedJsonAdapterName(className: String): String { public fun generatedJsonAdapterName(className: String): String {
return className.replace("$", "_") + "JsonAdapter" return "${className.replace("$", "_")}JsonAdapter"
} }
/** /**
@@ -81,8 +83,7 @@ public object Types {
return null return null
} }
for (annotation in annotations) { for (annotation in annotations) {
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") if ((jsonQualifier == (annotation as JavaAnnotation).annotationType())) {
if ((jsonQualifier == (annotation as java.lang.annotation.Annotation).annotationType())) {
val delegateAnnotations = LinkedHashSet(annotations) val delegateAnnotations = LinkedHashSet(annotations)
delegateAnnotations.remove(annotation) delegateAnnotations.remove(annotation)
return Collections.unmodifiableSet(delegateAnnotations) return Collections.unmodifiableSet(delegateAnnotations)
@@ -178,7 +179,7 @@ public object Types {
} }
is WildcardType -> getRawType(type.upperBounds[0]) is WildcardType -> getRawType(type.upperBounds[0])
else -> { else -> {
val className = if (type == null) "null" else type.javaClass.name val className = type?.javaClass?.name?.toString()
throw IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <$type> is of type $className") throw IllegalArgumentException("Expected a Class, ParameterizedType, or GenericArrayType, but <$type> is of type $className")
} }
} }
@@ -259,19 +260,18 @@ public object Types {
val field = clazz.getDeclaredField(fieldName) val field = clazz.getDeclaredField(fieldName)
field.isAccessible = true field.isAccessible = true
val fieldAnnotations = field.declaredAnnotations val fieldAnnotations = field.declaredAnnotations
val annotations: MutableSet<Annotation> = LinkedHashSet(fieldAnnotations.size) return buildSet(fieldAnnotations.size) {
for (annotation in fieldAnnotations) { for (annotation in fieldAnnotations) {
@Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") val hasJsonQualifier = (annotation as JavaAnnotation).annotationType()
if ((annotation as java.lang.annotation.Annotation).annotationType()
.isAnnotationPresent(JsonQualifier::class.java) .isAnnotationPresent(JsonQualifier::class.java)
) { if (hasJsonQualifier) {
annotations.add(annotation) add(annotation)
}
} }
} }
return Collections.unmodifiableSet(annotations)
} catch (e: NoSuchFieldException) { } catch (e: NoSuchFieldException) {
throw IllegalArgumentException( throw IllegalArgumentException(
"Could not access field " + fieldName + " on class " + clazz.canonicalName, e "Could not access field $fieldName on class ${clazz.canonicalName}", e
) )
} }
} }
@@ -298,7 +298,7 @@ public object Types {
annotationType.isInstance(o) annotationType.isInstance(o)
} }
"hashCode" -> 0 "hashCode" -> 0
"toString" -> "@" + annotationType.name + "()" "toString" -> "@${annotationType.name}()"
else -> method.invoke(proxy, *args) else -> method.invoke(proxy, *args)
} }
} as T } as T