Allow custom generators (#847)

* Extract generatedJsonAdapterName to public API for other generators/consumers

* Fix kapt location in tests

* Add IDE-generated dependency-reduced-pom.xml to gitignore

This always bites me

* Add generator property to JsonClass and skip in processor

* Opportunistically fix formatting for generateAdapter doc

* Extract NullSafeJsonAdapter for delegate testing

* Add custom adapter tests

* Allow no-moshi constructors for generated adapters

* Fix rebase issue

* Use something other than nullSafe() for lenient check

This no longer propagates lenient

* Add missing copyrights

* Add top-level class note

* Add note about working against Moshi's generated signature

* Add missing bit to "requirements for"

* Note kotlin requirement relaxed in custom generators

* Style
This commit is contained in:
Zac Sweers
2019-05-15 20:42:08 -04:00
committed by Jesse Wilson
parent a5020ddb3c
commit 0943ef5a61
11 changed files with 283 additions and 72 deletions

View File

@@ -85,7 +85,7 @@ class JsonClassCodegenProcessor : KotlinAbstractProcessor(), KotlinMetadataUtils
override fun process(annotations: Set<TypeElement>, roundEnv: RoundEnvironment): Boolean {
for (type in roundEnv.getElementsAnnotatedWith(annotation)) {
val jsonClass = type.getAnnotation(annotation)
if (jsonClass.generateAdapter) {
if (jsonClass.generateAdapter && jsonClass.generator.isEmpty()) {
val generator = adapterGenerator(type) ?: continue
generator.generateFile(generatedType)
.writeTo(filer)

View File

@@ -26,6 +26,7 @@ import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.ToJson
import com.squareup.moshi.Types
import com.squareup.moshi.internal.NullSafeJsonAdapter
import org.assertj.core.api.Assertions.assertThat
import org.intellij.lang.annotations.Language
import org.junit.Assert.assertNull
@@ -1155,37 +1156,70 @@ class GeneratedAdaptersTest {
assertThat(decoded).isEqualTo(HasCollectionOfPrimitives(listOf(4, -5, 6)))
}
/**
* This is here mostly just to ensure it still compiles. Covers variance, @Json, default values,
* nullability, primitive arrays, and some wacky generics.
*/
@JsonClass(generateAdapter = true)
data class SmokeTestType(
@Json(name = "first_name") val firstName: String,
@Json(name = "last_name") val lastName: String,
val age: Int,
val nationalities: List<String> = emptyList(),
val weight: Float,
val tattoos: Boolean = false,
val race: String?,
val hasChildren: Boolean = false,
val favoriteFood: String? = null,
val favoriteDrink: String? = "Water",
val wildcardOut: MutableList<out String> = mutableListOf(),
val nullableWildcardOut: MutableList<out String?> = mutableListOf(),
val wildcardIn: Array<in String>,
val any: List<*>,
val anyTwo: List<Any>,
val anyOut: MutableList<out Any>,
val nullableAnyOut: MutableList<out Any?>,
val favoriteThreeNumbers: IntArray,
val favoriteArrayValues: Array<String>,
val favoriteNullableArrayValues: Array<String?>,
val nullableSetListMapArrayNullableIntWithDefault: Set<List<Map<String, Array<IntArray?>>>>? = null,
val aliasedName: TypeAliasName = "Woah",
val genericAlias: GenericTypeAlias = listOf("Woah")
)
@JsonClass(generateAdapter = true, generator = "custom")
data class CustomGeneratedClass(val foo: String)
@Test fun customGenerator_withClassPresent() {
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(CustomGeneratedClass::class.java)
val unwrapped = (adapter as NullSafeJsonAdapter<CustomGeneratedClass>).delegate()
assertThat(unwrapped).isInstanceOf(GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter::class.java)
}
@JsonClass(generateAdapter = true, generator = "custom")
data class CustomGeneratedClassMissing(val foo: String)
@Test fun customGenerator_withClassMissing() {
val moshi = Moshi.Builder().build()
try {
moshi.adapter(CustomGeneratedClassMissing::class.java)
fail()
} catch (e: RuntimeException) {
assertThat(e).hasMessageContaining("Failed to find the generated JsonAdapter class")
}
}
}
// Has to be outside to avoid Types seeing an owning class
@JsonClass(generateAdapter = true)
data class NullableTypeParams<T>(
val nullableList: List<String?>,
val nullableSet: Set<String?>,
val nullableMap: Map<String, String?>,
val nullableT: T?,
val nonNullT: T
)
/**
* This is here mostly just to ensure it still compiles. Covers variance, @Json, default values,
* nullability, primitive arrays, and some wacky generics.
*/
@JsonClass(generateAdapter = true)
data class SmokeTestType(
@Json(name = "first_name") val firstName: String,
@Json(name = "last_name") val lastName: String,
val age: Int,
val nationalities: List<String> = emptyList(),
val weight: Float,
val tattoos: Boolean = false,
val race: String?,
val hasChildren: Boolean = false,
val favoriteFood: String? = null,
val favoriteDrink: String? = "Water",
val wildcardOut: MutableList<out String> = mutableListOf(),
val nullableWildcardOut: MutableList<out String?> = mutableListOf(),
val wildcardIn: Array<in String>,
val any: List<*>,
val anyTwo: List<Any>,
val anyOut: MutableList<out Any>,
val nullableAnyOut: MutableList<out Any?>,
val favoriteThreeNumbers: IntArray,
val favoriteArrayValues: Array<String>,
val favoriteNullableArrayValues: Array<String?>,
val nullableSetListMapArrayNullableIntWithDefault: Set<List<Map<String, Array<IntArray?>>>>? = null,
val aliasedName: TypeAliasName = "Woah",
val genericAlias: GenericTypeAlias = listOf("Woah")
)
typealias TypeAliasName = String
typealias GenericTypeAlias = List<String>

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2019 Square, 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.kotlin.codgen
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.kotlin.codgen.GeneratedAdaptersTest.CustomGeneratedClass
// This also tests custom generated types with no moshi constructor
class GeneratedAdaptersTest_CustomGeneratedClassJsonAdapter : JsonAdapter<CustomGeneratedClass>() {
override fun fromJson(reader: JsonReader): CustomGeneratedClass? {
TODO()
}
override fun toJson(writer: JsonWriter, value: CustomGeneratedClass?) {
TODO()
}
}