Curious if anyone thinks it'd be a good idea to ha...
# language-proposals
k
Curious if anyone thinks it'd be a good idea to have a
@JvmBuilder
compiler plugin in the stdlib + Kotlin IntelliJ plugin that would generate synthetic members to make builders on `data class`es for use in Java. Using `data class`es with many properties is currently pretty clunky in Java. For example:
Copy code
@JvmBuilder
data class Foo(val bar: String, val baz: Int = 0, val qux: String? = null)
should generate
Foo.builder()
that returns an object like:
Copy code
public final class FooBuilder {
  public static FooBuilder builder() {
    return new FooBuilder().baz(0).qux(null);
  }
  
  // fields...

  public FooBuilder bar(String bar) { ... }
  public FooBuilder baz(int baz) { ... }
  public FooBuilder qux(@Nullable String qux) { ... }
  public Foo build() {
    // assert that properties with no default value were set
  }
}
x
could just use immutables library?
k
Sure, or you could use AutoValue, but then: 1) you're writing your data classes in Java, not Kotlin 2) At least with AutoValue, it's still a ton of boilerplate and noise (
public abstract
everywhere) 3) Default values and optional values are hard to express in AutoValue. You put all the defaults into the
.builder()
method, not next to the property itself, so it's a lot of jumping around
I currently do keep my data classes in mixed projects in Java, because using
@AutoValue
classes in Kotlin is less painful than using `data class`es in Java. But writing
@AutoValue
classes is very painful compared to writing `data class`es
x
not certain that builder pattern is as valuable when you have key value pair constructors
but I digress
just my poor 2 cents
j
Pretty sure there is at least one or two of these already
I'm mobile. Will find when I get home
k
@xenoterracide can you elaborate? "Not as valuable when you have key value pair constructors". Any data class could be expressed as a fluent builder for Java
@jw do you mean something like this? https://github.com/jffiorillo/jvmbuilder This seems valuable (and I wasn't aware of its existence until now), but a compiler plugin would be preferable to an annotation processor IMHO. You wouldn't have to rely on a generated class as the builder type (it could be a synthetic provided by the Kotlin IntelliJ plugin so IDE autocomplete would work)
👌 1
x
3 reasons to use anaemic builders, 1 immutable result objects, 2 a readable way to construct the object (e.g. fluent). 3, the ability to programmatically build an object, and pass around that constructor object. 1 and 2 can be had simply by having key value pair constructors (kotlin has, java doesn’t)
so unless you’re passing the builder around… it becomes less necessary
k
by "key value pair constructors", you mean named parameters?
ex:
Foo(bar = "str1", baz = 2)
like all
@Jvm___
annotations, this is an enhancement for Java, not for Kotlin. In mixed codebases, you either have to make the decision to keep your data classes in Java, or convert them to Kotlin and force Java consumers to call constructors with 10+ parameters (comma-separated, with no named param support, as you said)
👍 1
and without sane defaults, too. If I wanted to use my
Foo
class in Java, it would be
new Foo("str1", 2, null);
. That's unclear (and requires duplication of the
null
for
qux
, which could be error-prone if we changed the default value of
qux
in the future)
Foo.builder().bar("str1").baz(2).build();
is way less error-prone
x
you can call them named parameters, yes that’s what I mean, but in other languages that have them they are called other things
point is that you have name value next to each other
k
right, which is why builders aren't necessary in Kotlin. But they are in Java, which is why it'd be nice if `data class`es could generate builders for Java consumers
x
sure
I can agree with that
also, it’s probably not worth saying, but there is still a case for rich (not anaemic builders) in kotlin, but those can’t be generated
j
Even for Kotlin I'd like a
builder { }
where I could put logic in a mutation/construction operation
👍 2
k
Hm, what would that look like? Would you have access to the properties on the data class inside the lambda?
Copy code
builder {
  bar = computeFoo()
  baz = bar.length()
}
x
I’m not sure, I’d have to think about that for more than a few seconds, but often I need to default properties and use if statements in the final construction logic in builders
a “rich” builder is more than the sum of its properties
e
This could be a compiler plugin and these kinds of plugins will be enabled by the IR work that Kotlin team is currently focused on. It does not belong to the core language / compiler, though.
👍 2
k
@elizarov yeah, I would think it should be a compiler plugin for sure, and not part of the compiler. Similar to how
@Parcelize
is implemented. Is the Kotlin team discouraging the addition of new compiler plugins using the currently bytecode-generation approach? I know IR is the future of compiler plugins and that the team is working hard on that, but it doesn't seem like there's a clear timeline for it. And I know that there's work going on for other compiler plugins at the moment (like the cross-platform serialization plugin). Not sure if you're targeting that for IR or bytecode+JS+LLVM generation though
when I said "in the stdlib + Kotlin IntelliJ plugin", I meant "it could be one of the plugins in https://github.com/JetBrains/kotlin/tree/master/plugins so that all Kotlin users would get the IntelliJ plugin for free". And if there's interest and it seems viable, I'd be happy to draft a KEEP for this
e
We do not encourage plugins at the moment, because the infrastructure to write is currently under a big rewrite (IR). The end-game is going to be ability to write and maintain plugin outside of the Jetbrains team.
k
Makes sense; sounded like the IR rewrite is a big effort that's going to take a while. What's the end-game plan for the accompanying IntelliJ plugins? It's really nice right now that the IntelliJ plugin for every compiler plugin is included with the core Kotlin plugin, so teams don't have to hunt down every team member to install a new plugin when they add a new compiler plugin to their codebase
e
In the end, compiler plugins will be added to the project just like other project dependencies (libraries).
j
Will they be able to ship an IDE component somehow? It'd be amazing that when you add a Gradle plugin it could also add IDE behavior. Something work thinking about.
e
Yes. The end game for plugins is that they do not only affect compiler, but they also drive resolution in IDE. In essence, compiler plugins are supposed to be annotation processors on steroids. Powerful macro-definitions without their IDE-experience-destroying side-effects. With full support for incremental analysis and compilation, too.
😍 1
k
That sounds perfect, then. Definitely worth waiting for. Right now, besides the pain-point of not having a common language to target with compiler plugins, we also have to rely on users installing a 3rd-party IDE plugin 🙂
@elizarov quick question: any way we can track progress on the new IR? YouTrack tickets, a Git branch where this is being worked on, a directory in the Git repo where this code is being committed, etc? Also, I assume that this is going to replace everything, including the current
IrGenerationExtension
(which isn't the Kotlin IR in question here, but LLVM IR, right?)