Как сгенерировать параметр конструктора типа Kotlin "Unit" с параметром одного типа с помощью kotlinpoet?

Это может быть слишком специфично для публикации здесь, но я пытаюсь создать такой класс с помощью kotlinpoet:

class Query<out E: Model>(val onSuccess: (E) -> Unit, val onError: (Int, String) -> Unit = { i, m -> })

Как бы я создал этот параметр типа / конструктора с kotlinpoet? Документы имеют "Unit"Тип перечислен вместе с примитивными типами, поэтому, похоже, это особый случай.

2 ответа

Решение

Достаточно легко, это делается с помощью LambdaTypeName учебный класс. Это было немного странно после привыкания к стилю функциональных типов kotlin, в отличие от строго функциональных интерфейсов java. Вот что я использовал:

val typeVariable = TypeVariableName.invoke("E")
    .withBounds(QueryData::class)
ParameterSpec.builder("onSuccess", 
    LambdaTypeName.get(null, listOf(typeVariable), UNIT)).build()

Который генерирует (со строителями класса, конечно):

class Query<E : QueryData> {
  constructor(onSuccess: (E) -> Unit) {
  }
}

Вот программа, которая производит вывод, который вам нужен:

class Model

fun main(args: Array<String>) {
  val onSuccessType = LambdaTypeName.get(
      parameters = TypeVariableName(name = "E"),
      returnType = Unit::class.asTypeName())
  val onErrorType = LambdaTypeName.get(
      parameters = listOf(Int::class.asTypeName(), String::class.asTypeName()),
      returnType = Unit::class.asTypeName())
  val primaryConstructor = FunSpec.constructorBuilder()
      .addParameter(ParameterSpec.builder(name = "onSuccess", type = onSuccessType)
          .build())
      .addParameter(ParameterSpec.builder(name = "onError", type = onErrorType)
          .defaultValue("{ i, m -> }")
          .build())
      .build()

  val querySpec = TypeSpec.classBuilder("Query")
      .addTypeVariable(TypeVariableName(name = "out E", bounds = Model::class))
      .addProperty(PropertySpec.builder(name = "onSuccess", type = onSuccessType)
          .initializer("onSuccess")
          .build())
      .addProperty(PropertySpec.builder(name = "onError", type = onErrorType)
          .initializer("onError")
          .build())
      .primaryConstructor(primaryConstructor)
      .build()

  val file = KotlinFile.builder(packageName = "", fileName = "test")
      .addType(querySpec)
      .build()
  file.writeTo(System.out)
}

Это печатает (исключая сгенерированный импорт) следующее:

class Query<out E : Model>(val onSuccess: (E) -> Unit,
    val onError: (Int, String) -> Unit = { i, m -> })

Я взломал TypeVariableName здесь как out E, поскольку, кажется, нет лучшего решения в то время. Я также использую 0.4.0-SNAPSHOT версия.

Другие вопросы по тегам