Giter VIP home page Giter VIP logo

innerbuilder's Introduction

innerbuilder Build Status

IntelliJ IDEA plugin that adds a 'Builder' action to the Generate menu (Alt+Insert) which generates an inner builder class as described in the Effective Java book. Works with IntelliJ IDEA 2019 and later.

screenshot

public class JavaBean {
    private final String foo;
    private String bar;
    private int qux;
    private Double x,y;

    private JavaBean(Builder builder) {
        foo = builder.foo;
        bar = builder.bar;
        qux = builder.qux;
        x = builder.x;
        y = builder.y;
    }

    public static Builder newJavaBean() {
        return new Builder();
    }

    public static final class Builder {
        private String foo;
        private String bar;
        private int qux;
        private Double x;
        private Double y;

        private Builder() {
        }

        public Builder foo(String val) {
            foo = val;
            return this;
        }

        public Builder bar(String val) {
            bar = val;
            return this;
        }

        public Builder qux(int val) {
            qux = val;
            return this;
        }

        public Builder x(Double val) {
            x = val;
            return this;
        }

        public Builder y(Double val) {
            y = val;
            return this;
        }

        public JavaBean build() {
            return new JavaBean(this);
        }
    }
}

Installation

In IntelliJ IDEA 2019 or later, open Preferences... > Plugins, search for innerbuilder. It should show up in the plugin list, click INSTALL.

Manual installation

Download the plugin jar innerbuilder.jar and select Install Plugin From Disk in IntelliJ's plugin preferences.

Usage

Use Shift+Alt+B or Alt+Insert and select Builder.... Choose the fields to be included and press OK. When generating a builder when a builder already exists, the plugin will try to update it. It will add missing fields and builder methods, but never remove any fields or methods.

Rate

If you enjoy this plugin, please rate it on its plugins.jetbrains.com page.

Building

  • Run ./prepare-build.sh to download IntelliJ IDEA Community Edition
  • Run mvn package

License

Licensed under the Apache License, Version 2.0.

innerbuilder's People

Contributors

analytically avatar fjardlabs avatar hahawin avatar jheirbaut avatar lanxx019 avatar lmineiro avatar markphilpot avatar minidmnv avatar neilg avatar prodikl avatar yuriy-eremin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

innerbuilder's Issues

Fields Only Added from Immediate Parent Class

I have a class setup like the following

Class C extends Class B extends Class A

In the field selection dialog box only field names from Class C and B are included. Is there a reason I can't also use the builder to declare Class A's fields?

Feature request update all files in package

Mathias
Id like to congratulate you on your excellent innerbuilder; it has saved me many hours of work.
I would like to make one request: add a facility to update all (or selected) .java in a package. I recently needed to do just that on 700+ files. Whilst innerbuilder saved many hours of work - it could have saved more with this update.

Keep up the good work.

db

Feature: add option to use default JVM contructor if the constructor is empty

Can you add an option to use default JVM contructor if the constructor is empty

According to squid:S1186 is having a empty body method a coding anti-pattern.

This is behavior now:

        private String name;
        private int age;

        public Builder() {
        }

        public Builder withName(String name) {
            this.name = name;
            return this;
        }

        public Builder withAge(int age) {
            this.age = age;
            return this;
        }

        public Person build() {
            return new Person(this);
        }

and this is the requested result

        private String name;
        private int age;

        public Builder withName(String name) {
            this.name = name;
            return this;
        }

        public Builder withAge(int age) {
            this.age = age;
            return this;
        }

        public Person build() {
            return new Person(this);
        }

Feature: Extend the static builder naming options with a regex textfield

Hello,

We ran into the limitation of not being able to provide our own naming for the static builder method. Therefor i would like to request
if it is possible to add the option in the prompt menu where we can write our own custom static builder naming pattern instead of choosing from the available options.

for example:
for class named Foo with static builder naming pattern = [className]From
would result in the static builder method being names as follows: public static Builder fooFrom() {}

Thanks.

Migration to java 8

What You guys think about migration to Java8, or even 11? I've tested already some migration to java 8 and it goes without any problems.

Customize pattern for creating the Builder

Currently the plugin is generating something like this:

public static final class Builder {

        private String foo;
       
        public Builder(){
        }

        public Builder foo (String foo) {
            this.foo = foo;
            return this;
        }

        public MyClass build(){
            return new MyClass(this);
       }

Is is possible to change the setting or customize the plugin to have something like this?:

public static class Builder {

        /** The MyClass to be build */
        private MyClass myClass;
       
        public Builder(){
           myClass = new MyClass();
        }

        public Builder(String foo) {
            this.myClass.setFoo(foo);
            return this;
        }

        public MyClass build(){
             return this.myClass;
       }

Thanks in advance.

Plugin generates copy constructors and use getXXX instead of isXXX for primitive boolean

Version 1.1.5

Following code is generated by the plugin

public class Todo {
    
    private boolean empty;

    private Todo(Builder builder) {
        empty = builder.empty;
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public static Builder newBuilder(Todo copy) {
        Builder builder = new Builder();
        builder.empty = copy.getEmpty();
        return builder;
    }


    public static final class Builder {
        private boolean empty;

        private Builder() {
        }

        public Builder empty(boolean val) {
            empty = val;
            return this;
        }

        public Todo build() {
            return new Todo(this);
        }
    }
}

Code Generation Prefix ignored

Hello,

thanks for this great plugin. I just got a little thing that would make this plugin perfect. In Settings -> Code Style -> Java -> Code Generation, we can define a prefix and a suffix. Unfortunately the prefix will not be checked. So the generated code looks something like that, if the prefix is '_':

public Builder with_content(string _content) {
    this._content = _content;
    return this;
}

In my opinion is would be nicer if the generated code looks something like this:

public Builder withContent(string content) {
    _content = content;
    return this;
}

Hope you understand my point. Thanks anyways. 👍

Support fields prefixes

When the POJO fields are prefixed, i.e with m --> private String mName the guilder with generated method is withMName(String val) is there any way to change it to be withName(String name) (as well as the param name)?

Optional Support for the build method

Often, if not always I am implementing the Builder like this:

public static final class Builder implements ValidatingBuilder {
        private Thing a;
        private Thing b;

        @Override
        public Boolean isValid() { return null != a && null != b; }

        public Builder withA(Thing a) {
            this.a = a;
            return this;
        }

        public Builder withB(Thing b) {
            this.b = b;
            return this;
        }

        public Optional<MyObject> build() {
            Optional<MyObject> myObject = Optional.empty();
            if (isValid()) {
                myObject = Optional.of(new MyObject(this));
            }

            return myObject;
        }
    }

The idea behind this is, that a resulting Object can only be instantiated if all mandatory fields are set (and further more with valid values). So I've made a very simple interface for this, but the build() method is not covered by it (the interface just lets me use [ctrl]-[i] to get the method stub).
I use the innerbuilder regularly and therefore issueing the request for supporting Optionals for the build method, because for me this would be a great feature.

Support for Android @NonNull and @Nullable annotations

Hi! 😄

It would be very helpful for me if this plugin could support NonNull and Nullable annotations from android.support.annotation. Logic would be pretty simple: if a field is marked as "NonNull", then the corresponding builder method parameter would be also marked as "NonNull". Same thing for "Nullable". It should generate similar code to JSR-305 NonNull annotation.

Thanks in advance! 😄

Support for Optionals

If I have some class with final optional variables, e.g

public final class ProductData {
    private final String code;
    private final String category;
    private final Optional<PriceData> price;
    //... getters ...
}

I want a option to create builder method that takes a PriceData instance and sets price to:

public ProductDataBuilder withPrice(PriceData price){
    this.price = Optional.ofNullable(price);
    return this;
}

This will make building classes with optional variables much smoother as we do not need to pre-wrap the arguments.

Copy builder uses getters even when they dont exist

In the version 1.1.5, the copy builder has started using getX() methods instead of just the field. So if there is a field without a getter function, like most public final fields would not have, the copy builder generated does not work properly.

Say we have the following class

public class Foo {
   public final String bar;
}

This would generate builder like

public static final class Builder {
        private String bar;

        public Builder() {
        }

        public Builder(final Foo copy) {
            this.bar = copy.getBar();
        }

        public Builder withBar(final String bar) {
            this.bar = bar;
            return this;
        }

        public Foo build() {
            return new Foo(this);
        }
    } 

this.bar = copy.getBar();
This part is not valid code as the class does not have getBar function

Plugin does not work with IntelliJ 2020.3

Hello there,

It looks like the plugin is not compatible with IntelliJ 2020.3 (version id 203).

As shown here, the highest supported version is 201:
https://plugins.jetbrains.com/plugin/7354-innerbuilder/versions/stable/39468

Manually installing the plugin results in the following error message:
Plugin "InnerBuilder" (version 1.1.5) was explicitly marked as incompatible with the current version of the IDE.

It seems like updating this line in src/main/resources/META-INF/plugin.xml:

<!-- Intellij 12+ -->
<idea-version since-build="123" />

To something like this

<!-- Intellij 12+ -->
<idea-version since-build="123" until-build="205"/>

Might solve it, although I haven't built an IntelliJ plugin before, so I'm not very sure.

I'd be happy to try and open an PR to get this in, if that'd solve it, but I figure you'd know better than I.

Thanks for the awesome plugin and for your time.

Allow builders to implement a Builder interface

For my use case, all builders must implement the IBuilder<O> interface which looks like this:

package com.example;

public interface IBuilder<O> {
    O build();
}

It would be amazing if we could configure the settings so that the generated builder class looks like this:

public final class Thing {
    ...
    public static final class Builder implements com.example.IBuilder<Thing> {
        ...
        @Override
        public Thing build() {
            return new Thing(...);
        }
    }
}

Maybe by specifying a configuration setting like the following:
build method = com.example.IBuilder.build

Which would also allow us to do something like this:
build method = java.util.function.Supplier.get,
generating the following code:

public static final class Builder implements java.util.function.Supplier<Thing> {
    ...
    @Override
    public Thing get() {
        return new Thing(...);
    }
}

Obviously, the specified interface would have to be a single-abstract-method functional interface, with the method having zero arguments.

That being the case, it might be redundant to specify the build method, when you could instead just specify the build interface. So something like this:

build interface = com.example.IBuilder
or
build interface = java.util.function.Supplier
or
build interface = org.apache.commons.lang3.builder.Builder
would also be great.

Make configurable static newBuilder() method

Please add option to change method name from newBuilder() to specified value, due to there different code style conventions and it depends from place where you work...

I change name manually to builder() after plugin finished work..

Thanks.

referencing wrong field name when global style of field name is prefixed with 'm'

in Android Studio, when setting java code style with field name prefix, then generated code is wrong, here is an example of auto generated Builder:

    public static final class Builder {
        private int mAppId;

        public Builder() {
        }
        
        public Builder appId(int val) {
            appId = val;
            return this;
        }

        public Config build() {
            return new Config(this);
        }
    }

Here, method appId references the wrong name.

InnerBuilder PluginException in IntelliJ v11.1.5

I am a big fan of builders and wrote one in C# using LINQPad to generate Java builders. I would much prefer your native solution, however it is not working for my version of IntelliJ. I am using IntelliJ v11.1.5 and InnerBuilder version 03.12.2013. When I enable it and restart IntelliJ, I get the following exception:

2:08:21 PM PluginException: org.jetbrains.plugins.innerbuilder.InnerBuilderAction: "relative-to-action" cannot be null if anchor is "after" or "before" [Plugin: InnerBuilder]: org.jetbrains.plugins.innerbuilder.InnerBuilderAction: "relative-to-action" cannot be null if anchor is "after" or "before" [Plugin: InnerBuilder]

Is InnerBuilder supported in version 11?

Thanks,
Derek

P.S. Here is the full stacktrace from the log file:

2013-12-04 14:08:17,990 [ 4621] ERROR - nSystem.impl.ActionManagerImpl - org.jetbrains.plugins.innerbuilder.InnerBuilderAction: "relative-to-action" cannot be null if anchor is "after" or "before" [Plugin: InnerBuilder]
com.intellij.diagnostic.PluginException: org.jetbrains.plugins.innerbuilder.InnerBuilderAction: "relative-to-action" cannot be null if anchor is "after" or "before" [Plugin: InnerBuilder]
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.a(ActionManagerImpl.java:903)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.checkRelativeToAction(ActionManagerImpl.java:656)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.a(ActionManagerImpl.java:644)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.a(ActionManagerImpl.java:380)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.a(ActionManagerImpl.java:845)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.a(ActionManagerImpl.java:209)
at com.intellij.openapi.actionSystem.impl.ActionManagerImpl.(ActionManagerImpl.java:142)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at org.picocontainer.defaults.InstantiatingComponentAdapter.newInstance(InstantiatingComponentAdapter.java:193)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:220)
at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:53)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:248)
at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:60)
at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:58)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:630)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:578)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:242)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:229)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:211)
at org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)
at org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:114)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getConstructorArguments(ConstructorInjectionComponentAdapter.java:257)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:217)
at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:53)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:248)
at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:60)
at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:58)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:630)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:578)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:242)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:229)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:211)
at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.getComponentInstance(AbstractDelegatingMutablePicoContainer.java:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.picocontainer.defaults.ImmutablePicoContainerProxyFactory.invoke(ImmutablePicoContainerProxyFactory.java:73)
at com.sun.proxy.$Proxy30.getComponentInstance(Unknown Source)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:232)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:211)
at org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)
at org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:114)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getConstructorArguments(ConstructorInjectionComponentAdapter.java:257)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:217)
at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:53)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:248)
at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:60)
at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:58)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:630)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:578)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:242)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:229)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:211)
at org.picocontainer.defaults.BasicComponentParameter.resolveInstance(BasicComponentParameter.java:77)
at org.picocontainer.defaults.ComponentParameter.resolveInstance(ComponentParameter.java:114)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getConstructorArguments(ConstructorInjectionComponentAdapter.java:257)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter$1.run(ConstructorInjectionComponentAdapter.java:217)
at org.picocontainer.defaults.ThreadLocalCyclicDependencyGuard.observe(ThreadLocalCyclicDependencyGuard.java:53)
at org.picocontainer.defaults.ConstructorInjectionComponentAdapter.getComponentInstance(ConstructorInjectionComponentAdapter.java:248)
at org.picocontainer.defaults.DecoratingComponentAdapter.getComponentInstance(DecoratingComponentAdapter.java:60)
at org.picocontainer.defaults.CachingComponentAdapter.getComponentInstance(CachingComponentAdapter.java:58)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:630)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:578)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:242)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:229)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:211)
at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.getComponentInstance(AbstractDelegatingMutablePicoContainer.java:75)
at com.intellij.openapi.components.impl.ComponentManagerImpl.createComponent(ComponentManagerImpl.java:126)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:107)
at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java:342)
at com.intellij.openapi.components.impl.ComponentManagerImpl.init(ComponentManagerImpl.java:85)
at com.intellij.openapi.project.impl.ProjectImpl.init(ProjectImpl.java:293)
at com.intellij.openapi.project.impl.ProjectManagerImpl.a(ProjectManagerImpl.java:277)
at com.intellij.openapi.project.impl.ProjectManagerImpl.getDefaultProject(ProjectManagerImpl.java:356)
at com.intellij.ide.UiActivityMonitorImpl.initComponent(UiActivityMonitorImpl.java:85)
at com.intellij.openapi.components.impl.ComponentManagerImpl.b(ComponentManagerImpl.java:216)
at com.intellij.openapi.components.impl.ComponentManagerImpl.access$1100(ComponentManagerImpl.java:54)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:643)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:578)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:242)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:229)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:211)
at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.getComponentInstance(AbstractDelegatingMutablePicoContainer.java:75)
at com.intellij.openapi.components.impl.ComponentManagerImpl.createComponent(ComponentManagerImpl.java:126)
at com.intellij.openapi.application.impl.ApplicationImpl.createComponent(ApplicationImpl.java:399)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:107)
at com.intellij.openapi.components.impl.ComponentManagerImpl.initComponents(ComponentManagerImpl.java:342)
at com.intellij.openapi.components.impl.stores.ApplicationStoreImpl.load(ApplicationStoreImpl.java:84)
at com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:515)
at com.intellij.idea.IdeaApplication.run(IdeaApplication.java:206)
at com.intellij.idea.MainImpl$3.run(MainImpl.java:184)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
at com.intellij.ide.IdeEventQueue.e(IdeEventQueue.java:699)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:538)
at com.intellij.ide.IdeEventQueue.b(IdeEventQueue.java:420)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:378)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
2013-12-04 14:08:17,994 [ 4625] ERROR - nSystem.impl.ActionManagerImpl - IntelliJ IDEA 11.1.5 Build #IU-117.1056

Javadoc too long

Automatically generated Javadoc too long, It's easy to exceed the 120 character limit.
Can make the generated javadoc shorter, or wrap.

Add support for required fields

Hi!

I think that would be nice to have an option to indicate which are the required fields, so in this way we can check at compile time what are the required fields that I must have to provide when I create a class.

In the two links below you can find examples of what I'm saying:
http://www.jayway.com/2012/02/07/builder-pattern-with-a-twist/
http://stackoverflow.com/questions/1638722/how-to-improve-the-builder-pattern

For example, the plugin could generate some code like this:
(In this pice of code the the port and the url are mandatory fields)

public class Address {
    private String protocol;
    private String url;
    private int port;
    private String path;
    private String description;

    // only builder should be able to create an instance
    private Address(Builder builder) {
        this.protocol = builder.protocol;
        this.url = builder.url;
        this.port = builder.port;
        this.path = builder.path;
        this.description = builder.description;
    }

    public static Url builder() {
        return new Builder();
    }

    public static class Builder implements Url, Port, Build{
        private String protocol;
        private String url;
        private int port;
        private String path;
        private String description;

        /** Mandatory, must be followed by {@link Port#port(int)}  */
        public Port url(String url) {
            this.url = url;
            return this;
        }

        /** Mandatory, must be followed by methods in {@link Build}  */
        public Build port(int port) {
            this.port = port;
            return this;
        }

        /** Non-mandatory, must be followed by methods in {@link Build}  */
        public Build protocol(String protocol) {
            this.protocol = protocol;
            return this;
        }

        /** Non-mandatory, must be followed by methods in {@link Build}  */
        public Build path(String path) {
            this.path = path;
            return this;
        }

        /** Non-mandatory, must be followed by methods in {@link Build}  */
        public Build description(String description) {
            this.description = description;
            return this;
        }

        /** Creates an instance of {@link Address} */
        public Address build() {
            return new Address(this);
        }
    }

    interface Url {
        public Port url(String url);
    }

    interface Port {
        public Build port(int port);
    }

    interface Build {
        public Build protocol(String protocol);
        public Build path(String path);
        public Build description(String description);
        public Address build();
    }

    // TODO: add some get methods here...
}

Regards,
Martín.

Generate Text that builder has been generated

What do you think about to extend the innerbuilder so that it is obvious to see that the builder has been generated? Reason: We are using the builder in some of our classes and if they are changed we do not want the engineers to modify the the builder manually. The should regenerate, similiar how the generate equals, hashCode and toString.

Something like

/**
 * generated with innerbuilder
**/

Not support inner class?

public class Foo extends FrameLayout {

    public Foo(@NonNull Context context) {
        this(context, null);
    }

    public Foo(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public Foo(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        inflate(context, R.layout.Foo, this);
    }

    public class CardInfo {

        private int status;
        private String cardNo;
        private String cardBgUrl;
        private boolean defaultCard;
        private String cardNumber;

    }


}

The "Builder options" didn't show up as I pressed Alt+Insert in this class for creating a builder for CardInfo

Builder methods should respect Checkstyle parameter rules

The current Builder template breaks Checkstyle rules for parameters, namely the hidden field rule. For example, public Builder name(String name) {...} generates a Checkstyle violation that states 'name' hides a field.

There should be an option to prefix the generated parameter names with something, such as "new" so that the above example becomes: public Builder name(String newName) {...} so that the Checkstyle violation is resolved.

Make Builder not use final's ?

Perhaps this is related to : #8

When I make a immutable class with final variables, I I expect the Builder inner class not to use final's, the Builder's class and constructor is created correctly though.

I think it defeats the purpose if the Builder class doesn't have a default constructor and essentially inherits the same constructor as my immutable class.

Hope I made myself clear :)

Builder does not support super class fields

If you generate a Builder that extends a class, it is not possible to select the fields of the super class. Also suppose the super class does not have a default constructor and has final fields, the Builder will generate a private constructor that is not valid for the class.

I think adding support for super classes will make this plugin a lot better.

Ability to remove annotations from from original fields

Was wondering if we can add a new feature (checkmark) -- to not copy over the annotations from the original fields that are defined

Example:

@NotNull
@Size(max = 250)
private String name;

Currently:

public Builder withName(@NotNull @Size(max = 250) String val) {
  name = val;
  return this;
}

Wanted feature:

public Builder withName(String val) {
  name = val;
  return this;
}

Thank you for this already great plugin!

"Generate..." popup takes 10+ seconds to show up

Version: 1.1.5
In class: com.intellij.ui.treeStructure.Tree

"AWT-EventQueue-0 2017.3#IU-173.3622.25 IDEA, eap:true, os:Windows 10 10.0, java-version:JetBrains s.r.o 1.8.0_152-release-1024-b6" prio=0 tid=0x0 nid=0x0 runnable
     java.lang.Thread.State: RUNNABLE

    at com.intellij.psi.impl.compiled.ClsRepositoryPsiElement.getParent(ClsRepositoryPsiElement.java:41)
    at com.intellij.psi.impl.compiled.ClsMethodImpl.getContainingClass(ClsMethodImpl.java:85)
    at com.intellij.psi.impl.PsiClassImplUtil.lambda$withSubstitutors$3(PsiClassImplUtil.java:994)
    at com.intellij.psi.impl.PsiClassImplUtil$$Lambda$1925/1673183955.fun(Unknown Source)
    at com.intellij.util.containers.ContainerUtil.map(ContainerUtil.java:1867)
    at com.intellij.psi.impl.PsiClassImplUtil.withSubstitutors(PsiClassImplUtil.java:993)
    at com.intellij.psi.impl.PsiClassImplUtil.getAllWithSubstitutorsByMap(PsiClassImplUtil.java:185)
    at com.intellij.psi.impl.PsiClassImplUtil.getAllByMap(PsiClassImplUtil.java:190)
    at com.intellij.psi.impl.PsiClassImplUtil.getAllMethods(PsiClassImplUtil.java:80)
    at com.intellij.psi.impl.compiled.ClsClassImpl.getAllMethods(ClsClassImpl.java:265)
    at org.jetbrains.plugins.innerbuilder.InnerBuilderCollector.hasSetter(InnerBuilderCollector.java:116)
    at org.jetbrains.plugins.innerbuilder.InnerBuilderCollector.collectFieldsInClass(InnerBuilderCollector.java:67)
    at org.jetbrains.plugins.innerbuilder.InnerBuilderCollector.collectFields(InnerBuilderCollector.java:49)
    at org.jetbrains.plugins.innerbuilder.InnerBuilderHandler.isApplicable(InnerBuilderHandler.java:46)
    at org.jetbrains.plugins.innerbuilder.InnerBuilderHandler.isValidFor(InnerBuilderHandler.java:37)
    at org.jetbrains.plugins.innerbuilder.InnerBuilderAction.isValidForFile(InnerBuilderAction.java:29)
    at com.intellij.codeInsight.actions.CodeInsightAction.update(CodeInsightAction.java:117)
    at com.intellij.codeInsight.actions.CodeInsightAction.update(CodeInsightAction.java:122)
    at com.intellij.codeInsight.actions.CodeInsightAction.update(CodeInsightAction.java:113)
    at com.intellij.codeInsight.actions.BaseCodeInsightAction.update(BaseCodeInsightAction.java:89)
    at com.intellij.openapi.actionSystem.AnAction.beforeActionPerformedUpdate(AnAction.java:240)
    at com.intellij.codeInsight.actions.CodeInsightAction.beforeActionPerformedUpdate(CodeInsightAction.java:87)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performDumbAwareUpdate(ActionUtil.java:129)
    at com.intellij.ui.popup.PopupFactoryImpl$ActionStepBuilder.a(PopupFactoryImpl.java:1138)
    at com.intellij.ui.popup.PopupFactoryImpl$ActionStepBuilder.b(PopupFactoryImpl.java:1129)
    at com.intellij.ui.popup.PopupFactoryImpl$ActionStepBuilder.buildGroup(PopupFactoryImpl.java:1074)
    at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.a(PopupFactoryImpl.java:325)
    at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.<init>(PopupFactoryImpl.java:260)
    at com.intellij.ui.popup.PopupFactoryImpl$ActionGroupPopup.<init>(PopupFactoryImpl.java:244)
    at com.intellij.ui.popup.PopupFactoryImpl.a(PopupFactoryImpl.java:222)
    at com.intellij.ui.popup.PopupFactoryImpl.a(PopupFactoryImpl.java:172)
    at com.intellij.ui.popup.PopupFactoryImpl.createActionGroupPopup(PopupFactoryImpl.java:463)
    at com.intellij.codeInsight.generation.actions.GenerateAction.actionPerformed(GenerateAction.java:39)
    at com.intellij.openapi.actionSystem.ex.ActionUtil$1.run(ActionUtil.java:216)
    at com.intellij.openapi.actionSystem.ex.ActionUtil.performActionDumbAware(ActionUtil.java:233)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher$1.performAction(IdeKeyEventDispatcher.java:576)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.a(IdeKeyEventDispatcher.java:625)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher$$Lambda$2936/1326196699.run(Unknown Source)
    at com.intellij.openapi.application.TransactionGuardImpl.performUserActivity(TransactionGuardImpl.java:195)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.processAction(IdeKeyEventDispatcher.java:624)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.e(IdeKeyEventDispatcher.java:479)
    at com.intellij.openapi.keymap.impl.IdeKeyEventDispatcher.dispatchKeyEvent(IdeKeyEventDispatcher.java:213)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:622)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:366)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

Plugin is not compatible with Java records

Here's a plugin output for record TestRecord(String a){}:

record TestRecord(String a){

    private TestRecord(Builder builder) {
        a = builder.a;
    }

    public static Builder builder(TestRecord copy) {
        Builder builder = new Builder();
        builder.a = copy.getA();
        return builder;
    }

    public static final class Builder {
        private String a;

        private Builder() {
        }

        public static Builder builder() {
            return new Builder();
        }

        public Builder withA(String val) {
            a = val;
            return this;
        }

        public TestRecord build() {
            return new TestRecord(this);
        }
    }
}

Two issues here:

  1. Record constructor needs to pass values via constructor (e.g. this(builder.a))
  2. Copy constructor is using copy.getA() instead of copy.a()

Feature: add option for constructors not to use overridable methods

Constructors should only call non-overridable methods

Calling an overridable method from a constructor could result in failures or strange behaviors when instantiating a subclass which overrides the method.

For example:

The subclass class constructor starts by contract by calling the parent class constructor.
The parent class constructor calls the method, which has been overridden in the child class.
If the behavior of the child class method depends on fields that are initialized in the child class constructor, unexpected behavior (like a NullPointerException) can result, because the fields aren't initialized yet.

Noncompliant Code Example

public class Parent {

  public Parent () {
    doSomething();  // Noncompliant
  }

  public void doSomething () {  // not final; can be overridden
    ...
  }
}

public class Child extends Parent {

  private String foo;

  public Child(String foo) {
    super(); // leads to call doSomething() in Parent constructor which triggers a NullPointerException as foo has not yet been initialized
    this.foo = foo;
  }

  public void doSomething () {
    System.out.println(this.foo.length());
  }

}

Fields are missing

When I create an classfile and add field by field I want to create the builder for each field I added, because there are other modifications elsewhere required.

My problem is that after adding a field to the class the builder doe not provide this new field . First I thought I have to recompile the project than the builder can see the fields, but this did not work.

Any idea, how to force the builder to see the new fields?

Do not support perfix.

My code style is every private fields' name start with the letter "m". But the plugin cannot ignore it.

Use 'set...' notation

It would be a nice feature to use a 'set' prefix instead of 'with'. Many builder patterns I've seen on Android use 'set'. Also, it would be nice to have fields in the builder class be package-local to avoid creating synthetic accessor methods.

Add a option to use field name for setters.

As a developer, I would like to avoid using generic name like val or value for setter parameter names. I would like to be able to pass in the parameter using actual field name. E.g.

public Builder withFieldName(String fieldName) {
    this.fieldName = fieldName;
    return this;
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.