Disallow irregular Kotlin classes. (#424)

This commit is contained in:
Eric Cochran 2018-01-10 19:07:13 -08:00 committed by Jesse Wilson
parent 9deeb62e77
commit 5b194964a9
2 changed files with 105 additions and 6 deletions

View file

@ -162,17 +162,32 @@ class KotlinJsonAdapterFactory : JsonAdapter.Factory {
if (!annotations.isEmpty()) return null
val rawType = Types.getRawType(type)
if (rawType.isInterface) return null
if (rawType.isEnum) return null
if (!rawType.isAnnotationPresent(KOTLIN_METADATA)) return null
if (ClassJsonAdapter.isPlatformType(rawType)) return null
val constructor = rawType.kotlin.primaryConstructor ?: return null
if (rawType.isLocalClass) {
throw IllegalArgumentException("Cannot serialize local class or object expression ${rawType.name}")
}
val rawTypeKotlin = rawType.kotlin
if (rawTypeKotlin.isAbstract) {
throw IllegalArgumentException("Cannot serialize abstract class ${rawType.name}")
}
if (rawTypeKotlin.isInner) {
throw IllegalArgumentException("Cannot serialize inner class ${rawType.name}")
}
if (rawTypeKotlin.objectInstance != null) {
throw IllegalArgumentException("Cannot serialize object declaration ${rawType.name}")
}
val constructor = rawTypeKotlin.primaryConstructor ?: return null
val parametersByName = constructor.parameters.associateBy { it.name }
constructor.isAccessible = true
val bindingsByName = LinkedHashMap<String, KotlinJsonAdapter.Binding<Any, Any?>>()
for (property in rawType.kotlin.memberProperties) {
for (property in rawTypeKotlin.memberProperties) {
val parameter = parametersByName[property.name]
if (Modifier.isTransient(property.javaField?.modifiers ?: 0)) {

View file

@ -134,9 +134,8 @@ class KotlinJsonAdapterTest {
class RequiredValueAbsent(var a: Int = 3, var b: Int)
@Test fun nonNullConstructorParameterCalledWithNullFailsWithJsonDataException() {
class Data(val a: String)
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter(Data::class.java)
val jsonAdapter = moshi.adapter(HasNonNullConstructorParameter::class.java)
try {
jsonAdapter.fromJson("{\"a\":null}")
@ -146,10 +145,11 @@ class KotlinJsonAdapterTest {
}
}
class HasNonNullConstructorParameter(val a: String)
@Test fun nonNullPropertySetToNullFailsWithJsonDataException() {
class Data { var a: String = "" }
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter(Data::class.java)
val jsonAdapter = moshi.adapter(HasNonNullProperty::class.java)
try {
jsonAdapter.fromJson("{\"a\":null}")
@ -159,6 +159,10 @@ class KotlinJsonAdapterTest {
}
}
class HasNonNullProperty {
var a: String = ""
}
@Test fun duplicatedValue() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter(DuplicateValue::class.java)
@ -576,6 +580,86 @@ class KotlinJsonAdapterTest {
A, B
}
@Test fun interfacesNotSupported() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
try {
moshi.adapter(Interface::class.java)
fail()
} catch (e: IllegalArgumentException) {
assertThat(e).hasMessage("No JsonAdapter for interface " +
"com.squareup.moshi.KotlinJsonAdapterTest\$Interface annotated []")
}
}
interface Interface
@Test fun abstractClassesNotSupported() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
try {
moshi.adapter(AbstractClass::class.java)
fail()
} catch (e: IllegalArgumentException) {
assertThat(e).hasMessage(
"Cannot serialize abstract class com.squareup.moshi.KotlinJsonAdapterTest\$AbstractClass")
}
}
abstract class AbstractClass(val a: Int)
@Test fun innerClassesNotSupported() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
try {
moshi.adapter(InnerClass::class.java)
fail()
} catch (e: IllegalArgumentException) {
assertThat(e).hasMessage(
"Cannot serialize inner class com.squareup.moshi.KotlinJsonAdapterTest\$InnerClass")
}
}
inner class InnerClass(val a: Int)
@Test fun localClassesNotSupported() {
class LocalClass(val a: Int)
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
try {
moshi.adapter(LocalClass::class.java)
fail()
} catch (e: IllegalArgumentException) {
assertThat(e).hasMessage("Cannot serialize local class or object expression " +
"com.squareup.moshi.KotlinJsonAdapterTest\$localClassesNotSupported\$LocalClass")
}
}
@Test fun objectDeclarationsNotSupported() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
try {
moshi.adapter(ObjectDeclaration.javaClass)
fail()
} catch (e: IllegalArgumentException) {
assertThat(e).hasMessage("Cannot serialize object declaration " +
"com.squareup.moshi.KotlinJsonAdapterTest\$ObjectDeclaration")
}
}
object ObjectDeclaration {
var a = 5
}
@Test fun objectExpressionsNotSupported() {
val expression = object : Any() {
var a = 5
}
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
try {
moshi.adapter(expression.javaClass)
fail()
} catch (e: IllegalArgumentException) {
assertThat(e).hasMessage("Cannot serialize local class or object expression " +
"com.squareup.moshi.KotlinJsonAdapterTest\$objectExpressionsNotSupported\$expression$1")
}
}
@Test fun manyProperties32() {
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
val jsonAdapter = moshi.adapter(ManyProperties32::class.java)