mirror of
https://github.com/fankes/moshi.git
synced 2025-10-18 23:49:21 +08:00
Fix reading property function types (#1311)
This commit is contained in:
@@ -17,6 +17,7 @@ package com.squareup.moshi.kotlin.codegen.api
|
||||
|
||||
import com.squareup.kotlinpoet.ARRAY
|
||||
import com.squareup.kotlinpoet.AnnotationSpec
|
||||
import com.squareup.kotlinpoet.AnnotationSpec.UseSiteTarget.FILE
|
||||
import com.squareup.kotlinpoet.CodeBlock
|
||||
import com.squareup.kotlinpoet.FileSpec
|
||||
import com.squareup.kotlinpoet.FunSpec
|
||||
@@ -82,9 +83,12 @@ internal class AdapterGenerator(
|
||||
// like for stylistic reasons.
|
||||
"LocalVariableName",
|
||||
// KotlinPoet always generates explicit public modifiers for public members.
|
||||
"RedundantVisibilityModifier"
|
||||
"RedundantVisibilityModifier",
|
||||
// For LambdaTypeNames we have to import kotlin.functions.* types
|
||||
"PLATFORM_CLASS_MAPPED_TO_KOTLIN"
|
||||
).let { suppressions ->
|
||||
AnnotationSpec.builder(Suppress::class)
|
||||
.useSiteTarget(FILE)
|
||||
.addMember(
|
||||
suppressions.indices.joinToString { "%S" },
|
||||
*suppressions
|
||||
@@ -175,6 +179,7 @@ internal class AdapterGenerator(
|
||||
val generatedAdapter = generateType().let(typeHook)
|
||||
val result = FileSpec.builder(className.packageName, adapterName)
|
||||
result.addComment("Code generated by moshi-kotlin-codegen. Do not edit.")
|
||||
result.addAnnotation(COMMON_SUPPRESS)
|
||||
result.addType(generatedAdapter)
|
||||
return PreparedAdapter(result.build(), generatedAdapter.createProguardRule())
|
||||
}
|
||||
@@ -224,7 +229,6 @@ internal class AdapterGenerator(
|
||||
|
||||
private fun generateType(): TypeSpec {
|
||||
val result = TypeSpec.classBuilder(adapterName)
|
||||
.addAnnotation(COMMON_SUPPRESS)
|
||||
|
||||
result.superclass(jsonAdapterTypeName)
|
||||
|
||||
|
@@ -27,6 +27,7 @@ import com.squareup.kotlinpoet.FLOAT
|
||||
import com.squareup.kotlinpoet.INT
|
||||
import com.squareup.kotlinpoet.KModifier
|
||||
import com.squareup.kotlinpoet.LONG
|
||||
import com.squareup.kotlinpoet.LambdaTypeName
|
||||
import com.squareup.kotlinpoet.NOTHING
|
||||
import com.squareup.kotlinpoet.ParameterizedTypeName
|
||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||
@@ -48,6 +49,18 @@ internal fun TypeName.findRawType(): ClassName? {
|
||||
return when (this) {
|
||||
is ClassName -> this
|
||||
is ParameterizedTypeName -> rawType
|
||||
is LambdaTypeName -> {
|
||||
var count = parameters.size
|
||||
if (receiver != null) {
|
||||
count++
|
||||
}
|
||||
val functionSimpleName = if (count >= 23) {
|
||||
"FunctionN"
|
||||
} else {
|
||||
"Function$count"
|
||||
}
|
||||
ClassName("kotlin.jvm.functions", functionSimpleName)
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -93,6 +106,7 @@ internal fun TypeName.asTypeBlock(): CodeBlock {
|
||||
val bound = bounds.firstOrNull() ?: ANY
|
||||
return bound.asTypeBlock()
|
||||
}
|
||||
is LambdaTypeName -> return rawType().asTypeBlock()
|
||||
is ClassName -> {
|
||||
// Check against the non-nullable version for equality, but we'll keep the nullability in
|
||||
// consideration when creating the CodeBlock if needed.
|
||||
@@ -164,6 +178,14 @@ internal fun WildcardTypeName.deepCopy(transform: (TypeName) -> TypeName): TypeN
|
||||
}
|
||||
}
|
||||
|
||||
internal fun LambdaTypeName.deepCopy(transform: (TypeName) -> TypeName): TypeName {
|
||||
return LambdaTypeName.get(
|
||||
receiver?.let(transform),
|
||||
parameters.map { it.toBuilder(type = transform(it.type)).build() },
|
||||
transform(returnType)
|
||||
).copy(nullable = isNullable, annotations = annotations, suspending = isSuspending)
|
||||
}
|
||||
|
||||
internal interface TypeVariableResolver {
|
||||
val parametersMap: Map<String, TypeVariableName>
|
||||
operator fun get(index: String): TypeVariableName
|
||||
|
@@ -18,6 +18,7 @@ package com.squareup.moshi.kotlin.codegen
|
||||
import com.squareup.kotlinpoet.AnnotationSpec
|
||||
import com.squareup.kotlinpoet.ClassName
|
||||
import com.squareup.kotlinpoet.KModifier
|
||||
import com.squareup.kotlinpoet.LambdaTypeName
|
||||
import com.squareup.kotlinpoet.ParameterizedTypeName
|
||||
import com.squareup.kotlinpoet.TypeName
|
||||
import com.squareup.kotlinpoet.TypeSpec
|
||||
@@ -530,6 +531,7 @@ internal fun TypeName.unwrapTypeAlias(): TypeName {
|
||||
is ParameterizedTypeName -> deepCopy(TypeName::unwrapTypeAlias)
|
||||
is TypeVariableName -> deepCopy(transform = TypeName::unwrapTypeAlias)
|
||||
is WildcardTypeName -> deepCopy(TypeName::unwrapTypeAlias)
|
||||
is LambdaTypeName -> deepCopy(TypeName::unwrapTypeAlias)
|
||||
else -> throw UnsupportedOperationException("Type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, wildcard types, or type variables are allowed.")
|
||||
}
|
||||
}
|
||||
|
@@ -1379,6 +1379,26 @@ class GeneratedAdaptersTest {
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class MultipleGenerics<A, B, C, D>(val prop: String)
|
||||
|
||||
@Test fun functionPropertyTypes() {
|
||||
val adapter = moshi.adapter<LambdaTypeNames>()
|
||||
val json = "{\"id\":\"value\"}"
|
||||
assertThat(adapter.fromJson(json)).isEqualTo(LambdaTypeNames("value"))
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/square/moshi/issues/1265
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class LambdaTypeNames(
|
||||
val id: String,
|
||||
@Transient
|
||||
val simple: ((String) -> Boolean)? = null,
|
||||
// Receivers count as the first param, just annotated with a special annotation to indicate it's a receiver
|
||||
@Transient
|
||||
val receiver: (String.(String) -> Boolean)? = null,
|
||||
// Tests that we use `FunctionN` since it has more than 23 params
|
||||
@Transient
|
||||
val arity: (String.(String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String, String) -> Boolean)? = null,
|
||||
)
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/square/moshi/issues/1277
|
||||
|
Reference in New Issue
Block a user