Skip to content

Commit

Permalink
work on Lombok 1.16.8 features #192
Browse files Browse the repository at this point in the history
improve generation of build method code block
  • Loading branch information
Michail Plushnikov committed Jun 11, 2016
1 parent f203be7 commit 890fb0f
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 23 deletions.
Expand Up @@ -339,7 +339,7 @@ private String createHashcodeBlockString(@NotNull PsiClass psiClass, @NotNull Ps
} }
} else { } else {
builder.append("final java.lang.Object $").append(fieldName).append(" = this.").append(fieldAccessor).append(";\n"); builder.append("final java.lang.Object $").append(fieldName).append(" = this.").append(fieldAccessor).append(";\n");
builder.append("result = result * PRIME + ($").append(fieldName).append(" == null ? 0 : $").append(fieldName).append(".hashCode());\n"); builder.append("result = result * PRIME + ($").append(fieldName).append(" == null ? 43 : $").append(fieldName).append(".hashCode());\n");
} }
} }
builder.append("return result;\n"); builder.append("return result;\n");
Expand Down
Expand Up @@ -246,7 +246,8 @@ protected Collection<PsiMethod> createConstructorMethod(@NotNull PsiClass psiCla
return Collections.singletonList(constructor); return Collections.singletonList(constructor);
} }


private PsiMethod createConstructor(@NotNull PsiClass psiClass, @PsiModifier.ModifierConstant @NotNull String modifier, boolean suppressConstructorProperties, boolean useJavaDefaults, @NotNull Collection<PsiField> params, @NotNull PsiAnnotation psiAnnotation) { private PsiMethod createConstructor(@NotNull PsiClass psiClass, @PsiModifier.ModifierConstant @NotNull String modifier, boolean suppressConstructorProperties,
boolean useJavaDefaults, @NotNull Collection<PsiField> params, @NotNull PsiAnnotation psiAnnotation) {
LombokLightMethodBuilder constructor = new LombokLightMethodBuilder(psiClass.getManager(), getConstructorName(psiClass)) LombokLightMethodBuilder constructor = new LombokLightMethodBuilder(psiClass.getManager(), getConstructorName(psiClass))
.withConstructor(true) .withConstructor(true)
.withContainingClass(psiClass) .withContainingClass(psiClass)
Expand Down
@@ -0,0 +1,25 @@
package de.plushnikov.intellij.plugin.processor.handler.singular;

import com.intellij.psi.CommonClassNames;

interface SingularCollectionClassNames {
String GUAVA_IMMUTABLE_COLLECTION = "com.google.common.collect.ImmutableCollection";
String GUAVA_IMMUTABLE_LIST = "com.google.common.collect.ImmutableList";
String GUAVA_IMMUTABLE_SET = "com.google.common.collect.ImmutableSet";
String GUAVA_IMMUTABLE_SORTED_SET = "com.google.common.collect.ImmutableSortedSet";
String GUAVA_IMMUTABLE_MAP = "com.google.common.collect.ImmutableMap";
String GUAVA_IMMUTABLE_TABLE = "com.google.common.collect.ImmutableTable";
String GUAVA_IMMUTABLE_BI_MAP = "com.google.common.collect.ImmutableBiMap";
String GUAVA_IMMUTABLE_SORTED_MAP = "com.google.common.collect.ImmutableSortedMap";

String JAVA_LANG_ITERABLE = CommonClassNames.JAVA_LANG_ITERABLE;
String JAVA_UTIL_COLLECTION = CommonClassNames.JAVA_UTIL_COLLECTION;
String JAVA_UTIL_LIST = CommonClassNames.JAVA_UTIL_LIST;

String JAVA_UTIL_MAP = CommonClassNames.JAVA_UTIL_MAP;
String JAVA_UTIL_SORTED_MAP = "java.util.SortedMap";
String JAVA_UTIL_NAVIGABLE_MAP = "java.util.NavigableMap";

String JAVA_UTIL_SORTED_SET = "java.util.SortedSet";
String JAVA_UTIL_NAVIGABLE_SET = "java.util.NavigableSet";
}
Expand Up @@ -14,18 +14,21 @@
class SingularGuavaCollectionHandler extends SingularCollectionHandler { class SingularGuavaCollectionHandler extends SingularCollectionHandler {


private final boolean sortedCollection; private final boolean sortedCollection;
private final String typeCollectionQualifiedName;


SingularGuavaCollectionHandler(String collectionQualifiedName, boolean sortedCollection, boolean shouldGenerateFullBodyBlock) { SingularGuavaCollectionHandler(String collectionQualifiedName, boolean sortedCollection, boolean shouldGenerateFullBodyBlock) {
super(collectionQualifiedName, shouldGenerateFullBodyBlock); super(collectionQualifiedName, shouldGenerateFullBodyBlock);
this.sortedCollection = sortedCollection; this.sortedCollection = sortedCollection;
this.typeCollectionQualifiedName = SingularCollectionClassNames.GUAVA_IMMUTABLE_COLLECTION.equals(collectionQualifiedName)
? SingularCollectionClassNames.GUAVA_IMMUTABLE_LIST : collectionQualifiedName;
} }


@NotNull @NotNull
protected PsiType getBuilderFieldType(@NotNull PsiType psiFieldType, @NotNull Project project) { protected PsiType getBuilderFieldType(@NotNull PsiType psiFieldType, @NotNull Project project) {
final PsiManager psiManager = PsiManager.getInstance(project); final PsiManager psiManager = PsiManager.getInstance(project);
final PsiType elementType = PsiTypeUtil.extractOneElementType(psiFieldType, psiManager); final PsiType elementType = PsiTypeUtil.extractOneElementType(psiFieldType, psiManager);


return PsiTypeUtil.createCollectionType(psiManager, collectionQualifiedName + ".Builder", elementType); return PsiTypeUtil.createCollectionType(psiManager, typeCollectionQualifiedName + ".Builder", elementType);
} }


protected void addAllMethodParameter(@NotNull LombokLightMethodBuilder methodBuilder, @NotNull PsiType psiFieldType, @NotNull String singularName) { protected void addAllMethodParameter(@NotNull LombokLightMethodBuilder methodBuilder, @NotNull PsiType psiFieldType, @NotNull String singularName) {
Expand All @@ -46,15 +49,15 @@ protected String getOneMethodBody(@NotNull String singularName, @NotNull String
final String codeBlockTemplate = "if (this.{0} == null) this.{0} = {2}.{3}; \n" + final String codeBlockTemplate = "if (this.{0} == null) this.{0} = {2}.{3}; \n" +
"this.{0}.add({1});{4}"; "this.{0}.add({1});{4}";


return MessageFormat.format(codeBlockTemplate, psiFieldName, singularName, collectionQualifiedName, return MessageFormat.format(codeBlockTemplate, psiFieldName, singularName, typeCollectionQualifiedName,
sortedCollection ? "naturalOrder()" : "builder()", fluentBuilder ? "\nreturn this;" : ""); sortedCollection ? "naturalOrder()" : "builder()", fluentBuilder ? "\nreturn this;" : "");
} }


protected String getAllMethodBody(@NotNull String singularName, @NotNull PsiType psiFieldType, @NotNull PsiManager psiManager, boolean fluentBuilder) { protected String getAllMethodBody(@NotNull String singularName, @NotNull PsiType psiFieldType, @NotNull PsiManager psiManager, boolean fluentBuilder) {
final String codeBlockTemplate = "if (this.{0} == null) this.{0} = {1}.{2}; \n" final String codeBlockTemplate = "if (this.{0} == null) this.{0} = {1}.{2}; \n"
+ "this.{0}.addAll({0});{3}"; + "this.{0}.addAll({0});{3}";


return MessageFormat.format(codeBlockTemplate, singularName, collectionQualifiedName, return MessageFormat.format(codeBlockTemplate, singularName, typeCollectionQualifiedName,
sortedCollection ? "naturalOrder()" : "builder()", fluentBuilder ? "\nreturn this;" : ""); sortedCollection ? "naturalOrder()" : "builder()", fluentBuilder ? "\nreturn this;" : "");
} }


Expand All @@ -64,12 +67,11 @@ public void appendBuildPrepare(@NotNull StringBuilder buildMethodCode, @NotNull
final PsiType psiFieldType = psiVariable.getType(); final PsiType psiFieldType = psiVariable.getType();


final PsiType elementType = PsiTypeUtil.extractOneElementType(psiFieldType, psiManager); final PsiType elementType = PsiTypeUtil.extractOneElementType(psiFieldType, psiManager);

buildMethodCode.append(MessageFormat.format( buildMethodCode.append(MessageFormat.format(
"{2}<{1}> {0} = " + "{2}<{1}> {0} = " +
"this.{0} == null ? " + "this.{0} == null ? " +
"{2}.<{1}>of() : " + "{3}.<{1}>of() : " +
"this.{0}.build();\n", "this.{0}.build();\n",
fieldName, elementType.getCanonicalText(false), collectionQualifiedName)); fieldName, elementType.getCanonicalText(false), collectionQualifiedName, typeCollectionQualifiedName));
} }
} }
Expand Up @@ -14,20 +14,15 @@


public class SingularHandlerFactory { public class SingularHandlerFactory {


private static final String JAVA_LANG_ITERABLE = CommonClassNames.JAVA_LANG_ITERABLE; private static final String[] JAVA_MAPS = new String[]{CommonClassNames.JAVA_UTIL_MAP, SingularCollectionClassNames.JAVA_UTIL_SORTED_MAP, SingularCollectionClassNames.JAVA_UTIL_NAVIGABLE_MAP,};
private static final String JAVA_UTIL_COLLECTION = CommonClassNames.JAVA_UTIL_COLLECTION; private static final String[] JAVA_SETS = new String[]{CommonClassNames.JAVA_UTIL_SET, SingularCollectionClassNames.JAVA_UTIL_SORTED_SET, SingularCollectionClassNames.JAVA_UTIL_NAVIGABLE_SET};
private static final String JAVA_UTIL_LIST = CommonClassNames.JAVA_UTIL_LIST; private static final String[] GUAVE_COLLECTIONS = new String[]{SingularCollectionClassNames.GUAVA_IMMUTABLE_COLLECTION, SingularCollectionClassNames.GUAVA_IMMUTABLE_LIST};
private static final String[] JAVA_MAPS = new String[]{CommonClassNames.JAVA_UTIL_MAP, "java.util.SortedMap", "java.util.NavigableMap",}; private static final String[] GUAVA_SETS = new String[]{SingularCollectionClassNames.GUAVA_IMMUTABLE_SET, SingularCollectionClassNames.GUAVA_IMMUTABLE_SORTED_SET};
private static final String[] JAVA_SETS = new String[]{CommonClassNames.JAVA_UTIL_SET, "java.util.SortedSet", "java.util.NavigableSet"}; private static final String[] GUAVA_MAPS = new String[]{SingularCollectionClassNames.GUAVA_IMMUTABLE_MAP, SingularCollectionClassNames.GUAVA_IMMUTABLE_BI_MAP, SingularCollectionClassNames.GUAVA_IMMUTABLE_SORTED_MAP};
private static final String GUAVA_IMMUTABLE_COLLECTION = "com.google.common.collect.ImmutableCollection"; private static final String[] GUAVA_TABLE = new String[]{SingularCollectionClassNames.GUAVA_IMMUTABLE_TABLE};
private static final String GUAVA_IMMUTABLE_LIST = "com.google.common.collect.ImmutableList";
private static final String[] GUAVE_COLLECTIONS = new String[]{GUAVA_IMMUTABLE_COLLECTION, GUAVA_IMMUTABLE_LIST};
private static final String[] GUAVA_SETS = new String[]{"com.google.common.collect.ImmutableSet", "com.google.common.collect.ImmutableSortedSet"};
private static final String[] GUAVA_MAPS = new String[]{"com.google.common.collect.ImmutableMap", "com.google.common.collect.ImmutableBiMap", "com.google.common.collect.ImmutableSortedMap"};
private static final String[] GUAVA_TABLE = new String[]{"com.google.common.collect.ImmutableTable"};


private static final Set<String> COLLECTION_TYPES = new HashSet<String>() {{ private static final Set<String> COLLECTION_TYPES = new HashSet<String>() {{
addAll(toSet(JAVA_LANG_ITERABLE, JAVA_UTIL_COLLECTION, JAVA_UTIL_LIST)); addAll(toSet(SingularCollectionClassNames.JAVA_LANG_ITERABLE, SingularCollectionClassNames.JAVA_UTIL_COLLECTION, SingularCollectionClassNames.JAVA_UTIL_LIST));
addAll(toSet(JAVA_SETS)); addAll(toSet(JAVA_SETS));
}}; }};


Expand Down Expand Up @@ -77,8 +72,7 @@ public static BuilderElementHandler getHandlerFor(@NotNull PsiVariable psiVariab
return new SingularMapHandler(qualifiedName, shouldGenerateFullBodyBlock); return new SingularMapHandler(qualifiedName, shouldGenerateFullBodyBlock);
} }
if (GUAVA_COLLECTION_TYPES.contains(qualifiedName)) { if (GUAVA_COLLECTION_TYPES.contains(qualifiedName)) {
String qualifiedName2Use = GUAVA_IMMUTABLE_COLLECTION.equals(qualifiedName) ? GUAVA_IMMUTABLE_LIST : qualifiedName; return new SingularGuavaCollectionHandler(qualifiedName, qualifiedName.contains("Sorted"), shouldGenerateFullBodyBlock);
return new SingularGuavaCollectionHandler(qualifiedName2Use, qualifiedName.contains("Sorted"), shouldGenerateFullBodyBlock);
} }
if (GUAVA_MAP_TYPES.contains(qualifiedName)) { if (GUAVA_MAP_TYPES.contains(qualifiedName)) {
return new SingularGuavaMapHandler(qualifiedName, qualifiedName.contains("Sorted"), shouldGenerateFullBodyBlock); return new SingularGuavaMapHandler(qualifiedName, qualifiedName.contains("Sorted"), shouldGenerateFullBodyBlock);
Expand Down
Expand Up @@ -105,7 +105,7 @@ protected String getAllMethodBody(@NotNull String singularName, @NotNull PsiType
"this.{0}" + LOMBOK_KEY + " = new java.util.ArrayList<{2}>(); \n" + "this.{0}" + LOMBOK_KEY + " = new java.util.ArrayList<{2}>(); \n" +
"this.{0}" + LOMBOK_VALUE + " = new java.util.ArrayList<{3}>(); \n" + "this.{0}" + LOMBOK_VALUE + " = new java.util.ArrayList<{3}>(); \n" +
"'}' \n" + "'}' \n" +
"for (java.util.Map.Entry<{4},{5}> $lombokEntry : {0}.entrySet()) '{'\n" + "for (final java.util.Map.Entry<{4},{5}> $lombokEntry : {0}.entrySet()) '{'\n" +
"this.{0}" + LOMBOK_KEY + ".add($lombokEntry.getKey());\n" + "this.{0}" + LOMBOK_KEY + ".add($lombokEntry.getKey());\n" +
"this.{0}" + LOMBOK_VALUE + ".add($lombokEntry.getValue());\n" + "this.{0}" + LOMBOK_VALUE + ".add($lombokEntry.getValue());\n" +
"'}'{1}"; "'}'{1}";
Expand All @@ -120,4 +120,40 @@ protected String getAllMethodBody(@NotNull String singularName, @NotNull PsiType
keyType.getCanonicalText(false), valueType.getCanonicalText(false), keyType.getCanonicalText(false), valueType.getCanonicalText(false),
keyIterType.getCanonicalText(false), valueIterType.getCanonicalText(false)); keyIterType.getCanonicalText(false), valueIterType.getCanonicalText(false));
} }

@Override
public void appendBuildPrepare(@NotNull StringBuilder buildMethodCode, @NotNull PsiVariable psiVariable, @NotNull String fieldName) {
final PsiManager psiManager = psiVariable.getManager();
final PsiType psiFieldType = psiVariable.getType();
final PsiType keyType = PsiTypeUtil.extractOneElementType(psiFieldType, psiManager, CommonClassNames.JAVA_UTIL_MAP, 0);
final PsiType valueType = PsiTypeUtil.extractOneElementType(psiFieldType, psiManager, CommonClassNames.JAVA_UTIL_MAP, 1);

final String selectedFormat;
if (collectionQualifiedName.equals(SingularCollectionClassNames.JAVA_UTIL_SORTED_MAP)) {
selectedFormat = "java.util.SortedMap<{1}, {2}> {0} = new java.util.TreeMap<{1}, {2}>();\n" +
" if (this.{0}$key != null) for (int $i = 0; $i < (this.{0}$key == null ? 0 : this.{0}$key.size()); $i++) {0}.put(this.{0}$key.get($i), this.{0}$value.get($i));\n" +
" {0} = java.util.Collections.unmodifiableSortedMap({0});\n";
} else if (collectionQualifiedName.equals(SingularCollectionClassNames.JAVA_UTIL_NAVIGABLE_MAP)) {
selectedFormat = "java.util.NavigableMap<{1}, {2}> {0} = new java.util.TreeMap<{1}, {2}>();\n" +
" if (this.{0}$key != null) for (int $i = 0; $i < (this.{0}$key == null ? 0 : this.{0}$key.size()); $i++) {0}.put(this.{0}$key.get($i), this.{0}$value.get($i));\n" +
" {0} = java.util.Collections.unmodifiableNavigableMap({0});\n";
} else {
selectedFormat = "java.util.Map<{1}, {2}> {0};\n" +
" switch (this.{0}$key == null ? 0 : this.{0}$key.size()) '{'\n" +
" case 0:\n" +
" {0} = java.util.Collections.emptyMap();\n" +
" break;\n" +
" case 1:\n" +
" {0} = java.util.Collections.singletonMap(this.{0}$key.get(0), this.{0}$value.get(0));\n" +
" break;\n" +
" default:\n" +
" {0} = new java.util.LinkedHashMap<{1}, {2}>(this.{0}$key.size() < 1073741824 ? 1 + this.{0}$key.size() + (this.{0}$key.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);\n" +
" for (int $i = 0; $i < this.{0}$key.size(); $i++) {0}.put(this.{0}$key.get($i), this.{0}$value.get($i));\n" +
" {0} = java.util.Collections.unmodifiableMap({0});\n" +
" '}'\n";
}

buildMethodCode.append(MessageFormat.format(selectedFormat,
fieldName, keyType.getCanonicalText(false), valueType.getCanonicalText(false), collectionQualifiedName));
}
} }

0 comments on commit 890fb0f

Please sign in to comment.