Skip to content

Commit 97b236f

Browse files
authored
Create add method for initialized collections (#4)
* Remove unused var * Adding builder classes * Add GeneratorFactory * Handle addToCollection
1 parent 0839006 commit 97b236f

15 files changed

+417
-151
lines changed

README.md

Lines changed: 97 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,48 +2,98 @@
22

33
# An opinionated Java Inner Builder Generator
44

5-
This is an opinionated but simple Java Inner Builder Generator IntelliJ plugin that generates a
6-
builder for a given class. The builder is an inner class of the class it is building.
5+
This is an opinionated but simple Java Inner Builder Generator IntelliJ plugin that generates an
6+
inner builder for a given class.
77

88
Based from [InnerBuilder](https://github.com/analytically/innerbuilder) with stripped down features.
99

10-
Generates a builder class for a given class with the following features:
11-
12-
1. Generates builder method for final fields that are not initialized and/or static fields
10+
1. Generates builder method for final fields that are not initialized, static fields are excluded
1311
2. Generates static `builder()` method inside the parent class
1412
3. Uses field names as setters in the builder
13+
4. Detects collection types and generates `addTo...` method for them if they are initialized
1514

1615
Optional features:
1716

1817
1. Generates `toBuilder()` method to convert the object to a builder
1918
2. Generates `validate()` method to validate the fields before building the object
2019

21-
<!-- Plugin description end -->
20+
### Example
21+
22+
Initial
2223

2324
```java
2425
public class Person {
26+
static String m = "ME";
2527
private static final Logger logger = Logger.getLogger("test");
28+
private final String name;
29+
private final int age;
30+
private String lastName;
31+
32+
private List<String> list;
2633

27-
private final String name = "1";
34+
private Set<String> set;
35+
36+
private final List<Address> addresses = new ArrayList<>();
37+
38+
}
39+
```
40+
41+
Generates
42+
43+
```java
44+
public class Person {
45+
static String m = "ME";
46+
private static final Logger logger = Logger.getLogger("test");
47+
private final String name;
2848
private final int age;
2949
private String lastName;
3050

51+
private List<String> list;
52+
53+
private Set<String> set;
54+
55+
private final List<Address> addresses;
56+
3157
private Person(Builder builder) {
58+
name = builder.name;
3259
age = builder.age;
3360
lastName = builder.lastName;
61+
list = builder.list;
62+
set = builder.set;
63+
addresses = builder.addresses;
3464
}
3565

3666
public static Builder builder() {
3767
return new Builder();
3868
}
3969

70+
public Builder toBuilder() {
71+
Builder builder = new Builder();
72+
builder.name = this.name;
73+
builder.age = this.age;
74+
builder.lastName = this.lastName;
75+
builder.list = this.list;
76+
builder.set = this.set;
77+
builder.addresses = this.addresses;
78+
return builder;
79+
}
80+
4081
public static final class Builder {
82+
private String name;
4183
private int age;
4284
private String lastName;
85+
private List<String> list;
86+
private Set<String> set;
87+
private List<Address> addresses = new ArrayList<>();
4388

4489
private Builder() {
4590
}
4691

92+
public Builder name(String name) {
93+
this.name = name;
94+
return this;
95+
}
96+
4797
public Builder age(int age) {
4898
this.age = age;
4999
return this;
@@ -54,6 +104,21 @@ public class Person {
54104
return this;
55105
}
56106

107+
public Builder list(List<String> list) {
108+
this.list = list;
109+
return this;
110+
}
111+
112+
public Builder set(Set<String> set) {
113+
this.set = set;
114+
return this;
115+
}
116+
117+
public Builder addToAddresses(Address e) {
118+
this.addresses.add(e);
119+
return this;
120+
}
121+
57122
private void validate() {
58123
}
59124

@@ -68,60 +133,66 @@ public class Person {
68133
Supports Java record classes
69134

70135
```java
71-
record Address(String street, String city, String state, String country) {
136+
record Address(Person person, List<String> streets, String city) {
137+
static String m = "ME";
138+
139+
}
140+
```
141+
142+
Generates
143+
144+
```java
145+
record Address(Person person, List<String> streets, String city) {
72146
static String m = "ME";
73147

74148
public static Builder builder() {
75149
return new Builder();
76150
}
77151

78-
//optional toBuilder method
79152
public Builder toBuilder() {
80153
Builder builder = new Builder();
81-
builder.street = this.street;
154+
builder.person = this.person;
155+
builder.streets = this.streets;
82156
builder.city = this.city;
83-
builder.state = this.state;
84-
builder.country = this.country;
85157
return builder;
86158
}
87159

88160
public static final class Builder {
89-
private String street;
161+
private Person person;
162+
private List<String> streets;
90163
private String city;
91-
private String state;
92-
private String country;
93164

94165
private Builder() {
95166
}
96167

97-
public Builder street(String street) {
98-
this.street = street;
168+
public Builder person(Person person) {
169+
this.person = person;
99170
return this;
100171
}
101172

102-
public Builder city(String city) {
103-
this.city = city;
173+
public Builder streets(List<String> streets) {
174+
this.streets = streets;
104175
return this;
105176
}
106177

107-
public Builder state(String state) {
108-
this.state = state;
178+
public Builder city(String city) {
179+
this.city = city;
109180
return this;
110181
}
111182

112-
public Builder country(String country) {
113-
this.country = country;
114-
return this;
183+
private void validate() {
115184
}
116185

117-
//follows the containing class visibility
118186
Address build() {
119-
return new Address(street, city, state, country);
187+
validate();
188+
return new Address(person, streets, city);
120189
}
121190
}
122191
}
123192
```
124193

194+
<!-- Plugin description end -->
195+
125196
## Installation
126197

127198
1. Download plugin zip file from [Releases](https://github.com/junkfactory/java-inner-builder/releases)

src/main/java/com/github/junkfactory/innerbuilder/InnerBuilderAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import org.jetbrains.annotations.NotNull;
99

1010
public class InnerBuilderAction extends BaseCodeInsightAction {
11-
private final JavaInnerBuilderHandler handler = new JavaInnerBuilderHandler();
11+
private static final JavaInnerBuilderHandler handler = new JavaInnerBuilderHandler();
1212

1313
@NotNull
1414
@Override

src/main/java/com/github/junkfactory/innerbuilder/JavaInnerBuilderHandler.java

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package com.github.junkfactory.innerbuilder;
22

3+
import com.github.junkfactory.innerbuilder.generators.GeneratorFactory;
4+
import com.github.junkfactory.innerbuilder.generators.GeneratorParams;
5+
import com.github.junkfactory.innerbuilder.generators.PsiParams;
6+
import com.github.junkfactory.innerbuilder.generators.Utils;
37
import com.github.junkfactory.innerbuilder.ui.JavaInnerBuilderOption;
48
import com.intellij.ide.util.PropertiesComponent;
59
import com.intellij.lang.LanguageCodeInsightActionHandler;
@@ -17,10 +21,13 @@
1721
import java.util.EnumSet;
1822
import java.util.Set;
1923

20-
import static com.github.junkfactory.innerbuilder.FieldCollector.collectFields;
24+
import static com.github.junkfactory.innerbuilder.generators.FieldCollector.collectFields;
2125
import static com.github.junkfactory.innerbuilder.ui.JavaInnerBuilderOptionSelector.selectFieldsAndOptions;
2226

23-
public class JavaInnerBuilderHandler implements LanguageCodeInsightActionHandler {
27+
class JavaInnerBuilderHandler implements LanguageCodeInsightActionHandler {
28+
29+
private static final GeneratorFactory generatorFactory = GeneratorFactory.create();
30+
2431
@Override
2532
public boolean isValidFor(final Editor editor, final PsiFile file) {
2633
if (!(file instanceof PsiJavaFile)) {
@@ -64,25 +71,28 @@ public void invoke(@NotNull final Project project, @NotNull final Editor editor,
6471
}
6572

6673
var existingFields = collectFields(file, editor);
67-
if (!existingFields.isEmpty()) {
68-
var selectedFields = selectFieldsAndOptions(existingFields, project);
69-
if (selectedFields.isEmpty()) {
70-
return;
71-
}
72-
var psiParams = PsiParams.builder()
73-
.file(file)
74-
.selectedFields(selectedFields)
75-
.factory(JavaPsiFacade.getElementFactory(project))
76-
.build();
77-
var generatorParams = GeneratorParams.builder()
78-
.project(project)
79-
.editor(editor)
80-
.psi(psiParams)
81-
.options(currentOptions())
82-
.build();
83-
var builderGenerator = new InnerBuilderGenerator(generatorParams);
84-
ApplicationManager.getApplication().runWriteAction(builderGenerator);
74+
if (existingFields.isEmpty()) {
75+
return;
8576
}
77+
78+
var selectedFields = selectFieldsAndOptions(existingFields, project);
79+
if (selectedFields.isEmpty()) {
80+
return;
81+
}
82+
83+
var psiParams = PsiParams.builder()
84+
.file(file)
85+
.selectedFields(selectedFields)
86+
.factory(JavaPsiFacade.getElementFactory(project))
87+
.build();
88+
var generatorParams = GeneratorParams.builder()
89+
.project(project)
90+
.editor(editor)
91+
.psi(psiParams)
92+
.options(currentOptions())
93+
.build();
94+
var builderGenerator = generatorFactory.createInnerBuilderGenerator(generatorParams);
95+
ApplicationManager.getApplication().runWriteAction(builderGenerator);
8696
}
8797

8898
private Set<JavaInnerBuilderOption> currentOptions() {

src/main/java/com/github/junkfactory/innerbuilder/AbstractGenerator.java renamed to src/main/java/com/github/junkfactory/innerbuilder/generators/AbstractGenerator.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.github.junkfactory.innerbuilder;
1+
package com.github.junkfactory.innerbuilder.generators;
22

33
import com.intellij.psi.PsiClass;
44
import com.intellij.psi.PsiElement;
@@ -10,15 +10,17 @@
1010
abstract class AbstractGenerator implements Runnable {
1111

1212
@NonNls
13-
protected static final String BUILDER_CLASS_NAME = "Builder";
13+
static final String BUILDER_CLASS_NAME = "Builder";
1414
@NonNls
15-
protected static final String BUILDER_METHOD_NAME = "builder";
15+
static final String BUILDER_METHOD_NAME = "builder";
1616
@NonNls
17-
protected static final String TO_BUILDER_NAME = "toBuilder";
17+
static final String TO_BUILDER_NAME = "toBuilder";
1818

19-
protected GeneratorParams generatorParams;
19+
protected final GeneratorFactory generatorFactory;
20+
protected final GeneratorParams generatorParams;
2021

21-
protected AbstractGenerator(GeneratorParams generatorParams) {
22+
protected AbstractGenerator(GeneratorFactory generatorFactory, GeneratorParams generatorParams) {
23+
this.generatorFactory = generatorFactory;
2224
this.generatorParams = generatorParams;
2325
}
2426

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.github.junkfactory.innerbuilder.generators;
2+
3+
import com.intellij.psi.PsiMethod;
4+
import com.intellij.psi.PsiModifier;
5+
import com.intellij.psi.util.PsiUtil;
6+
7+
class BuilderClassGenerator extends AbstractGenerator {
8+
9+
private final BuilderClassParams builderClassParams;
10+
private final Runnable fieldsGenerator;
11+
private final Runnable methodsGenerator;
12+
13+
BuilderClassGenerator(GeneratorFactory generatorFactory,
14+
GeneratorParams generatorParams,
15+
BuilderClassParams builderClassParams) {
16+
super(generatorFactory, generatorParams);
17+
this.builderClassParams = builderClassParams;
18+
this.fieldsGenerator = generatorFactory.createBuilderFieldsGenerator(generatorParams, builderClassParams);
19+
this.methodsGenerator = generatorFactory.createBuilderMethodsGenerator(generatorParams, builderClassParams);
20+
}
21+
22+
@Override
23+
public void run() {
24+
//builder constructor
25+
var builderClass = builderClassParams.builderClass();
26+
var builderConstructor = generateBuilderConstructor();
27+
addMethod(builderClass, null, builderConstructor, false);
28+
29+
fieldsGenerator.run();
30+
methodsGenerator.run();
31+
}
32+
33+
private PsiMethod generateBuilderConstructor() {
34+
var builderConstructor = generatorParams.psi().factory().createConstructor(BUILDER_CLASS_NAME);
35+
PsiUtil.setModifierProperty(builderConstructor, PsiModifier.PRIVATE, true);
36+
return builderConstructor;
37+
}
38+
39+
}

0 commit comments

Comments
 (0)