From db8281f7f5c027c24cf9a1a8208a2aa92d06a73d Mon Sep 17 00:00:00 2001 From: spc Date: Sun, 4 Oct 2015 09:23:28 +0200 Subject: Added support for builder singular for Guavas ImmutableTable --- src/core/lombok/core/GuavaTypeMap.java | 17 +-- .../singulars/EclipseGuavaSetListSingularizer.java | 16 +-- .../singulars/EclipseGuavaSingularizer.java | 139 +++++++++++++-------- .../singulars/JavacGuavaSetListSingularizer.java | 22 ++-- .../handlers/singulars/JavacGuavaSingularizer.java | 119 +++++++++++------- 5 files changed, 192 insertions(+), 121 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/core/GuavaTypeMap.java b/src/core/lombok/core/GuavaTypeMap.java index 900d2b72..e84a32be 100644 --- a/src/core/lombok/core/GuavaTypeMap.java +++ b/src/core/lombok/core/GuavaTypeMap.java @@ -1,16 +1,16 @@ /* * Copyright (C) 2015 The Project Lombok Authors. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,7 +28,7 @@ import java.util.Map; public final class GuavaTypeMap { private static final Map TYPE_TO_GUAVA_TYPE; static { Map m = new HashMap(); - + m.put("java.util.NavigableSet", "ImmutableSortedSet"); m.put("java.util.NavigableMap", "ImmutableSortedMap"); m.put("java.util.SortedSet", "ImmutableSortedSet"); @@ -37,7 +37,7 @@ public final class GuavaTypeMap { m.put("java.util.Map", "ImmutableMap"); m.put("java.util.Collection", "ImmutableList"); m.put("java.util.List", "ImmutableList"); - + m.put("com.google.common.collect.ImmutableSet", "ImmutableSet"); m.put("com.google.common.collect.ImmutableSortedSet", "ImmutableSortedSet"); m.put("com.google.common.collect.ImmutableMap", "ImmutableMap"); @@ -45,14 +45,15 @@ public final class GuavaTypeMap { m.put("com.google.common.collect.ImmutableSortedMap", "ImmutableSortedMap"); m.put("com.google.common.collect.ImmutableList", "ImmutableList"); m.put("com.google.common.collect.ImmutableCollection", "ImmutableList"); - + m.put("com.google.common.collect.ImmutableTable", "ImmutableTable"); + TYPE_TO_GUAVA_TYPE = Collections.unmodifiableMap(m); } - + public static String getGuavaTypeName(String fqn) { String target = TYPE_TO_GUAVA_TYPE.get(fqn); return target != null ? target : "ImmutableList"; } - + private GuavaTypeMap() {} } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java index bc2893bf..e2ca1270 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java @@ -1,16 +1,16 @@ /* * Copyright (C) 2015 The Project Lombok Authors. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,15 +28,15 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; @ProviderFor(EclipseSingularizer.class) public class EclipseGuavaSetListSingularizer extends EclipseGuavaSingularizer { - // TODO com.google.common.collect.ImmutableTable // TODO com.google.common.collect.ImmutableRangeSet // TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset @Override public LombokImmutableList getSupportedTypes() { return LombokImmutableList.of( - "com.google.common.collect.ImmutableCollection", - "com.google.common.collect.ImmutableList", - "com.google.common.collect.ImmutableSet", - "com.google.common.collect.ImmutableSortedSet"); + "com.google.common.collect.ImmutableCollection", + "com.google.common.collect.ImmutableList", + "com.google.common.collect.ImmutableSet", + "com.google.common.collect.ImmutableSortedSet", + "com.google.common.collect.ImmutableTable"); } @Override protected boolean isMap() { diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index fa121328..c3a4c314 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -1,16 +1,16 @@ /* * Copyright (C) 2015 The Project Lombok Authors. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -28,12 +28,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import lombok.core.GuavaTypeMap; -import lombok.core.handlers.HandlerUtil; -import lombok.eclipse.EclipseNode; -import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; -import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; - import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; @@ -59,23 +53,32 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import lombok.core.GuavaTypeMap; +import lombok.core.handlers.HandlerUtil; +import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; +import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; + abstract class EclipseGuavaSingularizer extends EclipseSingularizer { protected static final char[][] JAVA_UTIL_MAP = { {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'} }; - + protected static final char[][] GUAVA_COLLECT_TABLE = { + {'c', 'o', 'm'}, {'g', 'o', 'o', 'g', 'l', 'e'}, {'c', 'o', 'm', 'm', 'o', 'n'}, {'c', 'o', 'l', 'l', 'e', 'c', 't'}, {'T', 'a', 'b', 'l', 'e'} + }; + protected String getSimpleTargetTypeName(SingularData data) { return GuavaTypeMap.getGuavaTypeName(data.getTargetFqn()); } - + protected char[] getBuilderMethodName(SingularData data) { String simpleTypeName = getSimpleTargetTypeName(data); if ("ImmutableSortedSet".equals(simpleTypeName) || "ImmutableSortedMap".equals(simpleTypeName)) return "naturalOrder".toCharArray(); return "builder".toCharArray(); } - + protected abstract boolean isMap(); - + protected char[][] makeGuavaTypeName(String simpleName, boolean addBuilder) { char[][] tokenizedName = new char[addBuilder ? 6 : 5][]; tokenizedName[0] = new char[] {'c', 'o', 'm'}; @@ -86,12 +89,13 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { if (addBuilder) tokenizedName[5] = new char[] { 'B', 'u', 'i', 'l', 'd', 'e', 'r'}; return tokenizedName; } - + @Override public List generateFields(SingularData data, EclipseNode builderType) { - char[][] tokenizedName = makeGuavaTypeName(getSimpleTargetTypeName(data), true); + String simpleTypeName = getSimpleTargetTypeName(data); + char[][] tokenizedName = makeGuavaTypeName(simpleTypeName, true); TypeReference type = new QualifiedTypeReference(tokenizedName, NULL_POSS); - type = addTypeArgs(isMap() ? 2 : 1, false, builderType, type, data.getTypeArgs()); - + type = addTypeArgs(getTypeAgrumentsCount(isMap(), simpleTypeName), false, builderType, type, data.getTypeArgs()); + FieldDeclaration buildField = new FieldDeclaration(data.getPluralName(), 0, -1); buildField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; buildField.modifiers = ClassFileConstants.AccPrivate; @@ -100,29 +104,29 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { data.setGeneratedByRecursive(buildField); return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - + @Override public void generateMethods(SingularData data, EclipseNode builderType, boolean fluent, boolean chain) { TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0); Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null; generateSingularMethod(returnType, returnStatement, data, builderType, fluent); - + returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0); returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null; generatePluralMethod(returnType, returnStatement, data, builderType, fluent); } - + void generateSingularMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { boolean mapMode = isMap(); char[] keyName = !mapMode ? data.getSingularName() : (new String(data.getSingularName()) + "$key").toCharArray(); char[] valueName = !mapMode ? null : (new String(data.getSingularName()) + "$value").toCharArray(); - + MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; md.modifiers = ClassFileConstants.AccPublic; - + List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType)); - + FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); MessageSend thisDotFieldDotAdd = new MessageSend(); @@ -134,11 +138,11 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { thisDotFieldDotAdd.arguments = new Expression[] {new SingleNameReference(keyName, 0L)}; } thisDotFieldDotAdd.receiver = thisDotField; - thisDotFieldDotAdd.selector = (mapMode ? "put" : "add").toCharArray(); + thisDotFieldDotAdd.selector = (shouldUsePut(data, mapMode) ? "put" : "add").toCharArray(); statements.add(thisDotFieldDotAdd); if (returnStatement != null) statements.add(returnStatement); md.statements = statements.toArray(new Statement[statements.size()]); - + if (mapMode) { TypeReference keyType = cloneParamType(0, data.getTypeArgs(), builderType); Argument keyParam = new Argument(keyName, 0, keyType, 0); @@ -146,68 +150,87 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { Argument valueParam = new Argument(valueName, 0, valueType, 0); md.arguments = new Argument[] {keyParam, valueParam}; } else { - TypeReference paramType = cloneParamType(0, data.getTypeArgs(), builderType); - Argument param = new Argument(keyName, 0, paramType, 0); + final Argument param; + + if (isSpecialTypeOfListSet(data)) { + char[][] cellTypeName = makeGuavaTypeName("Table", true); + cellTypeName[5] = new char[] { 'C', 'e', 'l', 'l' }; + TypeReference type = new QualifiedTypeReference(cellTypeName, NULL_POSS); + type = addTypeArgs(3, false, builderType, type, data.getTypeArgs()); + + param = new Argument(keyName, 0, type, 0); + } else { + TypeReference paramType = cloneParamType(0, data.getTypeArgs(), builderType); + param = new Argument(keyName, 0, paramType, 0); + } + md.arguments = new Argument[] {param}; } md.returnType = returnType; - md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(mapMode ? "put" : "add", new String(data.getSingularName())).toCharArray(); - + md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(shouldUsePut(data, mapMode) ? "put" : "add", new String(data.getSingularName())).toCharArray(); + data.setGeneratedByRecursive(md); injectMethod(builderType, md); } - + void generatePluralMethod(TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { boolean mapMode = isMap(); - + MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; md.modifiers = ClassFileConstants.AccPublic; - + List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType)); - + FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); MessageSend thisDotFieldDotAddAll = new MessageSend(); thisDotFieldDotAddAll.arguments = new Expression[] {new SingleNameReference(data.getPluralName(), 0L)}; thisDotFieldDotAddAll.receiver = thisDotField; - thisDotFieldDotAddAll.selector = (mapMode ? "putAll" : "addAll").toCharArray(); + thisDotFieldDotAddAll.selector = (shouldUsePut(data, mapMode) ? "putAll" : "addAll").toCharArray(); statements.add(thisDotFieldDotAddAll); if (returnStatement != null) statements.add(returnStatement); - + md.statements = statements.toArray(new Statement[statements.size()]); - + TypeReference paramType; if (mapMode) { paramType = new QualifiedTypeReference(JAVA_UTIL_MAP, NULL_POSS); paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs()); } else { - paramType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_ITERABLE, NULL_POSS); - paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs()); + if (isSpecialTypeOfListSet(data)) { + paramType = new QualifiedTypeReference(GUAVA_COLLECT_TABLE, NULL_POSS); + } else { + paramType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_ITERABLE, NULL_POSS); + } + + paramType = addTypeArgs(getListSetTypeArgumentsCount(getSimpleTargetTypeName(data)), true, builderType, paramType, data.getTypeArgs()); } Argument param = new Argument(data.getPluralName(), 0, paramType, 0); md.arguments = new Argument[] {param}; md.returnType = returnType; - md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(mapMode ? "putAll" : "addAll", new String(data.getPluralName())).toCharArray(); - + md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(shouldUsePut(data, mapMode) ? "putAll" : "addAll", new String(data.getPluralName())).toCharArray(); + data.setGeneratedByRecursive(md); injectMethod(builderType, md); } - + @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName) { boolean mapMode = isMap(); TypeReference varType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS); - varType = addTypeArgs(mapMode ? 2 : 1, false, builderType, varType, data.getTypeArgs()); - + String simpleTypeName = getSimpleTargetTypeName(data); + int agrumentsCount = getTypeAgrumentsCount(mapMode, simpleTypeName); + varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs()); + MessageSend emptyInvoke; { //ImmutableX.of() emptyInvoke = new MessageSend(); emptyInvoke.selector = new char[] {'o', 'f'}; - emptyInvoke.receiver = new QualifiedNameReference(makeGuavaTypeName(getSimpleTargetTypeName(data), false), NULL_POSS, 0, 0); - emptyInvoke.typeArguments = createTypeArgs(mapMode ? 2 : 1, false, builderType, data.getTypeArgs()); + emptyInvoke.receiver = new QualifiedNameReference(makeGuavaTypeName(simpleTypeName, false), NULL_POSS, 0, 0); + emptyInvoke.typeArguments = createTypeArgs(agrumentsCount, false, builderType, data.getTypeArgs()); } - + MessageSend invokeBuild; { //this.pluralName.build(); invokeBuild = new MessageSend(); @@ -216,32 +239,48 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { thisDotField.receiver = new ThisReference(0, 0); invokeBuild.receiver = thisDotField; } - + Expression isNull; { //this.pluralName == null FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); isNull = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL); } - + Expression init = new ConditionalExpression(isNull, emptyInvoke, invokeBuild); LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0); varDefStat.type = varType; varDefStat.initialization = init; statements.add(varDefStat); } - + protected Statement createConstructBuilderVarIfNeeded(SingularData data, EclipseNode builderType) { FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); FieldReference thisDotField2 = new FieldReference(data.getPluralName(), 0L); thisDotField2.receiver = new ThisReference(0, 0); Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL); - + MessageSend createBuilderInvoke = new MessageSend(); char[][] tokenizedName = makeGuavaTypeName(getSimpleTargetTypeName(data), false); createBuilderInvoke.receiver = new QualifiedNameReference(tokenizedName, NULL_POSS, 0, 0); createBuilderInvoke.selector = getBuilderMethodName(data); return new IfStatement(cond, new Assignment(thisDotField2, createBuilderInvoke, 0), 0, 0); } + + private int getTypeAgrumentsCount(boolean isMap, String simpleTypeName) { + return isMap ? 2 : getListSetTypeArgumentsCount(simpleTypeName); + } + + private int getListSetTypeArgumentsCount(String simpleTypeName) { + return "ImmutableTable".equals(simpleTypeName) ? 3 : 1; + } + + private boolean shouldUsePut(SingularData data, boolean mapMode) { + return mapMode || isSpecialTypeOfListSet(data); + } + + private boolean isSpecialTypeOfListSet(SingularData data) { + return "ImmutableTable".equals(getSimpleTargetTypeName(data)); + } } diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java index 2e404ca8..fe8e8dc0 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java @@ -1,16 +1,16 @@ /* * Copyright (C) 2015 The Project Lombok Authors. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -21,24 +21,24 @@ */ package lombok.javac.handlers.singulars; +import org.mangosdk.spi.ProviderFor; + import lombok.core.LombokImmutableList; import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; -import org.mangosdk.spi.ProviderFor; - @ProviderFor(JavacSingularizer.class) public class JavacGuavaSetListSingularizer extends JavacGuavaSingularizer { - // TODO com.google.common.collect.ImmutableTable // TODO com.google.common.collect.ImmutableRangeSet // TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset @Override public LombokImmutableList getSupportedTypes() { return LombokImmutableList.of( - "com.google.common.collect.ImmutableCollection", - "com.google.common.collect.ImmutableList", - "com.google.common.collect.ImmutableSet", - "com.google.common.collect.ImmutableSortedSet"); + "com.google.common.collect.ImmutableCollection", + "com.google.common.collect.ImmutableList", + "com.google.common.collect.ImmutableSet", + "com.google.common.collect.ImmutableSortedSet", + "com.google.common.collect.ImmutableTable"); } - + @Override protected boolean isMap() { return false; } diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java index 41e379f6..399f2239 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java @@ -1,16 +1,16 @@ /* * Copyright (C) 2015 The Project Lombok Authors. - * + * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: - * + * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. - * + * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -26,14 +26,6 @@ import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collections; -import lombok.core.GuavaTypeMap; -import lombok.core.handlers.HandlerUtil; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.javac.handlers.JavacHandlerUtil; -import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; -import lombok.javac.handlers.JavacSingularsRecipes.SingularData; - import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -47,51 +39,60 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; +import lombok.core.GuavaTypeMap; +import lombok.core.handlers.HandlerUtil; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.javac.handlers.JavacHandlerUtil; +import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; +import lombok.javac.handlers.JavacSingularsRecipes.SingularData; + abstract class JavacGuavaSingularizer extends JavacSingularizer { protected String getSimpleTargetTypeName(SingularData data) { return GuavaTypeMap.getGuavaTypeName(data.getTargetFqn()); } - + protected String getBuilderMethodName(SingularData data) { String simpleTypeName = getSimpleTargetTypeName(data); if ("ImmutableSortedSet".equals(simpleTypeName) || "ImmutableSortedMap".equals(simpleTypeName)) return "naturalOrder"; return "builder"; } - + protected abstract boolean isMap(); - + @Override public java.util.List generateFields(SingularData data, JavacNode builderType, JCTree source) { JavacTreeMaker maker = builderType.getTreeMaker(); - JCExpression type = JavacHandlerUtil.chainDots(builderType, "com", "google", "common", "collect", getSimpleTargetTypeName(data), "Builder"); - type = addTypeArgs(isMap() ? 2 : 1, false, builderType, type, data.getTypeArgs(), source); - + String simpleTypeName = getSimpleTargetTypeName(data); + JCExpression type = JavacHandlerUtil.chainDots(builderType, "com", "google", "common", "collect", simpleTypeName, "Builder"); + type = addTypeArgs(getTypeAgrumentsCount(isMap(), simpleTypeName), false, builderType, type, data.getTypeArgs(), source); + JCVariableDecl buildField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), data.getPluralName(), type, null); return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - + @Override public void generateMethods(SingularData data, JavacNode builderType, JCTree source, boolean fluent, boolean chain) { JavacTreeMaker maker = builderType.getTreeMaker(); JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; generateSingularMethod(maker, returnType, returnStatement, data, builderType, source, fluent); - + returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(maker, CTC_VOID)); returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null; generatePluralMethod(maker, returnType, returnStatement, data, builderType, source, fluent); } - + void generateSingularMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) { List typeParams = List.nil(); List thrown = List.nil(); boolean mapMode = isMap(); - + Name keyName = !mapMode ? data.getSingularName() : builderType.toName(data.getSingularName() + "$key"); Name valueName = !mapMode ? null : builderType.toName(data.getSingularName() + "$value"); - + JCModifiers mods = maker.Modifiers(Flags.PUBLIC); ListBuffer statements = new ListBuffer(); statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, mapMode, source)); - JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), mapMode ? "put" : "add"); + JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), shouldUsePut(data, mapMode) ? "put" : "add"); List invokeAddExpr; if (mapMode) { invokeAddExpr = List.of(maker.Ident(keyName), maker.Ident(valueName)); @@ -104,7 +105,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { JCBlock body = maker.Block(0, statements.toList()); Name methodName = data.getSingularName(); long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext()); - if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(mapMode ? "put" : "add", methodName.toString())); + if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(shouldUsePut(data, mapMode) ? "put" : "add", methodName.toString())); List params; if (mapMode) { JCExpression keyType = cloneParamType(0, maker, data.getTypeArgs(), builderType, source); @@ -113,82 +114,112 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { JCVariableDecl paramValue = maker.VarDef(maker.Modifiers(paramFlags), valueName, valueType, null); params = List.of(paramKey, paramValue); } else { - JCExpression paramType = cloneParamType(0, maker, data.getTypeArgs(), builderType, source); + final JCExpression paramType; + + if (isSpecialTypeOfListSet(data)) { + JCExpression cellType = JavacHandlerUtil.chainDots(builderType, "com", "google", "common", "collect", "Table", "Cell"); + paramType = addTypeArgs(3, false, builderType, cellType, data.getTypeArgs(), source); + } else { + paramType = cloneParamType(0, maker, data.getTypeArgs(), builderType, source); + } params = List.of(maker.VarDef(maker.Modifiers(paramFlags), data.getSingularName(), paramType, null)); } JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null); injectMethod(builderType, method); } - + protected void generatePluralMethod(JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) { List typeParams = List.nil(); List thrown = List.nil(); boolean mapMode = isMap(); - + JCModifiers mods = maker.Modifiers(Flags.PUBLIC); ListBuffer statements = new ListBuffer(); statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, mapMode, source)); - JCExpression thisDotFieldDotAddAll = chainDots(builderType, "this", data.getPluralName().toString(), mapMode ? "putAll" : "addAll"); + JCExpression thisDotFieldDotAddAll = chainDots(builderType, "this", data.getPluralName().toString(), shouldUsePut(data, mapMode) ? "putAll" : "addAll"); JCExpression invokeAddAll = maker.Apply(List.nil(), thisDotFieldDotAddAll, List.of(maker.Ident(data.getPluralName()))); statements.append(maker.Exec(invokeAddAll)); if (returnStatement != null) statements.append(returnStatement); JCBlock body = maker.Block(0, statements.toList()); Name methodName = data.getPluralName(); long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext()); - if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(mapMode ? "putAll" : "addAll", methodName.toString())); + if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(shouldUsePut(data, mapMode) ? "putAll" : "addAll", methodName.toString())); JCExpression paramType; if (mapMode) { paramType = chainDots(builderType, "java", "util", "Map"); } else { - paramType = genJavaLangTypeRef(builderType, "Iterable"); + if (isSpecialTypeOfListSet(data)) { + paramType = chainDots(builderType, "com", "google", "common", "collect", "Table"); + } else { + paramType = genJavaLangTypeRef(builderType, "Iterable"); + } } - paramType = addTypeArgs(mapMode ? 2 : 1, true, builderType, paramType, data.getTypeArgs(), source); + String simpleTypeName = getSimpleTargetTypeName(data); + paramType = addTypeArgs(getTypeAgrumentsCount(mapMode, simpleTypeName), true, builderType, paramType, data.getTypeArgs(), source); JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null); JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, List.of(param), thrown, body, null); injectMethod(builderType, method); } - + @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer statements, Name targetVariableName) { JavacTreeMaker maker = builderType.getTreeMaker(); List jceBlank = List.nil(); boolean mapMode = isMap(); - + + String simpleTypeName = getSimpleTargetTypeName(data); JCExpression varType = chainDotsString(builderType, data.getTargetFqn()); - varType = addTypeArgs(mapMode ? 2 : 1, false, builderType, varType, data.getTypeArgs(), source); - + int agrumentsCount = getTypeAgrumentsCount(mapMode, simpleTypeName); + varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs(), source); + JCExpression empty; { //ImmutableX.of() JCExpression emptyMethod = chainDots(builderType, "com", "google", "common", "collect", getSimpleTargetTypeName(data), "of"); - List invokeTypeArgs = createTypeArgs(mapMode ? 2 : 1, false, builderType, data.getTypeArgs(), source); + List invokeTypeArgs = createTypeArgs(agrumentsCount, false, builderType, data.getTypeArgs(), source); empty = maker.Apply(invokeTypeArgs, emptyMethod, jceBlank); } - + JCExpression invokeBuild; { //this.pluralName.build(); invokeBuild = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName().toString(), "build"), jceBlank); } - + JCExpression isNull; { //this.pluralName == null isNull = maker.Binary(CTC_EQUAL, maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()), maker.Literal(CTC_BOT, null)); } - + JCExpression init = maker.Conditional(isNull, empty, invokeBuild); // this.pluralName == null ? ImmutableX.of() : this.pluralName.build() - + JCStatement jcs = maker.VarDef(maker.Modifiers(0), data.getPluralName(), varType, init); statements.append(jcs); } - + protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, JCTree source) { List jceBlank = List.nil(); - + JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()); JCExpression thisDotField2 = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()); JCExpression cond = maker.Binary(CTC_EQUAL, thisDotField, maker.Literal(CTC_BOT, null)); - + JCExpression create = maker.Apply(jceBlank, chainDots(builderType, "com", "google", "common", "collect", getSimpleTargetTypeName(data), getBuilderMethodName(data)), jceBlank); JCStatement thenPart = maker.Exec(maker.Assign(thisDotField2, create)); - + return maker.If(cond, thenPart, null); } + + private int getTypeAgrumentsCount(boolean isMap, String simpleTypeName) { + return isMap ? 2 : getListSetTypeArgumentsCount(simpleTypeName); + } + + private int getListSetTypeArgumentsCount(String simpleTypeName) { + return "ImmutableTable".equals(simpleTypeName) ? 3 : 1; + } + + private boolean shouldUsePut(SingularData data, boolean mapMode) { + return mapMode || isSpecialTypeOfListSet(data); + } + + private boolean isSpecialTypeOfListSet(SingularData data) { + return "ImmutableTable".equals(getSimpleTargetTypeName(data)); + } } -- cgit From 22e1fb91d4699a0bacafcd9f74fdca6acd8b275b Mon Sep 17 00:00:00 2001 From: spc Date: Thu, 8 Oct 2015 17:23:42 +0200 Subject: Fixed typo, moved imports --- AUTHORS | 1 + .../singulars/EclipseGuavaSingularizer.java | 18 ++++++++-------- .../handlers/singulars/JavacGuavaSingularizer.java | 24 +++++++++++----------- 3 files changed, 22 insertions(+), 21 deletions(-) (limited to 'src/core') diff --git a/AUTHORS b/AUTHORS index d5e35ed5..f581aeea 100644 --- a/AUTHORS +++ b/AUTHORS @@ -12,6 +12,7 @@ Reinier Zwitserloot Robbert Jan Grootjans Roel Spilker Sander Koning +Szymon Pacanowski Taiki Sugawara By adding your name to this list, you grant full and irrevocable copyright and patent indemnity to Project Lombok and all use of Project Lombok, and you certify that you have the right to do so for all commits you add to Project Lombok. diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index c3a4c314..5a85bfa5 100644 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -28,6 +28,12 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import lombok.core.GuavaTypeMap; +import lombok.core.handlers.HandlerUtil; +import lombok.eclipse.EclipseNode; +import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; +import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; + import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; @@ -53,12 +59,6 @@ import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; -import lombok.core.GuavaTypeMap; -import lombok.core.handlers.HandlerUtil; -import lombok.eclipse.EclipseNode; -import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; -import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; - abstract class EclipseGuavaSingularizer extends EclipseSingularizer { protected static final char[][] JAVA_UTIL_MAP = { {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'} @@ -94,7 +94,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { String simpleTypeName = getSimpleTargetTypeName(data); char[][] tokenizedName = makeGuavaTypeName(simpleTypeName, true); TypeReference type = new QualifiedTypeReference(tokenizedName, NULL_POSS); - type = addTypeArgs(getTypeAgrumentsCount(isMap(), simpleTypeName), false, builderType, type, data.getTypeArgs()); + type = addTypeArgs(getTypeArgumentsCount(isMap(), simpleTypeName), false, builderType, type, data.getTypeArgs()); FieldDeclaration buildField = new FieldDeclaration(data.getPluralName(), 0, -1); buildField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -220,7 +220,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { boolean mapMode = isMap(); TypeReference varType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS); String simpleTypeName = getSimpleTargetTypeName(data); - int agrumentsCount = getTypeAgrumentsCount(mapMode, simpleTypeName); + int agrumentsCount = getTypeArgumentsCount(mapMode, simpleTypeName); varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs()); MessageSend emptyInvoke; { @@ -268,7 +268,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { return new IfStatement(cond, new Assignment(thisDotField2, createBuilderInvoke, 0), 0, 0); } - private int getTypeAgrumentsCount(boolean isMap, String simpleTypeName) { + private int getTypeArgumentsCount(boolean isMap, String simpleTypeName) { return isMap ? 2 : getListSetTypeArgumentsCount(simpleTypeName); } diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java index 399f2239..1bf47e6e 100644 --- a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java +++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java @@ -26,6 +26,14 @@ import static lombok.javac.handlers.JavacHandlerUtil.*; import java.util.Collections; +import lombok.core.GuavaTypeMap; +import lombok.core.handlers.HandlerUtil; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; +import lombok.javac.handlers.JavacHandlerUtil; +import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; +import lombok.javac.handlers.JavacSingularsRecipes.SingularData; + import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCBlock; @@ -39,14 +47,6 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; -import lombok.core.GuavaTypeMap; -import lombok.core.handlers.HandlerUtil; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; -import lombok.javac.handlers.JavacHandlerUtil; -import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer; -import lombok.javac.handlers.JavacSingularsRecipes.SingularData; - abstract class JavacGuavaSingularizer extends JavacSingularizer { protected String getSimpleTargetTypeName(SingularData data) { return GuavaTypeMap.getGuavaTypeName(data.getTargetFqn()); @@ -64,7 +64,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { JavacTreeMaker maker = builderType.getTreeMaker(); String simpleTypeName = getSimpleTargetTypeName(data); JCExpression type = JavacHandlerUtil.chainDots(builderType, "com", "google", "common", "collect", simpleTypeName, "Builder"); - type = addTypeArgs(getTypeAgrumentsCount(isMap(), simpleTypeName), false, builderType, type, data.getTypeArgs(), source); + type = addTypeArgs(getTypeArgumentsCount(isMap(), simpleTypeName), false, builderType, type, data.getTypeArgs(), source); JCVariableDecl buildField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), data.getPluralName(), type, null); return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); @@ -155,7 +155,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { } } String simpleTypeName = getSimpleTargetTypeName(data); - paramType = addTypeArgs(getTypeAgrumentsCount(mapMode, simpleTypeName), true, builderType, paramType, data.getTypeArgs(), source); + paramType = addTypeArgs(getTypeArgumentsCount(mapMode, simpleTypeName), true, builderType, paramType, data.getTypeArgs(), source); JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null); JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, List.of(param), thrown, body, null); injectMethod(builderType, method); @@ -168,7 +168,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { String simpleTypeName = getSimpleTargetTypeName(data); JCExpression varType = chainDotsString(builderType, data.getTargetFqn()); - int agrumentsCount = getTypeAgrumentsCount(mapMode, simpleTypeName); + int agrumentsCount = getTypeArgumentsCount(mapMode, simpleTypeName); varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs(), source); JCExpression empty; { @@ -207,7 +207,7 @@ abstract class JavacGuavaSingularizer extends JavacSingularizer { return maker.If(cond, thenPart, null); } - private int getTypeAgrumentsCount(boolean isMap, String simpleTypeName) { + private int getTypeArgumentsCount(boolean isMap, String simpleTypeName) { return isMap ? 2 : getListSetTypeArgumentsCount(simpleTypeName); } -- cgit