Skip to content

Commit b4f8821

Browse files
authored
Enhancements (#8)
* Handle immutables in detecting addTo method * Add putTo map (or any class with a put(x,y) method
1 parent 788c866 commit b4f8821

File tree

2 files changed

+78
-23
lines changed

2 files changed

+78
-23
lines changed

src/main/java/com/github/junkfactory/innerbuilder/generators/BuilderMethodsGenerator.java

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22

33
import com.github.junkfactory.innerbuilder.ui.JavaInnerBuilderOption;
44
import com.intellij.openapi.util.text.StringUtil;
5-
import com.intellij.psi.PsiClass;
65
import com.intellij.psi.PsiElement;
76
import com.intellij.psi.PsiField;
87
import com.intellij.psi.PsiMethod;
98
import com.intellij.psi.PsiModifier;
109
import com.intellij.psi.util.PsiUtil;
1110

1211
import java.util.Objects;
13-
import java.util.Optional;
1412
import java.util.stream.Collectors;
1513

1614
class BuilderMethodsGenerator extends AbstractGenerator implements MethodsGenerator {
@@ -56,32 +54,42 @@ private PsiMethod generateValidateMethod() {
5654
}
5755

5856
private PsiMethod generateFieldMethod(PsiField field) {
59-
var addMethod = field.hasInitializer() ? findAddMethod(field) : null;
57+
var addMethod = field.hasInitializer() ? Utils.findAddMethod(field) : null;
6058
if (null != addMethod) {
6159
return generateAddToCollection(field, addMethod);
6260
}
61+
62+
var putMethod = field.hasInitializer() ? Utils.findPutMethod(field) : null;
63+
if (null != putMethod) {
64+
return generatePutToMap(field, putMethod);
65+
}
66+
6367
return generateBuilderSetter(field);
6468
}
6569

66-
private PsiMethod findAddMethod(PsiField field) {
67-
var fieldClass = PsiUtil.resolveClassInClassTypeOnly(field.getType());
68-
var methods = Optional.ofNullable(fieldClass)
69-
.map(PsiClass::getAllMethods)
70-
.orElseGet(() -> new PsiMethod[0]);
71-
for (var method : methods) {
72-
if (method.getName().equals("add") && method.getParameterList().getParametersCount() == 1) {
73-
return method;
74-
}
75-
}
76-
return null;
70+
private PsiMethod generatePutToMap(PsiField field, PsiMethod fieldPutMethod) {
71+
//resolve the generic type of the map via the parameter type of the put method
72+
var param1 = Objects.requireNonNull(fieldPutMethod.getParameterList().getParameter(0));
73+
var param1Type = Utils.resolveGenericParameterType(field.getType(), param1);
74+
var param2 = Objects.requireNonNull(fieldPutMethod.getParameterList().getParameter(1));
75+
var param2Type = Utils.resolveGenericParameterType(field.getType(), param2);
76+
77+
//now build the put method
78+
var methodName = "putTo" + StringUtil.capitalize(field.getName());
79+
var methodText = """
80+
public %s %s(%s key, %s value) {
81+
this.%s.put(key, value);
82+
return this;
83+
}""".formatted(BUILDER_CLASS_NAME, methodName, param1Type.getPresentableText(),
84+
param2Type.getPresentableText(), field.getName());
85+
var psiElementFactory = generatorParams.psi().factory();
86+
return psiElementFactory.createMethodFromText(methodText, field);
7787
}
7888

7989
private PsiMethod generateAddToCollection(PsiField field, PsiMethod fieldAddMethod) {
8090
//resolve the generic type of the collection via the parameter type of the add method
8191
var param = Objects.requireNonNull(fieldAddMethod.getParameterList().getParameter(0));
82-
var paramType = PsiUtil.resolveGenericsClassInType(field.getType())
83-
.getSubstitutor()
84-
.substitute(param.getType());
92+
var paramType = Utils.resolveGenericParameterType(field.getType(), param);
8593

8694
//now build the add method
8795
var methodName = "addTo" + StringUtil.capitalize(field.getName());

src/main/java/com/github/junkfactory/innerbuilder/generators/Utils.java

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22

33
import com.intellij.openapi.editor.Editor;
44
import com.intellij.psi.PsiClass;
5-
import com.intellij.psi.PsiElement;
6-
import com.intellij.psi.PsiElementFactory;
5+
import com.intellij.psi.PsiField;
76
import com.intellij.psi.PsiFile;
7+
import com.intellij.psi.PsiMethod;
88
import com.intellij.psi.PsiModifier;
9+
import com.intellij.psi.PsiParameter;
910
import com.intellij.psi.PsiParameterList;
10-
import com.intellij.psi.PsiStatement;
1111
import com.intellij.psi.PsiType;
1212
import com.intellij.psi.util.PsiTreeUtil;
1313
import com.intellij.psi.util.PsiUtil;
1414
import org.jetbrains.annotations.NonNls;
15-
import org.jetbrains.annotations.NotNull;
1615
import org.jetbrains.annotations.Nullable;
1716

17+
import java.util.Optional;
18+
1819
public class Utils {
1920
@NonNls
2021
static final String JAVA_DOT_LANG = "java.lang.";
@@ -84,8 +85,54 @@ public static PsiClass getStaticOrTopLevelClass(PsiFile file, Editor editor) {
8485
}
8586
}
8687

87-
static PsiStatement createReturnThis(@NotNull PsiElementFactory psiElementFactory, @Nullable PsiElement context) {
88-
return psiElementFactory.createStatementFromText("return this;", context);
88+
89+
@Nullable
90+
public static PsiMethod findAddMethod(PsiField field) {
91+
return findMethod(field, "add", 1);
92+
}
93+
94+
@Nullable
95+
public static PsiMethod findPutMethod(PsiField field) {
96+
return findMethod(field, "put", 2);
97+
}
98+
99+
@Nullable
100+
public static PsiMethod findMethod(PsiField field, String methodName, int parameterCount) {
101+
if (isFieldInitializedWithImmutableInstance(field)) {
102+
return null;
103+
}
104+
var fieldClass = PsiUtil.resolveClassInClassTypeOnly(field.getType());
105+
var methods = Optional.ofNullable(fieldClass)
106+
.map(PsiClass::getAllMethods)
107+
.orElseGet(() -> new PsiMethod[0]);
108+
for (var method : methods) {
109+
if (method.getName().equals(methodName) &&
110+
method.getParameterList().getParametersCount() == parameterCount) {
111+
return method;
112+
}
113+
}
114+
return null;
115+
}
116+
117+
public static PsiType resolveGenericParameterType(PsiType fieldType, PsiParameter param) {
118+
//resolve the generic type of the collection via the parameter type of the add method
119+
return PsiUtil.resolveGenericsClassInType(fieldType)
120+
.getSubstitutor()
121+
.substitute(param.getType());
89122
}
90123

124+
public static boolean isFieldInitializedWithImmutableInstance(PsiField field) {
125+
var initializer = field.getInitializer();
126+
if (null == initializer) {
127+
return false;
128+
}
129+
var initializerType = initializer.getType();
130+
if (null == initializerType) {
131+
return false;
132+
}
133+
var initializerClass = PsiUtil.resolveClassInClassTypeOnly(initializerType);
134+
return null != initializerClass && initializerClass.hasModifierProperty(PsiModifier.ABSTRACT);
135+
}
136+
137+
91138
}

0 commit comments

Comments
 (0)