From e76110b4b1c0008b4ac2c5061c26fc58d7355ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Br=C3=BCggemann?= Date: Fri, 21 Apr 2017 00:26:57 +0200 Subject: [PATCH] Fix Factory visibility (#282) * Fix Factory visibility * Remove redundant constructor keyword --- .../com/squareup/moshi/KotlinJsonAdapter.kt | 87 ++++++++++--------- .../squareup/moshi/KotlinJsonAdapterTest.kt | 46 +++++----- 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/kotlin/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt b/kotlin/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt index fe72818..f14faee 100644 --- a/kotlin/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt +++ b/kotlin/src/main/java/com/squareup/moshi/KotlinJsonAdapter.kt @@ -16,6 +16,7 @@ package com.squareup.moshi import java.lang.reflect.Modifier +import java.lang.reflect.Type import java.util.AbstractMap.SimpleEntry import kotlin.collections.Map.Entry import kotlin.reflect.KFunction @@ -42,7 +43,7 @@ private object ABSENT_VALUE * This class encodes Kotlin classes using their properties. It decodes them by first invoking the * constructor, and then by setting any additional properties that exist, if any. */ -internal class KotlinJsonAdapter private constructor( +internal class KotlinJsonAdapter( val constructor: KFunction, val bindings: List?>, val options: JsonReader.Options) : JsonAdapter() { @@ -148,60 +149,60 @@ internal class KotlinJsonAdapter private constructor( return if (value !== ABSENT_VALUE) value else null } } +} - companion object { - @JvmField val FACTORY = Factory { type, annotations, moshi -> - if (!annotations.isEmpty()) return@Factory null +object KotlinJsonAdapterFactory : JsonAdapter.Factory { + override fun create(type: Type?, annotations: MutableSet, moshi: Moshi): JsonAdapter<*>? { + if (!annotations.isEmpty()) return null - val rawType = Types.getRawType(type) - val platformType = ClassJsonAdapter.isPlatformType(rawType) - if (platformType) return@Factory null + val rawType = Types.getRawType(type) + val platformType = ClassJsonAdapter.isPlatformType(rawType) + if (platformType) return null - if (!rawType.isAnnotationPresent(KOTLIN_METADATA)) return@Factory null + if (!rawType.isAnnotationPresent(KOTLIN_METADATA)) return null - val constructor = rawType.kotlin.primaryConstructor ?: return@Factory null - val parametersByName = constructor.parameters.associateBy { it.name } - constructor.isAccessible = true + val constructor = rawType.kotlin.primaryConstructor ?: return null + val parametersByName = constructor.parameters.associateBy { it.name } + constructor.isAccessible = true - val bindingsByName = LinkedHashMap>() + val bindingsByName = LinkedHashMap>() - for (property in rawType.kotlin.memberProperties) { - if (Modifier.isTransient(property.javaField?.modifiers ?: 0)) continue + for (property in rawType.kotlin.memberProperties) { + if (Modifier.isTransient(property.javaField?.modifiers ?: 0)) continue - property.isAccessible = true - var allAnnotations = property.annotations - var jsonAnnotation = property.findAnnotation() + property.isAccessible = true + var allAnnotations = property.annotations + var jsonAnnotation = property.findAnnotation() - val parameter = parametersByName[property.name] - if (parameter != null) { - allAnnotations += parameter.annotations - if (jsonAnnotation == null) { - jsonAnnotation = parameter.findAnnotation() - } + val parameter = parametersByName[property.name] + if (parameter != null) { + allAnnotations += parameter.annotations + if (jsonAnnotation == null) { + jsonAnnotation = parameter.findAnnotation() } - - val name = jsonAnnotation?.name ?: property.name - val adapter = moshi.adapter( - property.returnType.javaType, Util.jsonAnnotations(allAnnotations.toTypedArray())) - - bindingsByName[property.name] = - Binding(name, adapter, property as KProperty1, parameter) } - val bindings = ArrayList?>() + val name = jsonAnnotation?.name ?: property.name + val adapter = moshi.adapter( + property.returnType.javaType, Util.jsonAnnotations(allAnnotations.toTypedArray())) - for (parameter in constructor.parameters) { - val binding = bindingsByName.remove(parameter.name) - if (binding == null && !parameter.isOptional) { - throw IllegalArgumentException("No property for required constructor ${parameter}") - } - bindings += binding - } - - bindings += bindingsByName.values - - val options = JsonReader.Options.of(*bindings.map { it?.name ?: "\u0000" }.toTypedArray()) - KotlinJsonAdapter(constructor, bindings, options) + bindingsByName[property.name] = + KotlinJsonAdapter.Binding(name, adapter, property as KProperty1, parameter) } + + val bindings = ArrayList?>() + + for (parameter in constructor.parameters) { + val binding = bindingsByName.remove(parameter.name) + if (binding == null && !parameter.isOptional) { + throw IllegalArgumentException("No property for required constructor ${parameter}") + } + bindings += binding + } + + bindings += bindingsByName.values + + val options = JsonReader.Options.of(*bindings.map { it?.name ?: "\u0000" }.toTypedArray()) + return KotlinJsonAdapter(constructor, bindings, options) } } diff --git a/kotlin/src/test/java/com/squareup/moshi/KotlinJsonAdapterTest.kt b/kotlin/src/test/java/com/squareup/moshi/KotlinJsonAdapterTest.kt index 781fb10..da9e565 100644 --- a/kotlin/src/test/java/com/squareup/moshi/KotlinJsonAdapterTest.kt +++ b/kotlin/src/test/java/com/squareup/moshi/KotlinJsonAdapterTest.kt @@ -25,7 +25,7 @@ import kotlin.annotation.AnnotationRetention.RUNTIME class KotlinJsonAdapterTest { @Test fun constructorParameters() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ConstructorParameters::class.java) val encoded = ConstructorParameters(3, 5) @@ -39,7 +39,7 @@ class KotlinJsonAdapterTest { class ConstructorParameters(var a: Int, var b: Int) @Test fun properties() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(Properties::class.java) val encoded = Properties() @@ -58,7 +58,7 @@ class KotlinJsonAdapterTest { } @Test fun constructorParametersAndProperties() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ConstructorParametersAndProperties::class.java) val encoded = ConstructorParametersAndProperties(3) @@ -75,7 +75,7 @@ class KotlinJsonAdapterTest { } @Test fun immutableConstructorParameters() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ImmutableConstructorParameters::class.java) val encoded = ImmutableConstructorParameters(3, 5) @@ -89,7 +89,7 @@ class KotlinJsonAdapterTest { class ImmutableConstructorParameters(val a: Int, val b: Int) @Test fun immutableProperties() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ImmutableProperties::class.java) val encoded = ImmutableProperties(3, 5) @@ -106,7 +106,7 @@ class KotlinJsonAdapterTest { } @Test fun constructorDefaults() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ConstructorDefaultValues::class.java) val encoded = ConstructorDefaultValues(3, 5) @@ -120,7 +120,7 @@ class KotlinJsonAdapterTest { class ConstructorDefaultValues(var a: Int = -1, var b: Int = -2) @Test fun requiredValueAbsent() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(RequiredValueAbsent::class.java) try { @@ -134,7 +134,7 @@ class KotlinJsonAdapterTest { class RequiredValueAbsent(var a: Int = 3, var b: Int) @Test fun duplicatedValue() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(DuplicateValue::class.java) try { @@ -148,7 +148,7 @@ class KotlinJsonAdapterTest { class DuplicateValue(var a: Int = -1, var b: Int = -2) @Test fun explicitNull() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ExplicitNull::class.java) val encoded = ExplicitNull(null, 5) @@ -163,7 +163,7 @@ class KotlinJsonAdapterTest { class ExplicitNull(var a: Int?, var b: Int?) @Test fun absentNull() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(AbsentNull::class.java) val encoded = AbsentNull(null, 5) @@ -193,7 +193,7 @@ class KotlinJsonAdapterTest { @Test fun constructorParameterWithQualifier() { val moshi = Moshi.Builder() - .add(KotlinJsonAdapter.FACTORY) + .add(KotlinJsonAdapterFactory) .add(UppercaseJsonAdapter()) .build() val jsonAdapter = moshi.adapter(ConstructorParameterWithQualifier::class.java) @@ -210,7 +210,7 @@ class KotlinJsonAdapterTest { @Test fun propertyWithQualifier() { val moshi = Moshi.Builder() - .add(KotlinJsonAdapter.FACTORY) + .add(KotlinJsonAdapterFactory) .add(UppercaseJsonAdapter()) .build() val jsonAdapter = moshi.adapter(PropertyWithQualifier::class.java) @@ -231,7 +231,7 @@ class KotlinJsonAdapterTest { } @Test fun constructorParameterWithJsonName() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ConstructorParameterWithJsonName::class.java) val encoded = ConstructorParameterWithJsonName(3, 5) @@ -245,7 +245,7 @@ class KotlinJsonAdapterTest { class ConstructorParameterWithJsonName(@Json(name = "key a") var a: Int, var b: Int) @Test fun propertyWithJsonName() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(PropertyWithJsonName::class.java) val encoded = PropertyWithJsonName() @@ -264,7 +264,7 @@ class KotlinJsonAdapterTest { } @Test fun transientConstructorParameter() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(TransientConstructorParameter::class.java) val encoded = TransientConstructorParameter(3, 5) @@ -278,7 +278,7 @@ class KotlinJsonAdapterTest { class TransientConstructorParameter(@Transient var a: Int = -1, var b: Int = -1) @Test fun transientProperty() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(TransientProperty::class.java) val encoded = TransientProperty() @@ -297,7 +297,7 @@ class KotlinJsonAdapterTest { } @Test fun supertypeConstructorParameters() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(SubtypeConstructorParameters::class.java) val encoded = SubtypeConstructorParameters(3, 5) @@ -313,7 +313,7 @@ class KotlinJsonAdapterTest { class SubtypeConstructorParameters(a: Int, var b: Int) : SupertypeConstructorParameters(a) @Test fun supertypeProperties() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(SubtypeProperties::class.java) val encoded = SubtypeProperties() @@ -335,7 +335,7 @@ class KotlinJsonAdapterTest { } @Test fun extendsPlatformClassWithPrivateField() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ExtendsPlatformClassWithPrivateField::class.java) val encoded = ExtendsPlatformClassWithPrivateField(3) @@ -349,7 +349,7 @@ class KotlinJsonAdapterTest { internal class ExtendsPlatformClassWithPrivateField(var a: Int) : SimpleTimeZone(0, "C") @Test fun extendsPlatformClassWithProtectedField() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(ExtendsPlatformClassWithProtectedField::class.java) val encoded = ExtendsPlatformClassWithProtectedField(3) @@ -367,7 +367,7 @@ class KotlinJsonAdapterTest { } @Test fun platformTypeThrows() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() try { moshi.adapter(Triple::class.java) fail() @@ -378,7 +378,7 @@ class KotlinJsonAdapterTest { } @Test fun privateConstructorParameters() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(PrivateConstructorParameters::class.java) val encoded = PrivateConstructorParameters(3, 5) @@ -415,7 +415,7 @@ class KotlinJsonAdapterTest { } @Test fun privateProperties() { - val moshi = Moshi.Builder().add(KotlinJsonAdapter.FACTORY).build() + val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory).build() val jsonAdapter = moshi.adapter(PrivateProperties::class.java) val encoded = PrivateProperties()