skinny85 / jilt

Java annotation processor library for auto-generating Builder (including Staged Builder) pattern classes
Other
229 stars 13 forks source link

Add propagation of properties' annotations #20

Closed thmasker closed 3 months ago

thmasker commented 3 months ago

Hello, (it's me again). I've made a PR (https://github.com/skinny85/jilt/pull/19) with the additional feature to propagate properties' annotations in the builders. I think this would be nice to have (in fact, I'd like to use it for my projects). Open to discussion/rejection, obviously!

skinny85 commented 3 months ago

Hey @thmasker,

thanks for opening the PR!

Would you mind expanding on the reasoning behind this PR? What does it enable that wasn't possible previously?

Thanks, Adam

thmasker commented 3 months ago

The idea is basically the same operation the library already does when facing a @Nullable annotation. Maybe I can clarify it with an example. Given the following class:

@Builder(style = BuilderStyle.STAGED_PRESERVING_ORDER)
public class PropagatedAnnotationName {
  public final String firstName;

  @Nullable
  public final String middleName;

  @NotNull
  public final String lastName;

  public PropagatedAnnotationName(String firstName, String middleName, String lastName) {
    this.firstName = firstName;
    this.middleName = middleName;
    this.lastName = lastName;
  }
}

The current generated builder would look like this (note the propagation of @Nullable for middleName):

public class PropagatedAnnotationNameBuilder implements PropagatedAnnotationNameBuilders.FirstName, PropagatedAnnotationNameBuilders.MiddleName, PropagatedAnnotationNameBuilders.LastName, PropagatedAnnotationNameBuilders.Build {
  private String firstName;

  private String middleName;

  private String lastName;

  private PropagatedAnnotationNameBuilder() {
  }

  public static PropagatedAnnotationNameBuilders.FirstName propagatedAnnotationName() {
    return new PropagatedAnnotationNameBuilder();
  }

  public PropagatedAnnotationNameBuilder firstName(String firstName) {
    this.firstName = firstName;
    return this;
  }

  public PropagatedAnnotationNameBuilder middleName(@Nullable String middleName) {
    this.middleName = middleName;
    return this;
  }

  public PropagatedAnnotationNameBuilder lastName(String lastName) {
    this.lastName = lastName;
    return this;
  }

  public PropagatedAnnotationName build() {
    return new PropagatedAnnotationName(firstName, middleName, lastName);
  }
}

However, any other annotations are not propagated. And it would be really useful to propagate them (for instance, in this case it would allow us to prevent passing null in the case of lastName). This PR would produce the following builder:

public class PropagatedAnnotationNameBuilder implements PropagatedAnnotationNameBuilders.FirstName, PropagatedAnnotationNameBuilders.MiddleName, PropagatedAnnotationNameBuilders.LastName, PropagatedAnnotationNameBuilders.Build {
  private String firstName;

  private String middleName;

  private String lastName;

  private PropagatedAnnotationNameBuilder() {
  }

  public static PropagatedAnnotationNameBuilders.FirstName propagatedAnnotationName() {
    return new PropagatedAnnotationNameBuilder();
  }

  public PropagatedAnnotationNameBuilder firstName(String firstName) {
    this.firstName = firstName;
    return this;
  }

  public PropagatedAnnotationNameBuilder middleName(@Nullable String middleName) {
    this.middleName = middleName;
    return this;
  }

  public PropagatedAnnotationNameBuilder lastName(@NotNull String lastName) {
    this.lastName = lastName;
    return this;
  }

  public PropagatedAnnotationName build() {
    return new PropagatedAnnotationName(firstName, middleName, lastName);
  }
}
skinny85 commented 3 months ago

OK, thanks for that explanation, that's super helpful!

I'll review the PR.

skinny85 commented 3 months ago

This feature has been released in Jilt version 1.6.

Let me know if you run into any problems related to this, and I'd be happy to reopen this issue.