Merge pull request #764 from square/jwilson.1128.kp10rc3
Upgrade to KotlinPoet 1.0-RC3
This commit is contained in:
commit
2e241bff6f
11 changed files with 66 additions and 63 deletions
|
@ -25,7 +25,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup</groupId>
|
<groupId>com.squareup</groupId>
|
||||||
<artifactId>kotlinpoet</artifactId>
|
<artifactId>kotlinpoet</artifactId>
|
||||||
<version>1.0.0-RC2</version>
|
<version>1.0.0-RC3</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.auto</groupId>
|
<groupId>com.google.auto</groupId>
|
||||||
|
|
|
@ -71,7 +71,7 @@ internal class AdapterGenerator(
|
||||||
.build()
|
.build()
|
||||||
private val valueParam = ParameterSpec.builder(
|
private val valueParam = ParameterSpec.builder(
|
||||||
nameAllocator.newName("value"),
|
nameAllocator.newName("value"),
|
||||||
originalTypeName.asNullable())
|
originalTypeName.copy(nullable = true))
|
||||||
.build()
|
.build()
|
||||||
private val jsonAdapterTypeName = JsonAdapter::class.asClassName().parameterizedBy(originalTypeName)
|
private val jsonAdapterTypeName = JsonAdapter::class.asClassName().parameterizedBy(originalTypeName)
|
||||||
|
|
||||||
|
@ -183,24 +183,24 @@ internal class AdapterGenerator(
|
||||||
result.beginControlFlow("%L -> ", index)
|
result.beginControlFlow("%L -> ", index)
|
||||||
if (property.delegateKey.nullable) {
|
if (property.delegateKey.nullable) {
|
||||||
result.addStatement("%N = %N.fromJson(%N)",
|
result.addStatement("%N = %N.fromJson(%N)",
|
||||||
property.localName, nameAllocator.get(property.delegateKey), readerParam)
|
property.localName, nameAllocator[property.delegateKey], readerParam)
|
||||||
} else {
|
} else {
|
||||||
result.addStatement("%N = %N.fromJson(%N)" +
|
result.addStatement("%N = %N.fromJson(%N) ?: throw·%T(%P)",
|
||||||
" ?: throw %T(\"Non-null value '%N' was null at \${%N.path}\")",
|
property.localName, nameAllocator[property.delegateKey], readerParam,
|
||||||
property.localName, nameAllocator.get(property.delegateKey), readerParam,
|
JsonDataException::class,
|
||||||
JsonDataException::class, property.localName, readerParam)
|
"Non-null value '${property.localName}' was null at \${${readerParam.name}.path}")
|
||||||
}
|
}
|
||||||
result.addStatement("%N = true", property.localIsPresentName)
|
result.addStatement("%N = true", property.localIsPresentName)
|
||||||
result.endControlFlow()
|
result.endControlFlow()
|
||||||
} else {
|
} else {
|
||||||
if (property.delegateKey.nullable) {
|
if (property.delegateKey.nullable) {
|
||||||
result.addStatement("%L -> %N = %N.fromJson(%N)",
|
result.addStatement("%L -> %N = %N.fromJson(%N)",
|
||||||
index, property.localName, nameAllocator.get(property.delegateKey), readerParam)
|
index, property.localName, nameAllocator[property.delegateKey], readerParam)
|
||||||
} else {
|
} else {
|
||||||
result.addStatement("%L -> %N = %N.fromJson(%N)" +
|
result.addStatement("%L -> %N = %N.fromJson(%N) ?: throw·%T(%P)",
|
||||||
" ?: throw %T(\"Non-null value '%N' was null at \${%N.path}\")",
|
index, property.localName, nameAllocator[property.delegateKey], readerParam,
|
||||||
index, property.localName, nameAllocator.get(property.delegateKey), readerParam,
|
JsonDataException::class,
|
||||||
JsonDataException::class, property.localName, readerParam)
|
"Non-null value '${property.localName}' was null at \${${readerParam.name}.path}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ internal class AdapterGenerator(
|
||||||
|
|
||||||
// Call the constructor providing only required parameters.
|
// Call the constructor providing only required parameters.
|
||||||
var hasOptionalParameters = false
|
var hasOptionalParameters = false
|
||||||
result.addCode("%[var %N = %T(", resultName, originalTypeName)
|
result.addCode("«var %N = %T(", resultName, originalTypeName)
|
||||||
var separator = "\n"
|
var separator = "\n"
|
||||||
for (property in propertyList) {
|
for (property in propertyList) {
|
||||||
if (!property.hasConstructorParameter) {
|
if (!property.hasConstructorParameter) {
|
||||||
|
@ -230,20 +230,20 @@ internal class AdapterGenerator(
|
||||||
result.addCode(separator)
|
result.addCode(separator)
|
||||||
result.addCode("%N = %N", property.name, property.localName)
|
result.addCode("%N = %N", property.name, property.localName)
|
||||||
if (property.isRequired) {
|
if (property.isRequired) {
|
||||||
result.addCode(" ?: throw %T(\"Required property '%L' missing at \${%N.path}\")",
|
result.addCode(" ?: throw·%T(%P)", JsonDataException::class,
|
||||||
JsonDataException::class, property.localName, readerParam)
|
"Required property '${property.localName}' missing at \${${readerParam.name}.path}")
|
||||||
}
|
}
|
||||||
separator = ",\n"
|
separator = ",\n"
|
||||||
}
|
}
|
||||||
result.addCode(")%]\n", originalTypeName)
|
result.addCode(")»\n", originalTypeName)
|
||||||
|
|
||||||
// Call either the constructor again, or the copy() method, this time providing any optional
|
// Call either the constructor again, or the copy() method, this time providing any optional
|
||||||
// parameters that we have.
|
// parameters that we have.
|
||||||
if (hasOptionalParameters) {
|
if (hasOptionalParameters) {
|
||||||
if (isDataClass) {
|
if (isDataClass) {
|
||||||
result.addCode("%[%1N = %1N.copy(", resultName)
|
result.addCode("«%1N = %1N.copy(", resultName)
|
||||||
} else {
|
} else {
|
||||||
result.addCode("%[%1N = %2T(", resultName, originalTypeName)
|
result.addCode("«%1N = %2T(", resultName, originalTypeName)
|
||||||
}
|
}
|
||||||
separator = "\n"
|
separator = "\n"
|
||||||
for (property in propertyList) {
|
for (property in propertyList) {
|
||||||
|
@ -255,17 +255,21 @@ internal class AdapterGenerator(
|
||||||
}
|
}
|
||||||
|
|
||||||
result.addCode(separator)
|
result.addCode(separator)
|
||||||
if (property.differentiateAbsentFromNull) {
|
when {
|
||||||
|
property.differentiateAbsentFromNull -> {
|
||||||
result.addCode("%2N = if (%3N) %4N else %1N.%2N",
|
result.addCode("%2N = if (%3N) %4N else %1N.%2N",
|
||||||
resultName, property.name, property.localIsPresentName, property.localName)
|
resultName, property.name, property.localIsPresentName, property.localName)
|
||||||
} else if (property.isRequired) {
|
}
|
||||||
|
property.isRequired -> {
|
||||||
result.addCode("%1N = %2N", property.name, property.localName)
|
result.addCode("%1N = %2N", property.name, property.localName)
|
||||||
} else {
|
}
|
||||||
|
else -> {
|
||||||
result.addCode("%2N = %3N ?: %1N.%2N", resultName, property.name, property.localName)
|
result.addCode("%2N = %3N ?: %1N.%2N", resultName, property.name, property.localName)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
separator = ",\n"
|
separator = ",\n"
|
||||||
}
|
}
|
||||||
result.addCode("%])\n")
|
result.addCode("»)\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign properties not present in the constructor.
|
// Assign properties not present in the constructor.
|
||||||
|
@ -301,7 +305,7 @@ internal class AdapterGenerator(
|
||||||
propertyList.forEach { property ->
|
propertyList.forEach { property ->
|
||||||
result.addStatement("%N.name(%S)", writerParam, property.jsonName)
|
result.addStatement("%N.name(%S)", writerParam, property.jsonName)
|
||||||
result.addStatement("%N.toJson(%N, %N.%L)",
|
result.addStatement("%N.toJson(%N, %N.%L)",
|
||||||
nameAllocator.get(property.delegateKey), writerParam, valueParam, property.name)
|
nameAllocator[property.delegateKey], writerParam, valueParam, property.name)
|
||||||
}
|
}
|
||||||
result.addStatement("%N.endObject()", writerParam)
|
result.addStatement("%N.endObject()", writerParam)
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ internal data class DelegateKey(
|
||||||
private val type: TypeName,
|
private val type: TypeName,
|
||||||
private val jsonQualifiers: List<AnnotationSpec>
|
private val jsonQualifiers: List<AnnotationSpec>
|
||||||
) {
|
) {
|
||||||
val nullable get() = type.nullable
|
val nullable get() = type.isNullable
|
||||||
|
|
||||||
/** Returns an adapter to use when encoding and decoding this property. */
|
/** Returns an adapter to use when encoding and decoding this property. */
|
||||||
fun generateProperty(
|
fun generateProperty(
|
||||||
|
@ -86,12 +86,12 @@ private fun TypeName.toVariableName(): String {
|
||||||
val base = when (this) {
|
val base = when (this) {
|
||||||
is ClassName -> simpleName
|
is ClassName -> simpleName
|
||||||
is ParameterizedTypeName -> rawType.simpleName + "Of" + typeArguments.toVariableNames()
|
is ParameterizedTypeName -> rawType.simpleName + "Of" + typeArguments.toVariableNames()
|
||||||
is WildcardTypeName -> (lowerBounds + upperBounds).toVariableNames()
|
is WildcardTypeName -> (inTypes + outTypes).toVariableNames()
|
||||||
is TypeVariableName -> name + bounds.toVariableNames()
|
is TypeVariableName -> name + bounds.toVariableNames()
|
||||||
else -> throw IllegalArgumentException("Unrecognized type! $this")
|
else -> throw IllegalArgumentException("Unrecognized type! $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (nullable) {
|
return if (isNullable) {
|
||||||
"Nullable$base"
|
"Nullable$base"
|
||||||
} else {
|
} else {
|
||||||
base
|
base
|
||||||
|
|
|
@ -44,7 +44,7 @@ internal class PropertyGenerator(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateLocalProperty(): PropertySpec {
|
fun generateLocalProperty(): PropertySpec {
|
||||||
return PropertySpec.builder(localName, target.type.asNullable())
|
return PropertySpec.builder(localName, target.type.copy(nullable = true))
|
||||||
.mutable(true)
|
.mutable(true)
|
||||||
.initializer("null")
|
.initializer("null")
|
||||||
.build()
|
.build()
|
||||||
|
|
|
@ -210,7 +210,7 @@ internal data class TargetType(
|
||||||
bounds = *possibleBounds.toTypedArray(),
|
bounds = *possibleBounds.toTypedArray(),
|
||||||
variance = it.varianceModifier)
|
variance = it.varianceModifier)
|
||||||
}
|
}
|
||||||
return@map typeVar.reified(it.reified)
|
return@map typeVar.copy(reified = it.reified)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,8 +41,8 @@ abstract class TypeRenderer {
|
||||||
abstract fun renderTypeVariable(typeVariable: TypeVariableName): CodeBlock
|
abstract fun renderTypeVariable(typeVariable: TypeVariableName): CodeBlock
|
||||||
|
|
||||||
fun render(typeName: TypeName): CodeBlock {
|
fun render(typeName: TypeName): CodeBlock {
|
||||||
if (typeName.nullable) {
|
if (typeName.isNullable) {
|
||||||
return renderObjectType(typeName.asNonNull())
|
return renderObjectType(typeName.copy(nullable = false))
|
||||||
}
|
}
|
||||||
|
|
||||||
return when (typeName) {
|
return when (typeName) {
|
||||||
|
@ -77,18 +77,18 @@ abstract class TypeRenderer {
|
||||||
val target: TypeName
|
val target: TypeName
|
||||||
val method: String
|
val method: String
|
||||||
when {
|
when {
|
||||||
typeName.lowerBounds.size == 1 -> {
|
typeName.inTypes.size == 1 -> {
|
||||||
target = typeName.lowerBounds[0]
|
target = typeName.inTypes[0]
|
||||||
method = "supertypeOf"
|
method = "supertypeOf"
|
||||||
}
|
}
|
||||||
typeName.upperBounds.size == 1 -> {
|
typeName.outTypes.size == 1 -> {
|
||||||
target = typeName.upperBounds[0]
|
target = typeName.outTypes[0]
|
||||||
method = "subtypeOf"
|
method = "subtypeOf"
|
||||||
}
|
}
|
||||||
else -> throw IllegalArgumentException(
|
else -> throw IllegalArgumentException(
|
||||||
"Unrepresentable wildcard type. Cannot have more than one bound: $typeName")
|
"Unrepresentable wildcard type. Cannot have more than one bound: $typeName")
|
||||||
}
|
}
|
||||||
CodeBlock.of("%T.%L(%T::class.java)", Types::class, method, target.asNonNull())
|
CodeBlock.of("%T.%L(%T::class.java)", Types::class, method, target.copy(nullable = false))
|
||||||
}
|
}
|
||||||
|
|
||||||
is TypeVariableName -> renderTypeVariable(typeName)
|
is TypeVariableName -> renderTypeVariable(typeName)
|
||||||
|
|
|
@ -17,10 +17,10 @@ package com.squareup.moshi.kotlin.codegen
|
||||||
|
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.ClassName
|
||||||
import com.squareup.kotlinpoet.ParameterizedTypeName
|
import com.squareup.kotlinpoet.ParameterizedTypeName
|
||||||
|
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||||
import com.squareup.kotlinpoet.TypeName
|
import com.squareup.kotlinpoet.TypeName
|
||||||
import com.squareup.kotlinpoet.TypeVariableName
|
import com.squareup.kotlinpoet.TypeVariableName
|
||||||
import com.squareup.kotlinpoet.WildcardTypeName
|
import com.squareup.kotlinpoet.WildcardTypeName
|
||||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves type parameters against a type declaration. Use this to fill in type variables with
|
* Resolves type parameters against a type declaration. Use this to fill in type variables with
|
||||||
|
@ -35,18 +35,18 @@ open class TypeResolver {
|
||||||
|
|
||||||
is ParameterizedTypeName -> {
|
is ParameterizedTypeName -> {
|
||||||
typeName.rawType.parameterizedBy(*(typeName.typeArguments.map { resolve(it) }.toTypedArray()))
|
typeName.rawType.parameterizedBy(*(typeName.typeArguments.map { resolve(it) }.toTypedArray()))
|
||||||
.asNullableIf(typeName.nullable)
|
.asNullableIf(typeName.isNullable)
|
||||||
}
|
}
|
||||||
|
|
||||||
is WildcardTypeName -> {
|
is WildcardTypeName -> {
|
||||||
when {
|
when {
|
||||||
typeName.lowerBounds.size == 1 -> {
|
typeName.inTypes.size == 1 -> {
|
||||||
WildcardTypeName.supertypeOf(resolve(typeName.lowerBounds[0]))
|
WildcardTypeName.consumerOf(resolve(typeName.inTypes[0]))
|
||||||
.asNullableIf(typeName.nullable)
|
.asNullableIf(typeName.isNullable)
|
||||||
}
|
}
|
||||||
typeName.upperBounds.size == 1 -> {
|
typeName.outTypes.size == 1 -> {
|
||||||
WildcardTypeName.subtypeOf(resolve(typeName.upperBounds[0]))
|
WildcardTypeName.producerOf(resolve(typeName.outTypes[0]))
|
||||||
.asNullableIf(typeName.nullable)
|
.asNullableIf(typeName.isNullable)
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
throw IllegalArgumentException(
|
throw IllegalArgumentException(
|
||||||
|
|
|
@ -28,5 +28,5 @@ internal fun TypeName.rawType(): ClassName {
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun TypeName.asNullableIf(condition: Boolean): TypeName {
|
internal fun TypeName.asNullableIf(condition: Boolean): TypeName {
|
||||||
return if (condition) asNullable() else this
|
return if (condition) copy(nullable = true) else this
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package com.squareup.moshi.kotlin.codegen
|
package com.squareup.moshi.kotlin.codegen
|
||||||
|
|
||||||
import com.squareup.kotlinpoet.ANY
|
|
||||||
import com.squareup.kotlinpoet.ClassName
|
import com.squareup.kotlinpoet.ClassName
|
||||||
import com.squareup.kotlinpoet.KModifier
|
import com.squareup.kotlinpoet.KModifier
|
||||||
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
|
||||||
|
import com.squareup.kotlinpoet.STAR
|
||||||
import com.squareup.kotlinpoet.TypeName
|
import com.squareup.kotlinpoet.TypeName
|
||||||
import com.squareup.kotlinpoet.TypeVariableName
|
import com.squareup.kotlinpoet.TypeVariableName
|
||||||
import com.squareup.kotlinpoet.WildcardTypeName
|
import com.squareup.kotlinpoet.WildcardTypeName
|
||||||
|
@ -75,11 +75,11 @@ internal fun Type.asTypeName(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFlexibleUpperBound()) {
|
if (hasFlexibleUpperBound()) {
|
||||||
return WildcardTypeName.subtypeOf(
|
return WildcardTypeName.producerOf(
|
||||||
flexibleUpperBound.asTypeName(nameResolver, getTypeParameter, useAbbreviatedType))
|
flexibleUpperBound.asTypeName(nameResolver, getTypeParameter, useAbbreviatedType))
|
||||||
.asNullableIf(nullable)
|
.asNullableIf(nullable)
|
||||||
} else if (hasOuterType()) {
|
} else if (hasOuterType()) {
|
||||||
return WildcardTypeName.supertypeOf(
|
return WildcardTypeName.consumerOf(
|
||||||
outerType.asTypeName(nameResolver, getTypeParameter, useAbbreviatedType))
|
outerType.asTypeName(nameResolver, getTypeParameter, useAbbreviatedType))
|
||||||
.asNullableIf(nullable)
|
.asNullableIf(nullable)
|
||||||
}
|
}
|
||||||
|
@ -107,15 +107,15 @@ internal fun Type.asTypeName(
|
||||||
.let { argumentTypeName ->
|
.let { argumentTypeName ->
|
||||||
nullableProjection?.let { projection ->
|
nullableProjection?.let { projection ->
|
||||||
when (projection) {
|
when (projection) {
|
||||||
Type.Argument.Projection.IN -> WildcardTypeName.supertypeOf(argumentTypeName)
|
Type.Argument.Projection.IN -> WildcardTypeName.consumerOf(argumentTypeName)
|
||||||
Type.Argument.Projection.OUT -> WildcardTypeName.subtypeOf(argumentTypeName)
|
Type.Argument.Projection.OUT -> WildcardTypeName.producerOf(argumentTypeName)
|
||||||
Type.Argument.Projection.STAR -> WildcardTypeName.STAR
|
Type.Argument.Projection.STAR -> STAR
|
||||||
Type.Argument.Projection.INV -> TODO("INV projection is unsupported")
|
Type.Argument.Projection.INV -> TODO("INV projection is unsupported")
|
||||||
}
|
}
|
||||||
} ?: argumentTypeName
|
} ?: argumentTypeName
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WildcardTypeName.STAR
|
STAR
|
||||||
}
|
}
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
typeName = (typeName as ClassName).parameterizedBy(*remappedArgs)
|
typeName = (typeName as ClassName).parameterizedBy(*remappedArgs)
|
||||||
|
|
|
@ -140,7 +140,7 @@ class KotlinCompilerCall(var scratchDir: File) {
|
||||||
ZipEntry("META-INF/services/${entry.key.qualifiedName}"))
|
ZipEntry("META-INF/services/${entry.key.qualifiedName}"))
|
||||||
val serviceFile = Okio.buffer(Okio.sink(zipOutputStream))
|
val serviceFile = Okio.buffer(Okio.sink(zipOutputStream))
|
||||||
for (implementation in entry.value) {
|
for (implementation in entry.value) {
|
||||||
serviceFile.writeUtf8(implementation.qualifiedName)
|
serviceFile.writeUtf8(implementation.qualifiedName!!)
|
||||||
serviceFile.writeUtf8("\n")
|
serviceFile.writeUtf8("\n")
|
||||||
}
|
}
|
||||||
serviceFile.emit() // Don't close the entry; that closes the file.
|
serviceFile.emit() // Don't close the entry; that closes the file.
|
||||||
|
|
|
@ -26,22 +26,21 @@ class TypeResolverTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensureClassNameNullabilityIsPreserved() {
|
fun ensureClassNameNullabilityIsPreserved() {
|
||||||
assertThat(resolver.resolve(Int::class.asClassName().asNullable()).nullable).isTrue()
|
assertThat(resolver.resolve(Int::class.asClassName().copy(nullable = true)).isNullable).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensureParameterizedNullabilityIsPreserved() {
|
fun ensureParameterizedNullabilityIsPreserved() {
|
||||||
val nullableTypeName = List::class.plusParameter(String::class)
|
val nullableTypeName = List::class.plusParameter(String::class).copy(nullable = true)
|
||||||
.asNullable()
|
|
||||||
|
|
||||||
assertThat(resolver.resolve(nullableTypeName).nullable).isTrue()
|
assertThat(resolver.resolve(nullableTypeName).isNullable).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun ensureWildcardNullabilityIsPreserved() {
|
fun ensureWildcardNullabilityIsPreserved() {
|
||||||
val nullableTypeName = WildcardTypeName.subtypeOf(List::class.asClassName())
|
val nullableTypeName = WildcardTypeName.producerOf(List::class.asClassName())
|
||||||
.asNullable()
|
.copy(nullable = true)
|
||||||
|
|
||||||
assertThat(resolver.resolve(nullableTypeName).nullable).isTrue()
|
assertThat(resolver.resolve(nullableTypeName).isNullable).isTrue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue