Use raw type for kclass references in dynamic invocation code gen (#911)

* Use raw type for kclass references in dynamic invocation code gen

Added a compile-only regression test
Resolves #905

* Make it actually generic

* Mostly fix generation

Will need to wait for inlined instantiation to merge

* Fix rebase issues and use newInstance
This commit is contained in:
Zac Sweers
2019-09-12 21:55:47 -04:00
committed by GitHub
parent dd0e3807d3
commit 1e541fc66c
2 changed files with 35 additions and 8 deletions

View File

@@ -24,6 +24,7 @@ import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.NameAllocator import com.squareup.kotlinpoet.NameAllocator
import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ParameterizedTypeName
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.PropertySpec
import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.TypeSpec
@@ -260,21 +261,39 @@ internal class AdapterGenerator(
} else { } else {
CodeBlock.of("return·") CodeBlock.of("return·")
} }
val localConstructorName = nameAllocator.newName("localConstructor")
if (useDefaultsConstructor) { if (useDefaultsConstructor) {
classBuilder.addProperty(constructorProperty) classBuilder.addProperty(constructorProperty)
// Dynamic default constructor call // Dynamic default constructor call
result.addStatement( val rawOriginalTypeName = originalTypeName.rawType()
"val %1L·= this.%2N ?: %3T.lookupDefaultsConstructor(%4T::class.java).also·{ this.%2N·= it }", val nonNullConstructorType = constructorProperty.type.copy(nullable = false)
localConstructorName, val coreLookupBlock = CodeBlock.of(
constructorProperty, "%T.lookupDefaultsConstructor(%T::class.java)",
MOSHI_UTIL, MOSHI_UTIL,
originalTypeName rawOriginalTypeName
) )
val lookupBlock = if (originalTypeName is ParameterizedTypeName) {
CodeBlock.of("(%L·as·%T)", coreLookupBlock, nonNullConstructorType)
} else {
coreLookupBlock
}
val initializerBlock = CodeBlock.of(
"this.%1N ?:·%2L.also·{ this.%1N·= it }",
constructorProperty,
lookupBlock
)
val localConstructorProperty = PropertySpec.builder(
nameAllocator.newName("localConstructor"),
nonNullConstructorType)
.addAnnotation(AnnotationSpec.builder(Suppress::class)
.addMember("%S", "UNCHECKED_CAST")
.build())
.initializer(initializerBlock)
.build()
result.addCode("%L", localConstructorProperty)
result.addCode( result.addCode(
"«%L%L.newInstance(", "«%L%N.newInstance(",
returnOrResultAssignment, returnOrResultAssignment,
localConstructorName localConstructorProperty
) )
} else { } else {
// Standard constructor call // Standard constructor call

View File

@@ -47,6 +47,14 @@ data class TestClass(
val dynamicInlineOptional: Int = createInlineInt() val dynamicInlineOptional: Int = createInlineInt()
) )
// Regression test for https://github.com/square/moshi/issues/905
// Just needs to compile
@JsonClass(generateAdapter = true)
data class GenericTestClassWithDefaults<T>(
val input: String = "",
val genericInput: T
)
private fun createInt(): Int { private fun createInt(): Int {
return 3 return 3
} }