aboutsummaryrefslogtreecommitdiff
path: root/src/core/lombok/eclipse/handlers
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/eclipse/handlers
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/eclipse/handlers')
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java59
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleBuilder.java18
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/HandleSuperBuilder.java7
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java5
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java4
-rwxr-xr-xsrc/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java5
6 files changed, 88 insertions, 10 deletions
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
index 9d79d75c..5fe4b958 100755
--- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -33,25 +33,31 @@ import java.util.Map;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Reference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.ThrowStatement;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.ast.Wildcard;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
@@ -60,10 +66,12 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import lombok.AccessLevel;
+import lombok.Singular.NullCollectionBehavior;
import lombok.core.LombokImmutableList;
import lombok.core.SpiLoadUtil;
import lombok.core.TypeLibrary;
import lombok.core.configuration.CheckerFrameworkVersion;
+import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseNode;
public class EclipseSingularsRecipes {
@@ -126,13 +134,14 @@ public class EclipseSingularsRecipes {
private final List<TypeReference> typeArgs;
private final String targetFqn;
private final EclipseSingularizer singularizer;
+ private final NullCollectionBehavior nullCollectionBehavior;
private final ASTNode source;
- public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source) {
- this(annotation, singularName, pluralName, typeArgs, targetFqn, singularizer, source, new char[0]);
+ public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source, NullCollectionBehavior nullCollectionBehavior) {
+ this(annotation, singularName, pluralName, typeArgs, targetFqn, singularizer, source, nullCollectionBehavior, new char[0]);
}
- public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source, char[] setterPrefix) {
+ public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source, NullCollectionBehavior nullCollectionBehavior, char[] setterPrefix) {
this.annotation = annotation;
this.singularName = singularName;
this.pluralName = pluralName;
@@ -140,6 +149,7 @@ public class EclipseSingularsRecipes {
this.targetFqn = targetFqn;
this.singularizer = singularizer;
this.source = source;
+ this.nullCollectionBehavior = nullCollectionBehavior;
this.setterPrefix = setterPrefix;
}
@@ -187,6 +197,10 @@ public class EclipseSingularsRecipes {
return singularizer;
}
+ public NullCollectionBehavior getNullCollectionBehavior() {
+ return nullCollectionBehavior;
+ }
+
public String getTargetSimpleType() {
int idx = targetFqn.lastIndexOf(".");
return idx == -1 ? targetFqn : targetFqn.substring(idx + 1);
@@ -423,6 +437,45 @@ public class EclipseSingularsRecipes {
}
}
+ protected void nullBehaviorize(SingularData data, List<Statement> statements) {
+ NullCollectionBehavior behavior = data.getNullCollectionBehavior();
+
+ if (behavior == NullCollectionBehavior.IGNORE) {
+ Expression isNotNull = new EqualExpression(new SingleNameReference(data.getPluralName(), 0L), new NullLiteral(0, 0), OperatorIds.NOT_EQUAL);
+ Block b = new Block(0);
+ b.statements = statements.toArray(new Statement[statements.size()]);
+ statements.clear();
+ statements.add(new IfStatement(isNotNull, b, 0, 0));
+ return;
+ }
+
+ String exceptionTypeStr = behavior.getExceptionType();
+ StringLiteral message = new StringLiteral(behavior.toExceptionMessage(new String(data.getPluralName())).toCharArray(), 0, 0, 0);
+ if (exceptionTypeStr != null) {
+ Expression isNull = new EqualExpression(new SingleNameReference(data.getPluralName(), 0L), new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+ int partCount = 1;
+ for (int i = 0; i < exceptionTypeStr.length(); i++) if (exceptionTypeStr.charAt(i) == '.') partCount++;
+ long[] ps = new long[partCount];
+ Arrays.fill(ps, 0L);
+ AllocationExpression alloc = new AllocationExpression();
+ alloc.type = new QualifiedTypeReference(Eclipse.fromQualifiedName(exceptionTypeStr), ps);
+ alloc.arguments = new Expression[] {message};
+ Statement t = new ThrowStatement(alloc, 0, 0);
+ statements.add(0, new IfStatement(isNull, t, 0, 0));
+ return;
+ }
+
+ MessageSend invoke = new MessageSend();
+ LombokImmutableList<String> method = behavior.getMethod();
+ char[][] utilityTypeName = new char[method.size() - 1][];
+ for (int i = 0; i < method.size() - 1; i++) utilityTypeName[i] = method.get(i).toCharArray();
+
+ invoke.receiver = new QualifiedNameReference(utilityTypeName, new long[method.size() - 1], 0, 0);
+ invoke.selector = method.get(method.size() - 1).toCharArray();
+ invoke.arguments = new Expression[] {new SingleNameReference(data.getPluralName(), 0L), message};
+ statements.add(0, invoke);
+ }
+
protected abstract char[][] getEmptyMakerReceiver(String targetFqn);
protected abstract char[] getEmptyMakerSelector(String targetFqn);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index bb031ebc..578fa2a3 100755
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java
@@ -79,6 +79,7 @@ import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Builder.ObtainVia;
+import lombok.Singular.NullCollectionBehavior;
import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.ToString;
@@ -992,7 +993,8 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
if (!annotationTypeMatches(Singular.class, child)) continue;
char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name;
AnnotationValues<Singular> ann = createAnnotation(Singular.class, child);
- String explicitSingular = ann.getInstance().value();
+ Singular singularInstance = ann.getInstance();
+ 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.");
@@ -1034,9 +1036,21 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return null;
}
- return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source, setterPrefix.toCharArray());
+ NullCollectionBehavior behavior = getNullBehaviorFor(ann, singularInstance, node);
+ return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source, behavior, setterPrefix.toCharArray());
}
return null;
}
+
+ static NullCollectionBehavior getNullBehaviorFor(AnnotationValues<Singular> ann, Singular singularInstance, EclipseNode 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/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
index 3a2e59f7..4b450a07 100755
--- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java
@@ -79,6 +79,7 @@ import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Builder.ObtainVia;
+import lombok.Singular.NullCollectionBehavior;
import lombok.ConfigurationKeys;
import lombok.Singular;
import lombok.ToString;
@@ -1000,7 +1001,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name;
AnnotationValues<Singular> ann = createAnnotation(Singular.class, child);
- String explicitSingular = ann.getInstance().value();
+ Singular singularInstance = ann.getInstance();
+ 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.");
@@ -1042,7 +1044,8 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> {
return null;
}
- return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source);
+ NullCollectionBehavior behavior = HandleBuilder.getNullBehaviorFor(ann, singularInstance, node);
+ return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source, behavior);
}
return null;
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
index 8f80d228..b067ad80 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 The Project Lombok Authors.
+ * Copyright (C) 2015-2020 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
@@ -195,6 +195,9 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
thisDotFieldDotAddAll.receiver = thisDotField;
thisDotFieldDotAddAll.selector = (getAddMethodName() + "All").toCharArray();
statements.add(thisDotFieldDotAddAll);
+
+ nullBehaviorize(data, statements);
+
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[0]);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
index e3a99008..ba447397 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 The Project Lombok Authors.
+ * Copyright (C) 2015-2020 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
@@ -173,6 +173,8 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula
thisDotFieldDotAddAll.receiver = thisDotField;
thisDotFieldDotAddAll.selector = "addAll".toCharArray();
statements.add(thisDotFieldDotAddAll);
+
+ nullBehaviorize(data, statements);
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[0]);
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
index b0223c50..e91c6616 100755
--- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015-2019 The Project Lombok Authors.
+ * Copyright (C) 2015-2020 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
@@ -305,6 +305,9 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer
forEachContent.statements = new Statement[] {addKey, addValue};
forEach.action = forEachContent;
statements.add(forEach);
+
+ nullBehaviorize(data, statements);
+
if (returnStatement != null) statements.add(returnStatement);
md.statements = statements.toArray(new Statement[0]);