projectlombok / lombok

Very spicy additions to the Java programming language.
https://projectlombok.org/
Other
12.79k stars 2.37k forks source link

[FEATURE] @Builder on an interface method #2493

Open juriad opened 4 years ago

juriad commented 4 years ago

Use case:

I have this method defined in class DbConnection:

    @Builder(builderClassName = "MultiInsertBuilder", builderMethodName = "insertMultiple", buildMethodName = "insert")
    int insertMultipleValues(
            @Nullable Table table,
            @Singular Collection<? extends List<?>> values,
            Boolean ignoreDuplicates, /* ignore by default */
            Integer batchSize /* default 1000 */
    ) {...}

Now I have to extract an interface because there are different implementations for Oracle and Postgres.

Simply adding the annotation on a method in an interface leads to:

error: non-static variable this cannot be referenced from a static context

Implementation

There are a couple things that need to change in comparison to a builder on a method in a class or enum:

Concerns

Builder Support

I also found that @Builder is allowed on enum's constructor, which causes a compile error:

error: enum types may not be instantiated

It is not entirely related to this feature request, but can probably be fixed at the same time. I assume that we want to report an error to the user in such situation.

type method constructor
class Works Works Works
enum Error Works Bug
interface Error Proposition N/A
juriad commented 4 years ago

Ok, I started implementing it; it does not look hard; verbose but doable.

So far I only have one question: com.sun.tools.javac.code.Flags does not contain constant for DEFAULT because it was not a modifier in Java 6 (net.java.openjdk.custom-javac6.jar). How should I handle this?


I was fooled by error messages from Intellij plugin instead of Lombok itself. Actually the table should look like this (proposed improvement is highlighted):

  type constructor method static method
class Works Works Works Works
enum error: enum types may not be instantiated error: enum types may not be instantiated Works Works
interface error: $typename is abstract; cannot be instantiated N/A error: non-static variable this cannot be referenced from a static context Works
annotation interface error: modifier static not allowed here N/A error: non-static variable this cannot be referenced from a static context N/A
janrieke commented 4 years ago

Just a hint: Before you invest too much time on a pull request, you should wait for some feedback from the maintainers. There may be reasons why this does not work (and should not work). One could be that this is not a real builder pattern any more, but a kind of method-argument collector.

I would simply not generate the builder() method. If you are on java8+, you could still add it manually to the interface or to the implementing class, as it's quite trivial.