7

I want to generate simple data class with KotlinPoet:

data class User(val id: Int)

I do it like that:

val builder = KotlinFile.builder("", "Foo")
val classBuilder = TypeSpec.classBuilder("User").addModifiers(KModifier.DATA)
val ctor = FunSpec.constructorBuilder()
ctor.addParameter("id", Int::class)
classBuilder.primaryConstructor(ctor.build())
builder.addType(classBuilder.build())
builder.build().writeTo(System.out)

But what I get is this:

data class User(id: Int) {
}

How can I add val modifier to constructor parameter?

Egor
  • 39,695
  • 10
  • 113
  • 130
xap4o
  • 2,776
  • 2
  • 19
  • 13

1 Answers1

8

Here is an issue discussing this problem.

The conclusion is that the way to write this code is to create a property that matches the constructor parameter's name, and is initialized by it:

KotlinFile.builder("", "Foo")
        .addType(TypeSpec.classBuilder("User")
                .addModifiers(KModifier.DATA)
                .primaryConstructor(FunSpec.constructorBuilder()
                        .addParameter("id", Int::class)
                        .build())
                .addProperty(PropertySpec.builder("id", Int::class)
                        .initializer("id")
                        .build())
                .build()
        )
        .build()
        .writeTo(System.out)

However, this feature is not available as of the 0.2.0 release of KotlinPoet. It is already implemented, and there is a test for this in the repository that is passing, but you'll have to wait for the 0.3.0 release of KotlinPoet to be able to use this feature, which is supposed to come in the next few days.

This feature is available from 0.3.0, which is out now.


The previous code with an alternative formatting that matches your original style:

val builder = KotlinFile.builder("", "Foo")
val classBuilder = TypeSpec.classBuilder("User").addModifiers(KModifier.DATA)

val ctor = FunSpec.constructorBuilder()
ctor.addParameter("id", Int::class)
classBuilder.primaryConstructor(ctor.build())

val idProperty = PropertySpec.builder("id", Int::class).initializer("id").build()
classBuilder.addProperty(idProperty)

builder.addType(classBuilder.build())
builder.build().writeTo(System.out)
zsmb13
  • 85,752
  • 11
  • 221
  • 226
  • Are there any plans to add idiomatic data class field declaration support? – xap4o Jun 12 '17 at 15:07
  • 1
    Not sure, you'd have to ask them. In the meantime, 0.3.0 is out as of 23 hours ago, you can go ahead and update to it. I'll edit my answer too. – zsmb13 Jun 12 '17 at 15:10