mirror of
https://github.com/fankes/moshi.git
synced 2025-10-19 16:09:21 +08:00
Fix handling of typealiases in non-classname envs + wildcard fix… (#987)
* Correctly render non-classname wildcard types Resolves #984 Resolves #985 * Add thorough typealias test * Expand unwrapTypeAlias to parameterized and wildcard types Resolves #983 * Disable Werror for now
This commit is contained in:
@@ -40,13 +40,19 @@ import com.squareup.moshi.Types
|
||||
abstract class TypeRenderer {
|
||||
abstract fun renderTypeVariable(typeVariable: TypeVariableName): CodeBlock
|
||||
|
||||
fun render(typeName: TypeName): CodeBlock {
|
||||
fun render(typeName: TypeName, forceBox: Boolean = false): CodeBlock {
|
||||
if (typeName.isNullable) {
|
||||
return renderObjectType(typeName.copy(nullable = false))
|
||||
}
|
||||
|
||||
return when (typeName) {
|
||||
is ClassName -> CodeBlock.of("%T::class.java", typeName)
|
||||
is ClassName -> {
|
||||
if (forceBox) {
|
||||
renderObjectType(typeName)
|
||||
} else {
|
||||
CodeBlock.of("%T::class.java", typeName)
|
||||
}
|
||||
}
|
||||
|
||||
is ParameterizedTypeName -> {
|
||||
// If it's an Array type, we shortcut this to return Types.arrayOf()
|
||||
@@ -88,7 +94,7 @@ abstract class TypeRenderer {
|
||||
else -> throw IllegalArgumentException(
|
||||
"Unrepresentable wildcard type. Cannot have more than one bound: $typeName")
|
||||
}
|
||||
CodeBlock.of("%T.%L(%T::class.java)", Types::class, method, target.copy(nullable = false))
|
||||
CodeBlock.of("%T.%L(%L)", Types::class, method, render(target, forceBox = true))
|
||||
}
|
||||
|
||||
is TypeVariableName -> renderTypeVariable(typeName)
|
||||
|
@@ -18,8 +18,13 @@ 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.ParameterizedTypeName
|
||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||
import com.squareup.kotlinpoet.STAR
|
||||
import com.squareup.kotlinpoet.TypeName
|
||||
import com.squareup.kotlinpoet.TypeSpec
|
||||
import com.squareup.kotlinpoet.TypeVariableName
|
||||
import com.squareup.kotlinpoet.WildcardTypeName
|
||||
import com.squareup.kotlinpoet.asClassName
|
||||
import com.squareup.kotlinpoet.asTypeName
|
||||
import com.squareup.kotlinpoet.classinspector.elements.ElementsClassInspector
|
||||
@@ -315,5 +320,33 @@ private fun String.escapeDollarSigns(): String {
|
||||
}
|
||||
|
||||
private fun TypeName.unwrapTypeAlias(): TypeName {
|
||||
return tag<TypeNameAliasTag>()?.type ?: this
|
||||
return when (this) {
|
||||
is ClassName -> {
|
||||
tag<TypeNameAliasTag>()?.type ?: this
|
||||
}
|
||||
is ParameterizedTypeName -> {
|
||||
return (rawType.unwrapTypeAlias() as ClassName).parameterizedBy(typeArguments.map { it.unwrapTypeAlias() })
|
||||
}
|
||||
is TypeVariableName -> {
|
||||
return copy(bounds = bounds.map { it.unwrapTypeAlias() })
|
||||
}
|
||||
is WildcardTypeName -> {
|
||||
// TODO Would be nice if KotlinPoet modeled these easier.
|
||||
// Producer type - empty inTypes, single element outTypes
|
||||
// Consumer type - single element inTypes, single ANY element outType.
|
||||
return when {
|
||||
this == STAR -> this
|
||||
outTypes.isNotEmpty() && inTypes.isEmpty() -> {
|
||||
WildcardTypeName.producerOf(outTypes[0].unwrapTypeAlias())
|
||||
.copy(nullable = isNullable, annotations = annotations)
|
||||
}
|
||||
inTypes.isNotEmpty() -> {
|
||||
WildcardTypeName.consumerOf(inTypes[0].unwrapTypeAlias())
|
||||
.copy(nullable = isNullable, annotations = annotations)
|
||||
}
|
||||
else -> throw UnsupportedOperationException("Not possible.")
|
||||
}
|
||||
}
|
||||
else -> throw UnsupportedOperationException("Type '${javaClass.simpleName}' is illegal. Only classes, parameterized types, wildcard types, or type variables are allowed.")
|
||||
}
|
||||
}
|
||||
|
@@ -115,7 +115,11 @@
|
||||
</executions>
|
||||
<configuration>
|
||||
<args>
|
||||
<arg>-Werror</arg>
|
||||
<!--
|
||||
Disabled for now because we generate redundant `out` variance for some generics,
|
||||
but there's no way for us to know when it's redundant.
|
||||
-->
|
||||
<!-- <arg>-Werror</arg>-->
|
||||
<arg>-Xuse-experimental=kotlin.ExperimentalStdlibApi</arg>
|
||||
<arg>-XXLanguage:+InlineClasses</arg>
|
||||
</args>
|
||||
|
@@ -403,8 +403,46 @@ class DualKotlinTest(useReflection: Boolean) {
|
||||
|
||||
var prop: Int = 0
|
||||
}
|
||||
|
||||
@Test fun typeAliasUnwrapping() {
|
||||
val adapter = moshi
|
||||
.newBuilder()
|
||||
.add(Types.supertypeOf(Int::class.javaObjectType), moshi.adapter<Int>())
|
||||
.build()
|
||||
.adapter<TypeAliasUnwrapping>()
|
||||
|
||||
@Language("JSON")
|
||||
val testJson = """{"simpleClass":6,"parameterized":{"value":6},"wildcardIn":{"value":6},"wildcardOut":{"value":6},"complex":{"value":[{"value":6}]}}"""
|
||||
|
||||
val testValue = TypeAliasUnwrapping(
|
||||
simpleClass = 6,
|
||||
parameterized = TypeAliasGeneric(6),
|
||||
wildcardIn = TypeAliasGeneric(6),
|
||||
wildcardOut = TypeAliasGeneric(6),
|
||||
complex = TypeAliasGeneric(listOf(TypeAliasGeneric(6)))
|
||||
)
|
||||
assertThat(adapter.toJson(testValue)).isEqualTo(testJson)
|
||||
|
||||
val result = adapter.fromJson(testJson)!!
|
||||
assertThat(result).isEqualTo(testValue)
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class TypeAliasUnwrapping(
|
||||
val simpleClass: TypeAlias,
|
||||
val parameterized: TypeAliasGeneric<TypeAlias>,
|
||||
val wildcardIn: TypeAliasGeneric<in TypeAlias>,
|
||||
val wildcardOut: TypeAliasGeneric<out TypeAlias>,
|
||||
@Suppress("REDUNDANT_PROJECTION")
|
||||
val complex: TypeAliasGeneric<List<out TypeAliasGeneric<in TypeAlias>>>
|
||||
)
|
||||
}
|
||||
|
||||
typealias TypeAlias = Int
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
data class TypeAliasGeneric<T>(val value: T)
|
||||
|
||||
// Has to be outside since inline classes are only allowed on top level
|
||||
@JsonClass(generateAdapter = true)
|
||||
inline class InlineClass(val i: Int)
|
||||
|
Reference in New Issue
Block a user