aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/javac
diff options
context:
space:
mode:
authorReinier Zwitserloot <r.zwitserloot@projectlombok.org>2020-01-18 03:10:07 +0100
committerReinier Zwitserloot <r.zwitserloot@projectlombok.org>2020-01-28 16:21:39 +0100
commit91a40b83125808d3684ce07c5cb4a2927d0b979c (patch)
treeee1105aa16d2db522e26ea16cf11579fee81d893 /src/core/lombok/javac
parent6cc74e42295b6138629c6b32dd56a99ee8c2c646 (diff)
downloadlombok-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.java19
-rw-r--r--src/core/lombok/javac/handlers/HandleSuperBuilder.java7
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java68
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);