diff options
author | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-01-18 03:10:07 +0100 |
---|---|---|
committer | Reinier Zwitserloot <r.zwitserloot@projectlombok.org> | 2020-01-28 16:21:39 +0100 |
commit | 91a40b83125808d3684ce07c5cb4a2927d0b979c (patch) | |
tree | ee1105aa16d2db522e26ea16cf11579fee81d893 /src/core/lombok/javac | |
parent | 6cc74e42295b6138629c6b32dd56a99ee8c2c646 (diff) | |
download | lombok-91a40b83125808d3684ce07c5cb4a2927d0b979c.tar.gz lombok-91a40b83125808d3684ce07c5cb4a2927d0b979c.tar.bz2 lombok-91a40b83125808d3684ce07c5cb4a2927d0b979c.zip |
[singular][issue #2221] the plural builder method now nullchecks its argument with configurable results.
Diffstat (limited to 'src/core/lombok/javac')
-rw-r--r-- | src/core/lombok/javac/handlers/HandleBuilder.java | 19 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleSuperBuilder.java | 7 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacSingularsRecipes.java | 68 |
3 files changed, 74 insertions, 20 deletions
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index 5fc3957b..75f3de2c 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -61,6 +61,7 @@ import lombok.Builder; import lombok.Builder.ObtainVia; import lombok.ConfigurationKeys; import lombok.Singular; +import lombok.Singular.NullCollectionBehavior; import lombok.ToString; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; @@ -869,8 +870,9 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (!annotationTypeMatches(Singular.class, child)) continue; Name pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((JCVariableDecl) node.get()).name; AnnotationValues<Singular> ann = createAnnotation(Singular.class, child); + Singular singularInstance = ann.getInstance(); deleteAnnotationIfNeccessary(child, Singular.class); - String explicitSingular = ann.getInstance().value(); + String explicitSingular = singularInstance.value(); if (explicitSingular.isEmpty()) { if (Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_AUTO))) { node.addError("The singular must be specified explicitly (e.g. @Singular(\"task\")) because auto singularization is disabled."); @@ -906,9 +908,22 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { return null; } - return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer, setterPrefix); + NullCollectionBehavior behavior = getNullBehaviorFor(ann, singularInstance, node); + + return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer, behavior, setterPrefix); } return null; } + + static NullCollectionBehavior getNullBehaviorFor(AnnotationValues<Singular> ann, Singular singularInstance, JavacNode node) { + NullCollectionBehavior behavior; + if (ann.isExplicit("nullBehavior")) { + behavior = singularInstance.nullBehavior(); + } else { + behavior = node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_NULL_COLLECTIONS); + } + if (behavior == null) return NullCollectionBehavior.NULL_POINTER_EXCEPTION; + return behavior; + } } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index b3002946..692ee60b 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -59,6 +59,7 @@ import com.sun.tools.javac.util.Name; import lombok.AccessLevel; import lombok.Builder; import lombok.Builder.ObtainVia; +import lombok.Singular.NullCollectionBehavior; import lombok.ConfigurationKeys; import lombok.Singular; import lombok.ToString; @@ -939,8 +940,9 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { if (!annotationTypeMatches(Singular.class, child)) continue; Name pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((JCVariableDecl) node.get()).name; AnnotationValues<Singular> ann = createAnnotation(Singular.class, child); + Singular singularInstance = ann.getInstance(); deleteAnnotationIfNeccessary(child, Singular.class); - String explicitSingular = ann.getInstance().value(); + String explicitSingular = singularInstance.value(); if (explicitSingular.isEmpty()) { if (Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_AUTO))) { node.addError("The singular must be specified explicitly (e.g. @Singular(\"task\")) because auto singularization is disabled."); @@ -974,7 +976,8 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { return null; } - return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer); + NullCollectionBehavior behavior = HandleBuilder.getNullBehaviorFor(ann, singularInstance, node); + return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer, behavior); } return null; diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java index c1e6edd8..a5d4a295 100644 --- a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java +++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java @@ -24,33 +24,24 @@ package lombok.javac.handlers; import static lombok.javac.Javac.*; import static lombok.javac.handlers.JavacHandlerUtil.*; -import com.sun.tools.javac.tree.JCTree.JCBlock; -import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import java.io.IOException; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.core.LombokImmutableList; -import lombok.core.SpiLoadUtil; -import lombok.core.TypeLibrary; -import lombok.core.configuration.CheckerFrameworkVersion; -import lombok.core.handlers.HandlerUtil; -import lombok.javac.JavacNode; -import lombok.javac.JavacTreeMaker; - import com.sun.source.tree.Tree.Kind; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; +import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.util.Context; @@ -58,6 +49,17 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Singular.NullCollectionBehavior; +import lombok.core.LombokImmutableList; +import lombok.core.SpiLoadUtil; +import lombok.core.TypeLibrary; +import lombok.core.configuration.CheckerFrameworkVersion; +import lombok.core.handlers.HandlerUtil; +import lombok.javac.JavacNode; +import lombok.javac.JavacTreeMaker; + public class JavacSingularsRecipes { public interface ExpressionMaker { JCExpression make(); @@ -120,12 +122,13 @@ public class JavacSingularsRecipes { private final String targetFqn; private final JavacSingularizer singularizer; private final String setterPrefix; + private final NullCollectionBehavior nullCollectionBehavior; - public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer) { - this(annotation, singularName, pluralName, typeArgs, targetFqn, singularizer, ""); + public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer, NullCollectionBehavior nullCollectionBehavior) { + this(annotation, singularName, pluralName, typeArgs, targetFqn, singularizer, nullCollectionBehavior, ""); } - public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer, String setterPrefix) { + public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer, NullCollectionBehavior nullCollectionBehavior, String setterPrefix) { this.annotation = annotation; this.singularName = singularName; this.pluralName = pluralName; @@ -133,6 +136,7 @@ public class JavacSingularsRecipes { this.targetFqn = targetFqn; this.singularizer = singularizer; this.setterPrefix = setterPrefix; + this.nullCollectionBehavior = nullCollectionBehavior; } public JavacNode getAnnotation() { @@ -163,6 +167,10 @@ public class JavacSingularsRecipes { return singularizer; } + public NullCollectionBehavior getNullCollectionBehavior() { + return nullCollectionBehavior; + } + public String getTargetSimpleType() { int idx = targetFqn.lastIndexOf("."); return idx == -1 ? targetFqn : targetFqn.substring(idx + 1); @@ -320,6 +328,7 @@ public class JavacSingularsRecipes { private void generatePluralMethod(CheckerFrameworkVersion cfv, boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent, AccessLevel access) { ListBuffer<JCStatement> statements = generatePluralMethodStatements(maker, data, builderType, source); + Name name = data.getPluralName(); String setterPrefix = data.getSetterPrefix(); if (setterPrefix.isEmpty() && !fluent) setterPrefix = getAddMethodName() + "All"; @@ -329,13 +338,40 @@ public class JavacSingularsRecipes { long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext()); JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null); statements.prepend(createConstructBuilderVarIfNeeded(maker, data, builderType, source)); + + NullCollectionBehavior behavior = data.getNullCollectionBehavior(); + + if (behavior == NullCollectionBehavior.IGNORE) { + JCExpression incomingIsNotNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(data.getPluralName()), maker.Literal(CTC_BOT, null)); + JCStatement onNotNull = maker.Block(0, statements.toList()); + statements = new ListBuffer<JCStatement>(); + statements.add(maker.If(incomingIsNotNull, onNotNull, null)); + } else { + JCLiteral message = maker.Literal(behavior.toExceptionMessage(data.getPluralName().toString())); + if (behavior.getExceptionType() != null) { + JCExpression incomingIsNull = maker.Binary(CTC_EQUAL, maker.Ident(data.getPluralName()), maker.Literal(CTC_BOT, null)); + JCExpression exType = genTypeRef(builderType, behavior.getExceptionType()); + JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), exType, List.<JCExpression>of(message), null); + JCStatement onNull = maker.Throw(exception); + statements.prepend(maker.If(incomingIsNull, onNull, null)); + } else { + LombokImmutableList<String> method = behavior.getMethod(); + JCExpression invoke = maker.Apply(List.<JCExpression>nil(), chainDots(builderType, method), List.of(maker.Ident(data.getPluralName()), message)); + statements.prepend(maker.Exec(invoke)); + } + } + finishAndInjectMethod(cfv, maker, returnType, returnStatement, data, builderType, source, deprecate, statements, name, List.of(param), access); } protected ListBuffer<JCStatement> generatePluralMethodStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) { + ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); + JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All"); JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(data.getPluralName()))); - return new ListBuffer<JCStatement>().append(maker.Exec(invokeAdd)); + statements.append(maker.Exec(invokeAdd)); + + return statements; } protected abstract JCExpression getPluralMethodParamType(JavacNode builderType); |