简体   繁体   中英

Lombok @SuperBuilder workaround on IntelliJ

I've a class Product:

   @Data
   @SuperBuilder
   public class Product {

        private String name;
        private String manufacturer;

   }

and an extended class

@Data
@SuperBuilder
public class Frame extends Product{

   private String model;

}

I'm trying to create a Frame object using the builder:

 return Frame.builder() 
        .name("Frame ABC")
        .manufacturer("Manufacturer")
        .model("Model 1")
        .build();

I'm using IntelliJ 2019.1.1 with Lombok plugin but unfortunately the compiler marks as error the .name() and .manufacturer() methods. I saw this issue opened and I'm wondering if there is a workaround to make my code to work.

No, not until the issue is resolved.

Its a chicken and egg issue. Until the classes with the @SuperBuilder annotations are compiled, the actual generated builder methods do not exist. The plugin (once updated/fixed) works with the IDE for these methods so that even though they don't exist yet, the plugin tells the IDE what they will be when compilation takes place.

There are ways to 'cheat' but they are all hacks - for example, you could compile your (super)builder classes in their own jar and then import that jar into your project. As you compiled the SuperBuilder classes they now contain all the generated methods, thus the IDE will see the actual methods and will therefore propose them if you try use them. Functional but not very useful... if you need to update the SuperBuilder annotated classes, you now have to compile them each time before the changes become visible. Obviously you could create build tasks to do this for you, but you are always working around the actual issue which is plugin support.

This workaround works for me:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product {

  private String name;
  private String manufacturer;

}

@Data
@NoArgsConstructor
public class Frame extends Product{

   private String model;

   @Builder
   public Frame(String name, String manufacturer, String model){
      super(name, manufacturer);
      this.model = model;
   }

}

The only problem I see is when you have a lot of fields in the class it is becoming annoying to write such constructors, but still I think it worth it cause at the end you can access parent and child fields.

 return Frame.builder()
        
        .name("Frame ABC")
        
        .manufacturer("Manufacturer")
        
        .model("Model 1")
        
        .build();

Build with child member fields first, then parent member fields, with a type casting seems to work for me:

return (Frame) Frame.builder()
                    .model("Model 1")
                    .name("Frame ABC")  
                    .manufacturer("Manufacturer")    
                    .build();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM