diff options
author | Caleb Brinkman <cbrinkman@sonatype.com> | 2019-07-16 10:39:54 -0500 |
---|---|---|
committer | Caleb Brinkman <cbrinkman@sonatype.com> | 2019-07-16 10:39:54 -0500 |
commit | 4dc5c32d6b47264b5c8abb6fdf24077eec5aa7e7 (patch) | |
tree | 9779fbf1d16dab92b0f5076f773870653de49820 | |
parent | 88bf742e3e107cc0bbfc3a72c2f456d34ef3079c (diff) | |
parent | 218f28cc95ee30d5d362c3ac9d5440c2f86fd712 (diff) | |
download | lombok-4dc5c32d6b47264b5c8abb6fdf24077eec5aa7e7.tar.gz lombok-4dc5c32d6b47264b5c8abb6fdf24077eec5aa7e7.tar.bz2 lombok-4dc5c32d6b47264b5c8abb6fdf24077eec5aa7e7.zip |
Merge branch 'master' of github.com:rzwitserloot/lombok into feature/builder-setter-prefixes
42 files changed, 632 insertions, 228 deletions
diff --git a/doc/changelog.markdown b/doc/changelog.markdown index e486a713..0e489dd3 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -7,10 +7,12 @@ Lombok Changelog * ENHANCEMENT: `val` is now capable of decoding the type of convoluted expressions (particularly if the right hand side involves lambdas and conditional (ternary) expressions). [Pull Request #2109](https://github.com/rzwitserloot/lombok/pull/2109) and [Pull Request #2138](https://github.com/rzwitserloot/lombok/pull/2138) with thanks to Alexander Bulgakov. * ENHANCEMENT: You can now configure the generated builder class name via the config system, using key `lombok.builder.className`. See the [Builder documentation](https://projectlombok.org/features/Builder) and [SuperBuilder documentation](https://projectlombok.org/features/experimental/SuperBuilder) * ENHANCEMENT: If you mix up eclipse's non-null support, such as `@NonNullByDefault`, with lombok's `@NonNull`, you get a bunch of warnings about dead code that are inappropriate. These warnings are now suppressed, thanks to a contribution from Till Brychcy! [Pull Request #2155](https://github.com/rzwitserloot/lombok/pull/2155) +* ENHANCEMENT: `@NonNull` can now also generate checks using jdk's `Objects.requireNonNull` or Guava's `Preconditions.checkNotNull`. [Issue #1197](https://github.com/rzwitserloot/lombok/issues/1197) * BUGFIX: Delombok would turn something like `List<byte[]>...` in a method parameter to `List<byte...>...` [Issue #2140](https://github.com/rzwitserloot/lombok/issues/2140) * BUGFIX: Javac would generate the wrong equals and hashCode if a type-use annotation was put on an array type field [Issue #2165](https://github.com/rzwitserloot/lombok/issues/2165) +* BUGFIX: Eclipse 2019-06 + JDK-12 compatibility + an `@Singular` builder entry would produce a cascade of error dialogs. [Issue #2169](https://github.com/rzwitserloot/lombok/issues/2169) * IMPROBABLE BREAKING CHANGE: Stricter validation of configuration keys dealing with identifiers and types (`lombok.log.fieldName`, `lombok.fieldNameConstants.innerTypeName`, `lombok.copyableAnnotations`). ->>>>>>> customlog +* IMPROBABLE BREAKING CHANGE: The fields generated inside builders for fields with defaults (with `@Builder` on a class with fields marked `@Default`) now have `$value` as the name; direct manipulation of these fields is not advised because there is an associated `$set` variable that also needs to be taken into account. [Issue #2115](https://github.com/rzwitserloot/lombok/issues/2115) ### v1.18.8 (May 7th, 2019) * FEATURE: You can now configure `@FieldNameConstants` to `CONSTANT_CASE` the generated constants, using a `lombok.config` option. See the [FieldNameConstants documentation](https://projectlombok.org/features/experimental/FieldNameConstants). [Issue #2092](https://github.com/rzwitserloot/lombok/issues/2092). diff --git a/src/core/lombok/core/configuration/NullCheckExceptionType.java b/src/core/lombok/core/configuration/NullCheckExceptionType.java index d226c0a8..3c9e325d 100644 --- a/src/core/lombok/core/configuration/NullCheckExceptionType.java +++ b/src/core/lombok/core/configuration/NullCheckExceptionType.java @@ -21,28 +21,64 @@ */ package lombok.core.configuration; +import lombok.core.LombokImmutableList; -@ExampleValueString("[NullPointerException | IllegalArgumentException | Assertion]") +@ExampleValueString("[NullPointerException | IllegalArgumentException | Assertion | JDK | GUAVA]") public enum NullCheckExceptionType { ILLEGAL_ARGUMENT_EXCEPTION { @Override public String getExceptionType() { return "java.lang.IllegalArgumentException"; } + + @Override public LombokImmutableList<String> getMethod() { + return null; + } }, NULL_POINTER_EXCEPTION { @Override public String getExceptionType() { return "java.lang.NullPointerException"; } + + @Override public LombokImmutableList<String> getMethod() { + return null; + } }, ASSERTION { @Override public String getExceptionType() { return null; } + + @Override public LombokImmutableList<String> getMethod() { + return null; + } + }, + JDK { + @Override public String getExceptionType() { + return null; + } + + @Override public LombokImmutableList<String> getMethod() { + return METHOD_JDK; + } + }, + GUAVA { + @Override public String getExceptionType() { + return null; + } + + @Override public LombokImmutableList<String> getMethod() { + return METHOD_GUAVA; + } }; + private static final LombokImmutableList<String> METHOD_JDK = LombokImmutableList.of("java", "util", "Objects", "requireNonNull"); + private static final LombokImmutableList<String> METHOD_GUAVA = LombokImmutableList.of("com", "google", "common", "base", "Preconditions", "checkNotNull"); + public String toExceptionMessage(String fieldName) { return fieldName + " is marked non-null but is null"; } public abstract String getExceptionType(); + + public abstract LombokImmutableList<String> getMethod(); } diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java index 6e28f65d..21a3a216 100644 --- a/src/core/lombok/core/handlers/HandlerUtil.java +++ b/src/core/lombok/core/handlers/HandlerUtil.java @@ -302,6 +302,7 @@ public class HandlerUtil { })); COPY_TO_SETTER_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(new String[] { "com.fasterxml.jackson.annotation.JsonProperty", + "com.fasterxml.jackson.annotation.JsonSetter", })); } diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java index 1a0633bf..11a2b9bd 100644 --- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java +++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java @@ -38,26 +38,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import lombok.AccessLevel; -import lombok.ConfigurationKeys; -import lombok.Data; -import lombok.Getter; -import lombok.Lombok; -import lombok.core.AST.Kind; -import lombok.core.AnnotationValues; -import lombok.core.AnnotationValues.AnnotationValue; -import lombok.core.TypeResolver; -import lombok.core.configuration.NullCheckExceptionType; -import lombok.core.configuration.TypeName; -import lombok.core.debug.ProblemReporter; -import lombok.core.handlers.HandlerUtil; -import lombok.eclipse.Eclipse; -import lombok.eclipse.EclipseAST; -import lombok.eclipse.EclipseNode; -import lombok.experimental.Accessors; -import lombok.experimental.Tolerate; -import lombok.permit.Permit; - import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; @@ -121,6 +101,28 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.eclipse.jdt.internal.compiler.lookup.WildcardBinding; +import lombok.AccessLevel; +import lombok.ConfigurationKeys; +import lombok.Data; +import lombok.Getter; +import lombok.Lombok; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues; +import lombok.core.AnnotationValues.AnnotationValue; +import lombok.core.LombokImmutableList; +import lombok.core.TypeResolver; +import lombok.core.configuration.NullCheckExceptionType; +import lombok.core.configuration.TypeName; +import lombok.core.debug.ProblemReporter; +import lombok.core.handlers.HandlerUtil; +import lombok.core.handlers.HandlerUtil.FieldAccess; +import lombok.eclipse.Eclipse; +import lombok.eclipse.EclipseAST; +import lombok.eclipse.EclipseNode; +import lombok.experimental.Accessors; +import lombok.experimental.Tolerate; +import lombok.permit.Permit; + /** * Container for static utility methods useful to handlers written for eclipse. */ @@ -1816,36 +1818,54 @@ public class EclipseHandlerUtil { } /** - * Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the + * Generates a new statement that checks if the given local variable is null, and if so, throws a specified exception with the * variable name as message. - * - * @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}. */ - public static Statement generateNullCheck(AbstractVariableDeclaration variable, EclipseNode sourceNode) { + public static Statement generateNullCheck(TypeReference type, char[] variable, EclipseNode sourceNode) { NullCheckExceptionType exceptionType = sourceNode.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE); if (exceptionType == null) exceptionType = NullCheckExceptionType.NULL_POINTER_EXCEPTION; ASTNode source = sourceNode.get(); int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; + long p = (long) pS << 32 | pE; + + if (isPrimitive(type)) return null; + SingleNameReference varName = new SingleNameReference(variable, p); + setGeneratedBy(varName, source); + + StringLiteral message = new StringLiteral(exceptionType.toExceptionMessage(new String(variable)).toCharArray(), pS, pE, 0); + setGeneratedBy(message, source); + + LombokImmutableList<String> method = exceptionType.getMethod(); + if (method != null) { + + MessageSend invocation = new MessageSend(); + invocation.sourceStart = pS; invocation.sourceEnd = pE; + setGeneratedBy(invocation, source); + + char[][] utilityTypeName = new char[method.size() - 1][]; + for (int i = 0; i < method.size() - 1; i++) { + utilityTypeName[i] = method.get(i).toCharArray(); + } + + invocation.receiver = new QualifiedNameReference(utilityTypeName, new long[method.size()], pS, pE); + setGeneratedBy(invocation.receiver, source); + invocation.selector = method.get(method.size() - 1).toCharArray(); + invocation.arguments = new Expression[] {varName, message}; + return invocation; + } - if (isPrimitive(variable.type)) return null; AllocationExpression exception = new AllocationExpression(); setGeneratedBy(exception, source); - SingleNameReference varName = new SingleNameReference(variable.name, p); - setGeneratedBy(varName, source); NullLiteral nullLiteral = new NullLiteral(pS, pE); setGeneratedBy(nullLiteral, source); - + int equalOperator = exceptionType == NullCheckExceptionType.ASSERTION ? OperatorIds.NOT_EQUAL : OperatorIds.EQUAL_EQUAL; EqualExpression equalExpression = new EqualExpression(varName, nullLiteral, equalOperator); equalExpression.sourceStart = pS; equalExpression.statementEnd = equalExpression.sourceEnd = pE; setGeneratedBy(equalExpression, source); - - StringLiteral message = new StringLiteral(exceptionType.toExceptionMessage(new String(variable.name)).toCharArray(), pS, pE, 0); - setGeneratedBy(message, source); if (exceptionType == NullCheckExceptionType.ASSERTION) { Statement assertStatement = new AssertStatement(message, equalExpression, pS); @@ -1865,7 +1885,6 @@ public class EclipseHandlerUtil { ThrowStatement throwStatement = new ThrowStatement(exception, pS, pE); setGeneratedBy(throwStatement, source); - Block throwBlock = new Block(0); throwBlock.statements = new Statement[] {throwStatement}; throwBlock.sourceStart = pS; throwBlock.sourceEnd = pE; @@ -1876,6 +1895,16 @@ public class EclipseHandlerUtil { } /** + * Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the + * variable name as message. + * + * @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}. + */ + public static Statement generateNullCheck(AbstractVariableDeclaration variable, EclipseNode sourceNode) { + return generateNullCheck(variable.type, variable.name, sourceNode); + } + + /** * Create an annotation of the given name, and is marked as being generated by the given source. */ public static MarkerAnnotation makeMarkerAnnotation(char[][] name, ASTNode source) { diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index aa43e96e..5a4d5bff 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -114,6 +114,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { TypeReference type; char[] rawName; char[] name; + char[] builderFieldName; char[] nameOfDefaultProvider; char[] nameOfSetFlag; SingularData singularData; @@ -144,6 +145,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'}; private static final char[] SET_PREFIX = {'$', 's', 'e', 't'}; + private static final char[] VALUE_PREFIX = {'$', 'v', 'a', 'l', 'u', 'e'}; private static final char[] prefixWith(char[] prefix, char[] name) { char[] out = new char[prefix.length + name.length]; @@ -230,6 +232,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { BuilderFieldData bfd = new BuilderFieldData(); bfd.rawName = fieldNode.getName().toCharArray(); bfd.name = removePrefixFromField(fieldNode); + bfd.builderFieldName = bfd.name; bfd.annotations = copyAnnotations(fd, copyableAnnotations); bfd.type = fd.type; bfd.singularData = getSingularData(fieldNode, ast); @@ -254,6 +257,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { if (isDefault != null) { bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name); bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX); + bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX); MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast); if (md != null) injectMethod(tdParent, md); @@ -411,6 +415,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { bfd.rawName = arg.name; bfd.name = arg.name; + bfd.builderFieldName = bfd.name; bfd.annotations = copyAnnotations(arg, copyableAnnotations); bfd.type = arg.type; bfd.singularData = getSingularData(param, ast); @@ -662,7 +667,7 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name, "this"); + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.builderFieldName, "this"); } } @@ -678,10 +683,10 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { args.add(new ConditionalExpression( new SingleNameReference(bfd.nameOfSetFlag, 0L), - new SingleNameReference(bfd.name, 0L), + new SingleNameReference(bfd.builderFieldName, 0L), inv)); } else { - args.add(new SingleNameReference(bfd.name, 0L)); + args.add(new SingleNameReference(bfd.builderFieldName, 0L)); } } @@ -782,12 +787,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { EclipseNode field = null, setFlag = null; for (EclipseNode exists : existing) { char[] n = ((FieldDeclaration) exists.get()).name; - if (Arrays.equals(n, bfd.name)) field = exists; + if (Arrays.equals(n, bfd.builderFieldName)) field = exists; if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists; } if (field == null) { - FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0); + FieldDeclaration fd = new FieldDeclaration(bfd.builderFieldName, 0, 0); fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; fd.modifiers = ClassFileConstants.AccPrivate; fd.type = copyType(bfd.type); @@ -812,13 +817,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode) { boolean deprecate = isFieldDeprecated(bfd.originalFieldNode); if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { - makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode); + makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode); } else { bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain, access); } } - private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode) { + private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode) { TypeDeclaration td = (TypeDeclaration) builderType.get(); AbstractMethodDeclaration[] existing = td.methods; if (existing == null) existing = EMPTY; @@ -832,12 +837,12 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { if (Arrays.equals(name, existingName) && !isTolerate(fieldNode, existing[i])) return; } - String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName()); + String setterName = fluent ? new String(paramName) : HandlerUtil.buildAccessorName("set", new String(paramName)); List<Annotation> methodAnnsList = Collections.<Annotation>emptyList(); Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns); - MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, toEclipseModifier(access), + MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access), sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annotations)) : Collections.<Annotation>emptyList()); injectMethod(builderType, setter); } @@ -845,13 +850,13 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { public void makePrefixedSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access, EclipseNode originalFieldNode, String prefix) { boolean deprecate = isFieldDeprecated(bfd.originalFieldNode); if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { - makePrefixedSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode, prefix); + makePrefixedSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access, originalFieldNode, prefix); } else { bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain, access); } } - private void makePrefixedSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode, String prefix) { + private void makePrefixedSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access, EclipseNode originalFieldNode, String prefix) { TypeDeclaration td = (TypeDeclaration) builderType.get(); AbstractMethodDeclaration[] existing = td.methods; if (existing == null) existing = EMPTY; @@ -868,15 +873,15 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> { String setterPrefix = prefix.isEmpty() ? "set" : prefix; String setterName; if(fluent) { - setterName = prefix.isEmpty() ? fieldNode.getName() : HandlerUtil.buildAccessorName(setterPrefix, fieldNode.getName()); + setterName = prefix.isEmpty() ? new String(paramName) : HandlerUtil.buildAccessorName(setterPrefix, new String(paramName)); } else { - setterName = HandlerUtil.buildAccessorName(setterPrefix, fieldNode.getName()); + setterName = HandlerUtil.buildAccessorName(setterPrefix, new String(paramName)); } List<Annotation> methodAnnsList = Collections.<Annotation>emptyList(); Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns); - MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, toEclipseModifier(access), + MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, chain, toEclipseModifier(access), sourceNode, methodAnnsList, annotations != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annotations)) : Collections.<Annotation>emptyList()); injectMethod(builderType, setter); } diff --git a/src/core/lombok/eclipse/handlers/HandleNonNull.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java index 77c77e1e..c61ce02d 100644 --- a/src/core/lombok/eclipse/handlers/HandleNonNull.java +++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java @@ -33,10 +33,12 @@ import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.AssertStatement; +import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.IfStatement; +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.SingleNameReference; @@ -61,6 +63,9 @@ import lombok.eclipse.EclipseNode; @ProviderFor(EclipseAnnotationHandler.class) @HandlerPriority(value = 512) // 2^9; onParameter=@__(@NonNull) has to run first. public class HandleNonNull extends EclipseAnnotationHandler<NonNull> { + private static final char[] REQUIRE_NON_NULL = "requireNonNull".toCharArray(); + private static final char[] CHECK_NOT_NULL = "checkNotNull".toCharArray(); + public static final HandleNonNull INSTANCE = new HandleNonNull(); public void fix(EclipseNode method) { @@ -193,7 +198,22 @@ public class HandleNonNull extends EclipseAnnotationHandler<NonNull> { public char[] returnVarNameIfNullCheck(Statement stat) { boolean isIf = stat instanceof IfStatement; - if (!isIf && !(stat instanceof AssertStatement)) return null; + boolean isExpression = stat instanceof Expression; + if (!isIf && !(stat instanceof AssertStatement) && !isExpression) return null; + + if (isExpression) { + /* Check if the statements contains a call to checkNotNull or requireNonNull */ + Expression expression = (Expression) stat; + if (expression instanceof Assignment) expression = ((Assignment) expression).expression; + if (!(expression instanceof MessageSend)) return null; + + MessageSend invocation = (MessageSend) expression; + if (!Arrays.equals(invocation.selector, CHECK_NOT_NULL) && !Arrays.equals(invocation.selector, REQUIRE_NON_NULL)) return null; + if (invocation.arguments == null || invocation.arguments.length == 0) return null; + Expression firstArgument = invocation.arguments[0]; + if (!(firstArgument instanceof SingleNameReference)) return null; + return ((SingleNameReference) firstArgument).token; + } if (isIf) { /* Check that the if's statement is a throw statement, possibly in a block. */ diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java index 4ea83cf6..bb704ead 100644 --- a/src/core/lombok/eclipse/handlers/HandleSetter.java +++ b/src/core/lombok/eclipse/handlers/HandleSetter.java @@ -184,11 +184,11 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { } } - MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), false, fieldNode, setterName, null, shouldReturnThis, modifier, sourceNode, onMethod, onParam); + MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), false, fieldNode, setterName, null, null, shouldReturnThis, modifier, sourceNode, onMethod, onParam); injectMethod(fieldNode.up(), method); } - static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) { + static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] paramName, char[] booleanFieldToSet, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) { ASTNode source = sourceNode.get(); int pS = source.sourceStart, pE = source.sourceEnd; @@ -200,14 +200,15 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { returnThis = new ReturnStatement(thisRef, pS, pE); } - return createSetter(parent, deprecate, fieldNode, name, booleanFieldToSet, returnType, returnThis, modifier, sourceNode, onMethod, onParam); + return createSetter(parent, deprecate, fieldNode, name, paramName, booleanFieldToSet, returnType, returnThis, modifier, sourceNode, onMethod, onParam); } - static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, TypeReference returnType, Statement returnStatement, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) { + static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] paramName, char[] booleanFieldToSet, TypeReference returnType, Statement returnStatement, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) { FieldDeclaration field = (FieldDeclaration) fieldNode.get(); + if (paramName == null) paramName = field.name; ASTNode source = sourceNode.get(); int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long)pS << 32 | pE; + long p = (long) pS << 32 | pE; MethodDeclaration method = new MethodDeclaration(parent.compilationResult); method.modifiers = modifier; if (returnType != null) { @@ -221,7 +222,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { deprecated = new Annotation[] { generateDeprecatedAnnotation(source) }; } method.annotations = mergeAnnotations(copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated), findCopyableToSetterAnnotations(fieldNode)); - Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL); + Argument param = new Argument(paramName, p, copyType(field.type, source), Modifier.FINAL); param.sourceStart = pS; param.sourceEnd = pE; method.arguments = new Argument[] { param }; method.selector = name.toCharArray(); @@ -230,8 +231,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { method.typeParameters = null; method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; Expression fieldRef = createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source); - NameReference fieldNameRef = new SingleNameReference(field.name, p); - Assignment assignment = new Assignment(fieldRef, fieldNameRef, (int)p); + NameReference fieldNameRef = new SingleNameReference(paramName, p); + Assignment assignment = new Assignment(fieldRef, fieldNameRef, (int) p); assignment.sourceStart = pS; assignment.sourceEnd = assignment.statementEnd = pE; method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart; method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd; @@ -241,7 +242,7 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> { if (!hasNonNullAnnotations(fieldNode) && !hasNonNullAnnotations(fieldNode, onParam)) { statements.add(assignment); } else { - Statement nullCheck = generateNullCheck(field, sourceNode); + Statement nullCheck = generateNullCheck(field.type, paramName, sourceNode); if (nullCheck != null) statements.add(nullCheck); statements.add(assignment); } diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index f204bc24..88479911 100755 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -81,6 +81,7 @@ import lombok.ConfigurationKeys; import lombok.Singular; import lombok.ToString; import lombok.core.AST.Kind; +import lombok.core.handlers.HandlerUtil; import lombok.core.handlers.InclusionExclusionUtils.Included; import lombok.core.AnnotationValues; import lombok.core.HandlerPriority; @@ -103,6 +104,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray(); private static final char[] DEFAULT_PREFIX = "$default$".toCharArray(); private static final char[] SET_PREFIX = "$set".toCharArray(); + private static final char[] VALUE_PREFIX = "$value".toCharArray(); private static final char[] SELF_METHOD_NAME = "self".toCharArray(); private static final String TO_BUILDER_METHOD_NAME_STRING = "toBuilder"; private static final char[] TO_BUILDER_METHOD_NAME = TO_BUILDER_METHOD_NAME_STRING.toCharArray(); @@ -169,6 +171,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { BuilderFieldData bfd = new BuilderFieldData(); bfd.rawName = fieldNode.getName().toCharArray(); bfd.name = removePrefixFromField(fieldNode); + bfd.builderFieldName = bfd.name; bfd.annotations = copyAnnotations(fd, copyableAnnotations); bfd.type = fd.type; bfd.singularData = getSingularData(fieldNode, ast); @@ -193,6 +196,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { if (isDefault != null) { bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name); bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX); + bfd.builderFieldName = prefixWith(bfd.name, VALUE_PREFIX); MethodDeclaration md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast); if (md != null) injectMethod(tdParent, md); @@ -519,7 +523,6 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { List<Statement> statements = new ArrayList<Statement>(); for (BuilderFieldData fieldNode : builderFields) { - char[] fieldName = removePrefixFromField(fieldNode.originalFieldNode); FieldReference fieldInThis = new FieldReference(fieldNode.rawName, p); int s = (int) (p >> 32); int e = (int) p; @@ -527,10 +530,10 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { Expression assignmentExpr; if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) { - fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.name, BUILDER_VARIABLE_NAME_STRING); - assignmentExpr = new SingleNameReference(fieldNode.name, p); + fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, typeNode, statements, fieldNode.builderFieldName, BUILDER_VARIABLE_NAME_STRING); + assignmentExpr = new SingleNameReference(fieldNode.builderFieldName, p); } else { - char[][] variableInBuilder = new char[][] {BUILDER_VARIABLE_NAME, fieldName}; + char[][] variableInBuilder = new char[][] {BUILDER_VARIABLE_NAME, fieldNode.builderFieldName}; long[] positions = new long[] {p, p}; assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e); } @@ -844,12 +847,12 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { EclipseNode field = null, setFlag = null; for (EclipseNode exists : existing) { char[] n = ((FieldDeclaration) exists.get()).name; - if (Arrays.equals(n, bfd.name)) field = exists; + if (Arrays.equals(n, bfd.builderFieldName)) field = exists; if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists; } if (field == null) { - FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0); + FieldDeclaration fd = new FieldDeclaration(bfd.builderFieldName, 0, 0); fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; fd.modifiers = ClassFileConstants.AccPrivate; fd.type = copyType(bfd.type); @@ -888,13 +891,13 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { }; if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { - generateSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations, bfd.originalFieldNode); + generateSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.name, bfd.nameOfSetFlag, true, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations, bfd.originalFieldNode); } else { bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC); } } - private void generateSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode, Annotation[] annosOnParam, EclipseNode originalFieldNode) { + private void generateSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] paramName, char[] nameOfSetFlag, boolean fluent, TypeReference returnType, Statement returnStatement, EclipseNode sourceNode, Annotation[] annosOnParam, EclipseNode originalFieldNode) { TypeDeclaration td = (TypeDeclaration) builderType.get(); AbstractMethodDeclaration[] existing = td.methods; if (existing == null) existing = EMPTY_METHODS; @@ -908,12 +911,12 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler<SuperBuilder> { if (Arrays.equals(name, existingName) && !isTolerate(fieldNode, existing[i])) return; } - String setterName = fieldNode.getName(); + String setterName = fluent ? new String(paramName) : HandlerUtil.buildAccessorName("set", new String(paramName)); List<Annotation> methodAnnsList = Collections.<Annotation>emptyList(); Annotation[] methodAnns = EclipseHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); if (methodAnns != null && methodAnns.length > 0) methodAnnsList = Arrays.asList(methodAnns); - MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic, + MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, paramName, nameOfSetFlag, returnType, returnStatement, ClassFileConstants.AccPublic, sourceNode, methodAnnsList, annosOnParam != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annosOnParam)) : Collections.<Annotation>emptyList()); injectMethod(builderType, setter); } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java index 7ea04821..bf50aef6 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java @@ -35,7 +35,6 @@ import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.BreakStatement; -import org.eclipse.jdt.internal.compiler.ast.CaseStatement; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.FieldReference; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; @@ -74,7 +73,7 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu List<Statement> switchContents = new ArrayList<Statement>(); /* case 0: (empty) break; */ { - switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'0'}, null), 0, 0)); + switchContents.add(Eclipse.createCaseStatement(makeIntLiteral(new char[] {'0'}, null))); MessageSend invoke = new MessageSend(); invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0); invoke.selector = "emptyList".toCharArray(); @@ -83,7 +82,7 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu } /* case 1: (singleton) break; */ { - switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'1'}, null), 0, 0)); + switchContents.add(Eclipse.createCaseStatement(makeIntLiteral(new char[] {'1'}, null))); FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = getBuilderReference(builderVariable); MessageSend thisDotFieldGet0 = new MessageSend(); @@ -101,7 +100,7 @@ public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingu } /* default: Create by passing builder field to constructor. */ { - switchContents.add(new CaseStatement(null, 0, 0)); + switchContents.add(Eclipse.createCaseStatement(null)); Expression argToUnmodifiable; /* new j.u.ArrayList<Generics>(this.pluralName); */ { diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java index 8aeffc48..4a143a06 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java @@ -34,7 +34,6 @@ import org.eclipse.jdt.internal.compiler.ast.Assignment; import org.eclipse.jdt.internal.compiler.ast.BinaryExpression; import org.eclipse.jdt.internal.compiler.ast.Block; import org.eclipse.jdt.internal.compiler.ast.BreakStatement; -import org.eclipse.jdt.internal.compiler.ast.CaseStatement; import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression; import org.eclipse.jdt.internal.compiler.ast.EqualExpression; import org.eclipse.jdt.internal.compiler.ast.Expression; @@ -58,6 +57,7 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import lombok.ConfigurationKeys; +import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer; import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData; @@ -95,7 +95,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { char[] keyName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName(); if (emptyCollectionMethod != null) { // case 0: (empty); break; - switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'0'}, null), 0, 0)); + switchContents.add(Eclipse.createCaseStatement(makeIntLiteral(new char[] {'0'}, null))); /* pluralName = java.util.Collections.emptyCollectionMethod(); */ { MessageSend invoke = new MessageSend(); @@ -108,7 +108,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { } if (singletonCollectionMethod != null) { // case 1: (singleton); break; - switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'1'}, null), 0, 0)); + switchContents.add(Eclipse.createCaseStatement(makeIntLiteral(new char[] {'1'}, null))); /* !mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName.get(0)); mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName$key.get(0), this.pluralName$value.get(0)); */ { FieldReference thisDotKey = new FieldReference(keyName, 0L); @@ -142,7 +142,7 @@ abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer { } { // default: - switchContents.add(new CaseStatement(null, 0, 0)); + switchContents.add(Eclipse.createCaseStatement(null)); switchContents.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, mapMode, false, true, emptyCollectionMethod == null, targetType, builderVariable)); } diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index ab63aa5a..e447ace7 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -89,6 +89,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JCExpression type; Name rawName; Name name; + Name builderFieldName; Name nameOfDefaultProvider; Name nameOfSetFlag; SingularData singularData; @@ -174,6 +175,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { BuilderFieldData bfd = new BuilderFieldData(); bfd.rawName = fd.name; bfd.name = removePrefixFromField(fieldNode); + bfd.builderFieldName = bfd.name; bfd.annotations = findCopyableAnnotations(fieldNode); bfd.type = fd.vartype; bfd.singularData = getSingularData(fieldNode); @@ -200,6 +202,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (isDefault != null) { bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name); bfd.nameOfSetFlag = parent.toName(bfd.name + "$set"); + bfd.builderFieldName = parent.toName(bfd.name + "$value"); JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); if (md != null) injectMethod(tdParent, md); @@ -360,6 +363,7 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JCVariableDecl raw = (JCVariableDecl) param.get(); bfd.name = raw.name; + bfd.builderFieldName = bfd.name; bfd.rawName = raw.name; bfd.annotations = findCopyableAnnotations(param); bfd.type = raw.vartype; @@ -628,17 +632,17 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { for (BuilderFieldData bfd : builderFields) { if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.name, "this"); + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.builderFieldName, "this"); } } ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); for (BuilderFieldData bfd : builderFields) { if (bfd.nameOfSetFlag != null) { - statements.append(maker.VarDef(maker.Modifiers(0L), bfd.name, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(type.toName("this")), bfd.name))); - statements.append(maker.If(maker.Unary(CTC_NOT, maker.Ident(bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.name),maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null)); + statements.append(maker.VarDef(maker.Modifiers(0L), bfd.builderFieldName, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(type.toName("this")), bfd.builderFieldName))); + statements.append(maker.If(maker.Unary(CTC_NOT, maker.Ident(bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.builderFieldName), maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null)); } - args.append(maker.Ident(bfd.name)); + args.append(maker.Ident(bfd.builderFieldName)); } if (addCleaning) { @@ -715,13 +719,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { JavacNode field = null, setFlag = null; for (JavacNode exists : existing) { Name n = ((JCVariableDecl) exists.get()).name; - if (n.equals(bfd.name)) field = exists; + if (n.equals(bfd.builderFieldName)) field = exists; if (n.equals(bfd.nameOfSetFlag)) setFlag = exists; } JavacTreeMaker maker = builderType.getTreeMaker(); if (field == null) { JCModifiers mods = maker.Modifiers(Flags.PRIVATE); - JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null); + JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source, builderType.getContext()), null); field = injectFieldAndMarkGenerated(builderType, newField); generated.add(newField); } @@ -740,13 +744,13 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access) { boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode); if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { - makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access); + makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access); } else { fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access); } } - - private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access) { + + private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access) { Name fieldName = ((JCVariableDecl) fieldNode.get()).name; for (JavacNode child : builderType.down()) { @@ -756,12 +760,12 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) return; } - String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName()); + String setterName = fluent ? paramName.toString() : HandlerUtil.buildAccessorName("set", paramName.toString()); JavacTreeMaker maker = fieldNode.getTreeMaker(); List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); - JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, nameOfSetFlag, chain, source, methodAnns, annosOnParam); + JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam); recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext()); copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER); @@ -771,14 +775,14 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { public void makePrefixedSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain, AccessLevel access, String prefix) { boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode); if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { - makePrefixedSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access, prefix); + makePrefixedSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, fluent, chain, fieldNode.annotations, fieldNode.originalFieldNode, access, prefix); } else { // TODO prefixed version fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain, access); } } - private void makePrefixedSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access, String prefix) { + private void makePrefixedSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode, AccessLevel access, String prefix) { Name fieldName = ((JCVariableDecl) fieldNode.get()).name; for (JavacNode child : builderType.down()) { @@ -791,15 +795,15 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> { String setterPrefix = prefix.isEmpty() ? "set" : prefix; String setterName; if(fluent) { - setterName = prefix.isEmpty() ? fieldNode.getName() : HandlerUtil.buildAccessorName(setterPrefix, fieldNode.getName()); + setterName = prefix.isEmpty() ? paramName.toString() : HandlerUtil.buildAccessorName(setterPrefix, paramName.toString()); } else { - setterName = HandlerUtil.buildAccessorName(setterPrefix, fieldNode.getName()); + setterName = HandlerUtil.buildAccessorName(setterPrefix, paramName.toString()); } JavacTreeMaker maker = fieldNode.getTreeMaker(); List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); - JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, nameOfSetFlag, chain, source, methodAnns, annosOnParam); + JCMethodDecl newMethod = HandleSetter.createSetter(toJavacModifier(access), deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, chain, source, methodAnns, annosOnParam); recursiveSetGeneratedBy(newMethod, source.get(), builderType.getContext()); copyJavadoc(originalFieldNode, newMethod, CopyJavadoc.SETTER); diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java index e0456782..096963f4 100644 --- a/src/core/lombok/javac/handlers/HandleConstructor.java +++ b/src/core/lombok/javac/handlers/HandleConstructor.java @@ -342,7 +342,7 @@ public class HandleConstructor { JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, copyableAnnotations), fieldName, field.vartype, null); params.append(param); if (hasNonNullAnnotations(fieldNode)) { - JCStatement nullCheck = generateNullCheck(maker, fieldNode, param, source); + JCStatement nullCheck = generateNullCheck(maker, param, source); if (nullCheck != null) nullChecks.append(nullCheck); } JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), rawName); diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java index 49b987ce..079d5b04 100644 --- a/src/core/lombok/javac/handlers/HandleNonNull.java +++ b/src/core/lombok/javac/handlers/HandleNonNull.java @@ -31,13 +31,17 @@ import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.tree.JCTree.JCAnnotation; import com.sun.tools.javac.tree.JCTree.JCAssert; +import com.sun.tools.javac.tree.JCTree.JCAssign; import com.sun.tools.javac.tree.JCTree.JCBinary; import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; +import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; import com.sun.tools.javac.tree.JCTree.JCParens; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCSynchronized; @@ -45,6 +49,7 @@ import com.sun.tools.javac.tree.JCTree.JCThrow; import com.sun.tools.javac.tree.JCTree.JCTry; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Name; import lombok.ConfigurationKeys; import lombok.NonNull; @@ -167,8 +172,31 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> { * If it is not of this form, returns null. */ public String returnVarNameIfNullCheck(JCStatement stat) { - boolean isIf = stat instanceof JCIf; - if (!isIf && !(stat instanceof JCAssert)) return null; + boolean isIf = stat instanceof JCIf; + boolean isExpression = stat instanceof JCExpressionStatement; + if (!isIf && !(stat instanceof JCAssert) && !isExpression) return null; + + if (isExpression) { + /* Check if the statements contains a call to checkNotNull or requireNonNull */ + JCExpression expression = ((JCExpressionStatement) stat).expr; + if (expression instanceof JCAssign) expression = ((JCAssign) expression).rhs; + if (!(expression instanceof JCMethodInvocation)) return null; + + JCMethodInvocation invocation = (JCMethodInvocation) expression; + JCExpression method = invocation.meth; + Name name = null; + if (method instanceof JCFieldAccess) { + name = ((JCFieldAccess) method).name; + } else if (method instanceof JCIdent) { + name = ((JCIdent) method).name; + } + if (name == null || (!name.contentEquals("checkNotNull") && !name.contentEquals("requireNonNull"))) return null; + + if (invocation.args.isEmpty()) return null; + JCExpression firstArgument = invocation.args.head; + if (!(firstArgument instanceof JCIdent)) return null; + return ((JCIdent) firstArgument).toString(); + } if (isIf) { /* Check that the if's statement is a throw statement, possibly in a block. */ diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java index 5482cccc..cd8b5d1c 100644 --- a/src/core/lombok/javac/handlers/HandleSetter.java +++ b/src/core/lombok/javac/handlers/HandleSetter.java @@ -203,10 +203,10 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { String setterName = toSetterName(field); boolean returnThis = shouldReturnThis(field); - return createSetter(access, false, field, treeMaker, setterName, null, returnThis, source, onMethod, onParam); + return createSetter(access, false, field, treeMaker, setterName, null, null, returnThis, source, onMethod, onParam); } - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { JCExpression returnType = null; JCReturn returnStatement = null; if (shouldReturnThis) { @@ -214,16 +214,17 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { returnStatement = treeMaker.Return(treeMaker.Ident(field.toName("this"))); } - return createSetter(access, deprecate, field, treeMaker, setterName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam); + return createSetter(access, deprecate, field, treeMaker, setterName, paramName, booleanFieldToSet, returnType, returnStatement, source, onMethod, onParam); } - public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { + public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name paramName, Name booleanFieldToSet, JCExpression methodType, JCStatement returnStatement, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) { if (setterName == null) return null; JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); + if (paramName == null) paramName = fieldDecl.name; JCExpression fieldRef = createFieldAccessor(treeMaker, field, FieldAccess.ALWAYS_FIELD); - JCAssign assign = treeMaker.Assign(fieldRef, treeMaker.Ident(fieldDecl.name)); + JCAssign assign = treeMaker.Assign(fieldRef, treeMaker.Ident(paramName)); ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>(); List<JCAnnotation> copyableAnnotations = findCopyableAnnotations(field); @@ -232,12 +233,12 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(copyableAnnotations); long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext()); - JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null); + JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(flags, annsOnParam), paramName, fieldDecl.vartype, null); if (!hasNonNullAnnotations(field) && !hasNonNullAnnotations(field, onParam)) { statements.append(treeMaker.Exec(assign)); } else { - JCStatement nullCheck = generateNullCheck(treeMaker, field, source); + JCStatement nullCheck = generateNullCheck(treeMaker, fieldDecl.vartype, paramName, source); if (nullCheck != null) statements.append(nullCheck); statements.append(treeMaker.Exec(assign)); } @@ -267,7 +268,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> { } JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType, - methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext()); + methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext()); copyJavadoc(field, decl, CopyJavadoc.SETTER); return decl; } diff --git a/src/core/lombok/javac/handlers/HandleSuperBuilder.java b/src/core/lombok/javac/handlers/HandleSuperBuilder.java index 9120fa07..a5c492a1 100644 --- a/src/core/lombok/javac/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/javac/handlers/HandleSuperBuilder.java @@ -142,6 +142,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { BuilderFieldData bfd = new BuilderFieldData(); bfd.rawName = fd.name; bfd.name = removePrefixFromField(fieldNode); + bfd.builderFieldName = bfd.name; bfd.annotations = findCopyableAnnotations(fieldNode); bfd.type = fd.vartype; bfd.singularData = getSingularData(fieldNode); @@ -166,7 +167,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { if (isDefault != null) { bfd.nameOfDefaultProvider = tdParent.toName("$default$" + bfd.name); bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set"); - bfd.nameOfSetFlag = tdParent.toName(bfd.name + "$set"); + bfd.builderFieldName = tdParent.toName(bfd.name + "$value"); JCMethodDecl md = HandleBuilder.generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); if (md != null) injectMethod(tdParent, md); @@ -493,10 +494,10 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { for (BuilderFieldData bfd : builderFields) { JCExpression rhs; if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) { - bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.name, "b"); + bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, bfd.originalFieldNode, bfd.type, statements, bfd.builderFieldName, "b"); rhs = maker.Ident(bfd.singularData.getPluralName()); } else { - rhs = maker.Select(maker.Ident(builderVariableName), bfd.name); + rhs = maker.Select(maker.Ident(builderVariableName), bfd.builderFieldName); } JCFieldAccess fieldInThis = maker.Select(maker.Ident(typeNode.toName("this")), bfd.rawName); @@ -829,13 +830,13 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { JavacNode field = null, setFlag = null; for (JavacNode exists : existing) { Name n = ((JCVariableDecl) exists.get()).name; - if (n.equals(bfd.name)) field = exists; + if (n.equals(bfd.builderFieldName)) field = exists; if (n.equals(bfd.nameOfSetFlag)) setFlag = exists; } JavacTreeMaker maker = builderType.getTreeMaker(); if (field == null) { JCModifiers mods = maker.Modifiers(Flags.PRIVATE); - JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null); + JCVariableDecl newField = maker.VarDef(mods, bfd.builderFieldName, cloneType(maker, bfd.type, source, builderType.getContext()), null); field = injectFieldAndMarkGenerated(builderType, newField); generated.add(newField); } @@ -863,13 +864,13 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { }}; if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) { - generateSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, true, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode); + generateSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.name, fieldNode.nameOfSetFlag, source, true, returnTypeMaker.make(), returnStatementMaker.make(), fieldNode.annotations, fieldNode.originalFieldNode); } else { fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC); } } - private void generateSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode) { + private void generateSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name paramName, Name nameOfSetFlag, JavacNode source, boolean fluent, JCExpression returnType, JCStatement returnStatement, List<JCAnnotation> annosOnParam, JavacNode originalFieldNode) { Name fieldName = ((JCVariableDecl) fieldNode.get()).name; for (JavacNode child : builderType.down()) { @@ -879,12 +880,12 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> { if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) return; } - String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName()); + String setterName = fluent ? paramName.toString() : HandlerUtil.buildAccessorName("set", paramName.toString()); JavacTreeMaker maker = fieldNode.getTreeMaker(); List<JCAnnotation> methodAnns = JavacHandlerUtil.findCopyableToSetterAnnotations(originalFieldNode); - JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, returnType, returnStatement, source, methodAnns, annosOnParam); + JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, paramName, nameOfSetFlag, returnType, returnStatement, source, methodAnns, annosOnParam); injectMethod(builderType, newMethod); } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 6fa70ff3..5f0f39b0 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -1516,34 +1516,46 @@ public class JavacHandlerUtil { * variable name as message. */ public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JavacNode source) { - return generateNullCheck(maker, variable, (JCVariableDecl) variable.get(), source); + return generateNullCheck(maker, (JCVariableDecl) variable.get(), source); } - + /** - * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the - * variable name as message. - * - * This is a special case method reserved for use when the provided declaration differs from the - * variable's declaration, i.e. in a constructor or setter where the local parameter is named the same but with the prefix - * stripped as a result of @Accessors.prefix. + * Generates a new statement that checks if the given local is null, and if so, throws a configured exception with the + * local variable name as message. */ - public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JCVariableDecl varDecl, JavacNode source) { + public static JCStatement generateNullCheck(JavacTreeMaker maker, JCExpression typeNode, Name varName, JavacNode source) { NullCheckExceptionType exceptionType = source.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE); if (exceptionType == null) exceptionType = NullCheckExceptionType.NULL_POINTER_EXCEPTION; - if (isPrimitive(varDecl.vartype)) return null; - Name fieldName = varDecl.name; + if (isPrimitive(typeNode)) return null; + JCLiteral message = maker.Literal(exceptionType.toExceptionMessage(varName.toString())); + + LombokImmutableList<String> method = exceptionType.getMethod(); + if (method != null) { + return maker.Exec(maker.Apply(List.<JCExpression>nil(), chainDots(source, method), List.of(maker.Ident(varName), message))); + } - JCLiteral message = maker.Literal(exceptionType.toExceptionMessage(fieldName.toString())); if (exceptionType == NullCheckExceptionType.ASSERTION) { - return maker.Assert(maker.Binary(CTC_NOT_EQUAL, maker.Ident(fieldName), maker.Literal(CTC_BOT, null)), message); + return maker.Assert(maker.Binary(CTC_NOT_EQUAL, maker.Ident(varName), maker.Literal(CTC_BOT, null)), message); } - JCExpression exType = genTypeRef(variable, exceptionType.getExceptionType()); + JCExpression exType = genTypeRef(source, exceptionType.getExceptionType()); JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), exType, List.<JCExpression>of(message), null); JCStatement throwStatement = maker.Throw(exception); JCBlock throwBlock = maker.Block(0, List.of(throwStatement)); - return maker.If(maker.Binary(CTC_EQUAL, maker.Ident(fieldName), maker.Literal(CTC_BOT, null)), throwBlock, null); + return maker.If(maker.Binary(CTC_EQUAL, maker.Ident(varName), maker.Literal(CTC_BOT, null)), throwBlock, null); + } + + /** + * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the + * variable name as message. + * + * This is a special case method reserved for use when the provided declaration differs from the + * variable's declaration, i.e. in a constructor or setter where the local parameter is named the same but with the prefix + * stripped as a result of @Accessors.prefix. + */ + public static JCStatement generateNullCheck(JavacTreeMaker maker, JCVariableDecl varDecl, JavacNode source) { + return generateNullCheck(maker, varDecl.vartype, varDecl.name, source); } /** diff --git a/src/utils/lombok/eclipse/Eclipse.java b/src/utils/lombok/eclipse/Eclipse.java index 5b3c453e..31f2518a 100644 --- a/src/utils/lombok/eclipse/Eclipse.java +++ b/src/utils/lombok/eclipse/Eclipse.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2013 The Project Lombok Authors. + * Copyright (C) 2009-2019 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 @@ -29,10 +29,13 @@ import java.util.regex.Pattern; import lombok.core.ClassLiteral; import lombok.core.FieldSelect; +import lombok.permit.Permit; + import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.CaseStatement; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.Clinit; import org.eclipse.jdt.internal.compiler.ast.Expression; @@ -262,4 +265,23 @@ public class Eclipse { return false; } } + + private static boolean caseStatementInit = false; + private static Field caseStatementConstantExpressions = null; + public static CaseStatement createCaseStatement(Expression expr) { + CaseStatement stat = new CaseStatement(expr, 0, 0); + if (expr == null) return stat; + if (!caseStatementInit) { + try { + caseStatementConstantExpressions = Permit.getField(CaseStatement.class, "constantExpressions"); + caseStatementConstantExpressions.setAccessible(true); + } catch (NoSuchFieldException ignore) {} + caseStatementInit = true; + } + if (caseStatementConstantExpressions != null) try { + caseStatementConstantExpressions.set(stat, new Expression[] {expr}); + } catch (IllegalArgumentException ignore) { + } catch (IllegalAccessException ignore) {} + return stat; + } } diff --git a/test/stubs/com/fasterxml/jackson/annotation/JsonSetter.java b/test/stubs/com/fasterxml/jackson/annotation/JsonSetter.java new file mode 100644 index 00000000..2886a6f4 --- /dev/null +++ b/test/stubs/com/fasterxml/jackson/annotation/JsonSetter.java @@ -0,0 +1,12 @@ +package com.fasterxml.jackson.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +public @interface JsonSetter { + Nulls nulls(); +} diff --git a/test/stubs/com/fasterxml/jackson/annotation/Nulls.java b/test/stubs/com/fasterxml/jackson/annotation/Nulls.java new file mode 100644 index 00000000..d40bd46d --- /dev/null +++ b/test/stubs/com/fasterxml/jackson/annotation/Nulls.java @@ -0,0 +1,5 @@ +package com.fasterxml.jackson.annotation; + +public enum Nulls { + SKIP; +} diff --git a/test/transform/resource/after-delombok/BuilderDefaults.java b/test/transform/resource/after-delombok/BuilderDefaults.java index b916b725..475b3f3c 100644 --- a/test/transform/resource/after-delombok/BuilderDefaults.java +++ b/test/transform/resource/after-delombok/BuilderDefaults.java @@ -21,19 +21,19 @@ public final class BuilderDefaults { @java.lang.SuppressWarnings("all") private boolean x$set; @java.lang.SuppressWarnings("all") - private int x; + private int x$value; @java.lang.SuppressWarnings("all") private String name; @java.lang.SuppressWarnings("all") private boolean z$set; @java.lang.SuppressWarnings("all") - private long z; + private long z$value; @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder() { } @java.lang.SuppressWarnings("all") public BuilderDefaultsBuilder x(final int x) { - this.x = x; + this.x$value = x; x$set = true; return this; } @@ -44,22 +44,22 @@ public final class BuilderDefaults { } @java.lang.SuppressWarnings("all") public BuilderDefaultsBuilder z(final long z) { - this.z = z; + this.z$value = z; z$set = true; return this; } @java.lang.SuppressWarnings("all") public BuilderDefaults build() { - int x = this.x; - if (!x$set) x = BuilderDefaults.$default$x(); - long z = this.z; - if (!z$set) z = BuilderDefaults.$default$z(); - return new BuilderDefaults(x, name, z); + int x$value = this.x$value; + if (!x$set) x$value = BuilderDefaults.$default$x(); + long z$value = this.z$value; + if (!z$set) z$value = BuilderDefaults.$default$z(); + return new BuilderDefaults(x$value, name, z$value); } @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { - return "BuilderDefaults.BuilderDefaultsBuilder(x=" + this.x + ", name=" + this.name + ", z=" + this.z + ")"; + return "BuilderDefaults.BuilderDefaultsBuilder(x$value=" + this.x$value + ", name=" + this.name + ", z$value=" + this.z$value + ")"; } } @java.lang.SuppressWarnings("all") diff --git a/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java b/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java index b88a61be..46fcd6b4 100644 --- a/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java +++ b/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java @@ -26,50 +26,50 @@ public class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> { @java.lang.SuppressWarnings("all") private boolean callable$set; @java.lang.SuppressWarnings("all") - private java.util.concurrent.Callable<N> callable; + private java.util.concurrent.Callable<N> callable$value; @java.lang.SuppressWarnings("all") private boolean tee$set; @java.lang.SuppressWarnings("all") - private T tee; + private T tee$value; @java.lang.SuppressWarnings("all") private boolean arrr$set; @java.lang.SuppressWarnings("all") - private R arrr; + private R arrr$value; @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder() { } @java.lang.SuppressWarnings("all") public BuilderDefaultsGenericsBuilder<N, T, R> callable(final java.util.concurrent.Callable<N> callable) { - this.callable = callable; + this.callable$value = callable; callable$set = true; return this; } @java.lang.SuppressWarnings("all") public BuilderDefaultsGenericsBuilder<N, T, R> tee(final T tee) { - this.tee = tee; + this.tee$value = tee; tee$set = true; return this; } @java.lang.SuppressWarnings("all") public BuilderDefaultsGenericsBuilder<N, T, R> arrr(final R arrr) { - this.arrr = arrr; + this.arrr$value = arrr; arrr$set = true; return this; } @java.lang.SuppressWarnings("all") public BuilderDefaultsGenerics<N, T, R> build() { - java.util.concurrent.Callable<N> callable = this.callable; - if (!callable$set) callable = BuilderDefaultsGenerics.<N, T, R>$default$callable(); - T tee = this.tee; - if (!tee$set) tee = BuilderDefaultsGenerics.<N, T, R>$default$tee(); - R arrr = this.arrr; - if (!arrr$set) arrr = BuilderDefaultsGenerics.<N, T, R>$default$arrr(); - return new BuilderDefaultsGenerics<N, T, R>(callable, tee, arrr); + java.util.concurrent.Callable<N> callable$value = this.callable$value; + if (!callable$set) callable$value = BuilderDefaultsGenerics.<N, T, R>$default$callable(); + T tee$value = this.tee$value; + if (!tee$set) tee$value = BuilderDefaultsGenerics.<N, T, R>$default$tee(); + R arrr$value = this.arrr$value; + if (!arrr$set) arrr$value = BuilderDefaultsGenerics.<N, T, R>$default$arrr(); + return new BuilderDefaultsGenerics<N, T, R>(callable$value, tee$value, arrr$value); } @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { - return "BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable=" + this.callable + ", tee=" + this.tee + ", arrr=" + this.arrr + ")"; + return "BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable$value=" + this.callable$value + ", tee$value=" + this.tee$value + ", arrr$value=" + this.arrr$value + ")"; } } @java.lang.SuppressWarnings("all") diff --git a/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults.java b/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults.java index 91f5b8be..f37c68af 100644 --- a/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults.java +++ b/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults.java @@ -10,7 +10,7 @@ final class ConstructorsWithBuilderDefaults { @java.lang.SuppressWarnings("all") private boolean x$set; @java.lang.SuppressWarnings("all") - private int x; + private int x$value; @java.lang.SuppressWarnings("all") private int y; @java.lang.SuppressWarnings("all") @@ -18,7 +18,7 @@ final class ConstructorsWithBuilderDefaults { } @java.lang.SuppressWarnings("all") public ConstructorsWithBuilderDefaultsBuilder x(final int x) { - this.x = x; + this.x$value = x; x$set = true; return this; } @@ -29,14 +29,14 @@ final class ConstructorsWithBuilderDefaults { } @java.lang.SuppressWarnings("all") public ConstructorsWithBuilderDefaults build() { - int x = this.x; - if (!x$set) x = ConstructorsWithBuilderDefaults.$default$x(); - return new ConstructorsWithBuilderDefaults(x, y); + int x$value = this.x$value; + if (!x$set) x$value = ConstructorsWithBuilderDefaults.$default$x(); + return new ConstructorsWithBuilderDefaults(x$value, y); } @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { - return "ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(x=" + this.x + ", y=" + this.y + ")"; + return "ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(x$value=" + this.x$value + ", y=" + this.y + ")"; } } @java.lang.SuppressWarnings("all") diff --git a/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults2.java b/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults2.java index 8a9c9b48..7816b0c8 100644 --- a/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults2.java +++ b/test/transform/resource/after-delombok/ConstructorsWithBuilderDefaults2.java @@ -23,11 +23,11 @@ final class ConstructorsWithBuilderDefaults<T> { @java.lang.SuppressWarnings("all") private boolean z$set; @java.lang.SuppressWarnings("all") - private java.util.List<T> z; + private java.util.List<T> z$value; @java.lang.SuppressWarnings("all") private boolean x$set; @java.lang.SuppressWarnings("all") - private T x; + private T x$value; @java.lang.SuppressWarnings("all") private T q; @java.lang.SuppressWarnings("all") @@ -35,13 +35,13 @@ final class ConstructorsWithBuilderDefaults<T> { } @java.lang.SuppressWarnings("all") public ConstructorsWithBuilderDefaultsBuilder<T> z(final java.util.List<T> z) { - this.z = z; + this.z$value = z; z$set = true; return this; } @java.lang.SuppressWarnings("all") public ConstructorsWithBuilderDefaultsBuilder<T> x(final T x) { - this.x = x; + this.x$value = x; x$set = true; return this; } @@ -53,16 +53,16 @@ final class ConstructorsWithBuilderDefaults<T> { @java.lang.SuppressWarnings("all") public ConstructorsWithBuilderDefaults<T> build() { - java.util.List<T> z = this.z; - if (!z$set) z = ConstructorsWithBuilderDefaults.<T>$default$z(); - T x = this.x; - if (!x$set) x = ConstructorsWithBuilderDefaults.<T>$default$x(); - return new ConstructorsWithBuilderDefaults<T>(z, x, q); + java.util.List<T> z$value = this.z$value; + if (!z$set) z$value = ConstructorsWithBuilderDefaults.<T>$default$z(); + T x$value = this.x$value; + if (!x$set) x$value = ConstructorsWithBuilderDefaults.<T>$default$x(); + return new ConstructorsWithBuilderDefaults<T>(z$value, x$value, q); } @java.lang.Override @java.lang.SuppressWarnings("all") public java.lang.String toString() { - return "ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(z=" + this.z + ", x=" + this.x + ", q=" + this.q + ")"; + return "ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(z$value=" + this.z$value + ", x$value=" + this.x$value + ", q=" + this.q + ")"; } } @java.lang.SuppressWarnings("all") diff --git a/test/transform/resource/after-delombok/JacksonJsonProperty.java b/test/transform/resource/after-delombok/JacksonJsonProperty.java index 842ba298..16a8039e 100644 --- a/test/transform/resource/after-delombok/JacksonJsonProperty.java +++ b/test/transform/resource/after-delombok/JacksonJsonProperty.java @@ -1,6 +1,9 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; public class JacksonJsonProperty { @JsonProperty("kebab-case-prop") + @JsonSetter(nulls = Nulls.SKIP) public String kebabCaseProp; @java.lang.SuppressWarnings("all") JacksonJsonProperty(final String kebabCaseProp) { @@ -14,6 +17,7 @@ public class JacksonJsonProperty { JacksonJsonPropertyBuilder() { } @JsonProperty("kebab-case-prop") + @JsonSetter(nulls = Nulls.SKIP) @java.lang.SuppressWarnings("all") public JacksonJsonPropertyBuilder kebabCaseProp(final String kebabCaseProp) { this.kebabCaseProp = kebabCaseProp; @@ -34,6 +38,7 @@ public class JacksonJsonProperty { return new JacksonJsonPropertyBuilder(); } @JsonProperty("kebab-case-prop") + @JsonSetter(nulls = Nulls.SKIP) @java.lang.SuppressWarnings("all") public void setKebabCaseProp(final String kebabCaseProp) { this.kebabCaseProp = kebabCaseProp; diff --git a/test/transform/resource/after-delombok/NonNullWithGuava.java b/test/transform/resource/after-delombok/NonNullWithGuava.java new file mode 100644 index 00000000..b3c13d30 --- /dev/null +++ b/test/transform/resource/after-delombok/NonNullWithGuava.java @@ -0,0 +1,35 @@ +import static com.google.common.base.Preconditions.*; +public class NonNullWithGuava { + @lombok.NonNull + private String test; + public void testMethod(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + System.out.println(arg); + } + public void testMethodWithCheck1(@lombok.NonNull String arg) { + checkNotNull(arg); + } + public void testMethodWithCheckAssign(@lombok.NonNull String arg) { + test = checkNotNull(arg); + } + public void testMethodWithCheck2(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg); + } + public void testMethodWithFakeCheck1(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + checkNotNull(""); + } + public void testMethodWithFakeCheck2(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + com.google.common.base.Preconditions.checkNotNull(test); + } + public void testMethodWithFakeCheckAssign(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + test = checkNotNull(test); + } + @java.lang.SuppressWarnings("all") + public void setTest(@lombok.NonNull final String test) { + com.google.common.base.Preconditions.checkNotNull(test, "test is marked non-null but is null"); + this.test = test; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/NonNullWithJdk.java b/test/transform/resource/after-delombok/NonNullWithJdk.java new file mode 100644 index 00000000..d7e2958c --- /dev/null +++ b/test/transform/resource/after-delombok/NonNullWithJdk.java @@ -0,0 +1,36 @@ +//version 7: +import static java.util.Objects.*; +public class NonNullWithJdk { + @lombok.NonNull + private String test; + public void testMethod(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + System.out.println(arg); + } + public void testMethodWithCheck1(@lombok.NonNull String arg) { + requireNonNull(arg); + } + public void testMethodWithCheckAssign(@lombok.NonNull String arg) { + test = requireNonNull(arg); + } + public void testMethodWithCheck2(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg); + } + public void testMethodWithFakeCheck1(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + requireNonNull(""); + } + public void testMethodWithFakeCheck2(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + java.util.Objects.requireNonNull(test); + } + public void testMethodWithFakeCheckAssign(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + test = requireNonNull(test); + } + @java.lang.SuppressWarnings("all") + public void setTest(@lombok.NonNull final String test) { + java.util.Objects.requireNonNull(test, "test is marked non-null but is null"); + this.test = test; + } +}
\ No newline at end of file diff --git a/test/transform/resource/after-delombok/SuperBuilderWithDefaults.java b/test/transform/resource/after-delombok/SuperBuilderWithDefaults.java index 842b7e55..2ac3d1b7 100644 --- a/test/transform/resource/after-delombok/SuperBuilderWithDefaults.java +++ b/test/transform/resource/after-delombok/SuperBuilderWithDefaults.java @@ -16,31 +16,31 @@ public class SuperBuilderWithDefaults { @java.lang.SuppressWarnings("all")
private boolean millis$set;
@java.lang.SuppressWarnings("all")
- private long millis;
+ private long millis$value;
@java.lang.SuppressWarnings("all")
private boolean numberField$set;
@java.lang.SuppressWarnings("all")
- private N numberField;
+ private N numberField$value;
@java.lang.SuppressWarnings("all")
protected abstract B self();
@java.lang.SuppressWarnings("all")
public abstract C build();
@java.lang.SuppressWarnings("all")
public B millis(final long millis) {
- this.millis = millis;
+ this.millis$value = millis;
millis$set = true;
return self();
}
@java.lang.SuppressWarnings("all")
public B numberField(final N numberField) {
- this.numberField = numberField;
+ this.numberField$value = numberField;
numberField$set = true;
return self();
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
- return "SuperBuilderWithDefaults.Parent.ParentBuilder(millis=" + this.millis + ", numberField=" + this.numberField + ")";
+ return "SuperBuilderWithDefaults.Parent.ParentBuilder(millis$value=" + this.millis$value + ", numberField$value=" + this.numberField$value + ")";
}
}
@java.lang.SuppressWarnings("all")
@@ -61,9 +61,9 @@ public class SuperBuilderWithDefaults { }
@java.lang.SuppressWarnings("all")
protected Parent(final ParentBuilder<N, ?, ?> b) {
- if (b.millis$set) this.millis = b.millis;
+ if (b.millis$set) this.millis = b.millis$value;
else this.millis = Parent.<N>$default$millis();
- if (b.numberField$set) this.numberField = b.numberField;
+ if (b.numberField$set) this.numberField = b.numberField$value;
else this.numberField = Parent.<N>$default$numberField();
}
@java.lang.SuppressWarnings("all")
@@ -82,7 +82,7 @@ public class SuperBuilderWithDefaults { @java.lang.SuppressWarnings("all")
private boolean doubleField$set;
@java.lang.SuppressWarnings("all")
- private double doubleField;
+ private double doubleField$value;
@java.lang.Override
@java.lang.SuppressWarnings("all")
protected abstract B self();
@@ -91,14 +91,14 @@ public class SuperBuilderWithDefaults { public abstract C build();
@java.lang.SuppressWarnings("all")
public B doubleField(final double doubleField) {
- this.doubleField = doubleField;
+ this.doubleField$value = doubleField;
doubleField$set = true;
return self();
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
- return "SuperBuilderWithDefaults.Child.ChildBuilder(super=" + super.toString() + ", doubleField=" + this.doubleField + ")";
+ return "SuperBuilderWithDefaults.Child.ChildBuilder(super=" + super.toString() + ", doubleField$value=" + this.doubleField$value + ")";
}
}
@java.lang.SuppressWarnings("all")
@@ -120,7 +120,7 @@ public class SuperBuilderWithDefaults { @java.lang.SuppressWarnings("all")
protected Child(final ChildBuilder<?, ?> b) {
super(b);
- if (b.doubleField$set) this.doubleField = b.doubleField;
+ if (b.doubleField$set) this.doubleField = b.doubleField$value;
else this.doubleField = Child.$default$doubleField();
}
@java.lang.SuppressWarnings("all")
diff --git a/test/transform/resource/after-delombok/SuperBuilderWithNonNull.java b/test/transform/resource/after-delombok/SuperBuilderWithNonNull.java index ce5c838c..52328780 100644 --- a/test/transform/resource/after-delombok/SuperBuilderWithNonNull.java +++ b/test/transform/resource/after-delombok/SuperBuilderWithNonNull.java @@ -12,7 +12,7 @@ public class SuperBuilderWithNonNull { @java.lang.SuppressWarnings("all")
private boolean nonNullParentField$set;
@java.lang.SuppressWarnings("all")
- private String nonNullParentField;
+ private String nonNullParentField$value;
@java.lang.SuppressWarnings("all")
protected abstract B self();
@java.lang.SuppressWarnings("all")
@@ -22,14 +22,14 @@ public class SuperBuilderWithNonNull { if (nonNullParentField == null) {
throw new java.lang.NullPointerException("nonNullParentField is marked non-null but is null");
}
- this.nonNullParentField = nonNullParentField;
+ this.nonNullParentField$value = nonNullParentField;
nonNullParentField$set = true;
return self();
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
- return "SuperBuilderWithNonNull.Parent.ParentBuilder(nonNullParentField=" + this.nonNullParentField + ")";
+ return "SuperBuilderWithNonNull.Parent.ParentBuilder(nonNullParentField$value=" + this.nonNullParentField$value + ")";
}
}
@java.lang.SuppressWarnings("all")
@@ -50,7 +50,7 @@ public class SuperBuilderWithNonNull { }
@java.lang.SuppressWarnings("all")
protected Parent(final ParentBuilder<?, ?> b) {
- if (b.nonNullParentField$set) this.nonNullParentField = b.nonNullParentField;
+ if (b.nonNullParentField$set) this.nonNullParentField = b.nonNullParentField$value;
else this.nonNullParentField = Parent.$default$nonNullParentField();
if (nonNullParentField == null) {
throw new java.lang.NullPointerException("nonNullParentField is marked non-null but is null");
diff --git a/test/transform/resource/after-ecj/BuilderDefaults.java b/test/transform/resource/after-ecj/BuilderDefaults.java index 1a0f1168..b9588386 100644 --- a/test/transform/resource/after-ecj/BuilderDefaults.java +++ b/test/transform/resource/after-ecj/BuilderDefaults.java @@ -2,16 +2,16 @@ import lombok.Builder; import lombok.Value; public final @Value @Builder class BuilderDefaults { public static @java.lang.SuppressWarnings("all") class BuilderDefaultsBuilder { - private @java.lang.SuppressWarnings("all") int x; + private @java.lang.SuppressWarnings("all") int x$value; private @java.lang.SuppressWarnings("all") boolean x$set; private @java.lang.SuppressWarnings("all") String name; - private @java.lang.SuppressWarnings("all") long z; + private @java.lang.SuppressWarnings("all") long z$value; private @java.lang.SuppressWarnings("all") boolean z$set; @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder() { super(); } public @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder x(final int x) { - this.x = x; + this.x$value = x; x$set = true; return this; } @@ -20,15 +20,15 @@ public final @Value @Builder class BuilderDefaults { return this; } public @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder z(final long z) { - this.z = z; + this.z$value = z; z$set = true; return this; } public @java.lang.SuppressWarnings("all") BuilderDefaults build() { - return new BuilderDefaults((x$set ? x : BuilderDefaults.$default$x()), name, (z$set ? z : BuilderDefaults.$default$z())); + return new BuilderDefaults((x$set ? x$value : BuilderDefaults.$default$x()), name, (z$set ? z$value : BuilderDefaults.$default$z())); } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (((((("BuilderDefaults.BuilderDefaultsBuilder(x=" + this.x) + ", name=") + this.name) + ", z=") + this.z) + ")"); + return (((((("BuilderDefaults.BuilderDefaultsBuilder(x$value=" + this.x$value) + ", name=") + this.name) + ", z$value=") + this.z$value) + ")"); } } private final @Builder.Default int x; diff --git a/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java b/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java index a8f81afa..8f9da4b3 100644 --- a/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java +++ b/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java @@ -2,35 +2,35 @@ import lombok.Builder; import java.util.*; public @Builder class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> { public static @java.lang.SuppressWarnings("all") class BuilderDefaultsGenericsBuilder<N extends Number, T, R extends List<T>> { - private @java.lang.SuppressWarnings("all") java.util.concurrent.Callable<N> callable; + private @java.lang.SuppressWarnings("all") java.util.concurrent.Callable<N> callable$value; private @java.lang.SuppressWarnings("all") boolean callable$set; - private @java.lang.SuppressWarnings("all") T tee; + private @java.lang.SuppressWarnings("all") T tee$value; private @java.lang.SuppressWarnings("all") boolean tee$set; - private @java.lang.SuppressWarnings("all") R arrr; + private @java.lang.SuppressWarnings("all") R arrr$value; private @java.lang.SuppressWarnings("all") boolean arrr$set; @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder() { super(); } public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> callable(final java.util.concurrent.Callable<N> callable) { - this.callable = callable; + this.callable$value = callable; callable$set = true; return this; } public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> tee(final T tee) { - this.tee = tee; + this.tee$value = tee; tee$set = true; return this; } public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> arrr(final R arrr) { - this.arrr = arrr; + this.arrr$value = arrr; arrr$set = true; return this; } public @java.lang.SuppressWarnings("all") BuilderDefaultsGenerics<N, T, R> build() { - return new BuilderDefaultsGenerics<N, T, R>((callable$set ? callable : BuilderDefaultsGenerics.<N, T, R>$default$callable()), (tee$set ? tee : BuilderDefaultsGenerics.<N, T, R>$default$tee()), (arrr$set ? arrr : BuilderDefaultsGenerics.<N, T, R>$default$arrr())); + return new BuilderDefaultsGenerics<N, T, R>((callable$set ? callable$value : BuilderDefaultsGenerics.<N, T, R>$default$callable()), (tee$set ? tee$value : BuilderDefaultsGenerics.<N, T, R>$default$tee()), (arrr$set ? arrr$value : BuilderDefaultsGenerics.<N, T, R>$default$arrr())); } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (((((("BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable=" + this.callable) + ", tee=") + this.tee) + ", arrr=") + this.arrr) + ")"); + return (((((("BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable$value=" + this.callable$value) + ", tee$value=") + this.tee$value) + ", arrr$value=") + this.arrr$value) + ")"); } } private @Builder.Default java.util.concurrent.Callable<N> callable; diff --git a/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults.java b/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults.java index 9d4c42c1..fd860c69 100644 --- a/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults.java +++ b/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults.java @@ -4,14 +4,14 @@ import lombok.Value; import lombok.Builder; final @NoArgsConstructor(force = true) @AllArgsConstructor @Builder @Value class ConstructorsWithBuilderDefaults { public static @java.lang.SuppressWarnings("all") class ConstructorsWithBuilderDefaultsBuilder { - private @java.lang.SuppressWarnings("all") int x; + private @java.lang.SuppressWarnings("all") int x$value; private @java.lang.SuppressWarnings("all") boolean x$set; private @java.lang.SuppressWarnings("all") int y; @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaultsBuilder() { super(); } public @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaultsBuilder x(final int x) { - this.x = x; + this.x$value = x; x$set = true; return this; } @@ -20,10 +20,10 @@ final @NoArgsConstructor(force = true) @AllArgsConstructor @Builder @Value class return this; } public @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaults build() { - return new ConstructorsWithBuilderDefaults((x$set ? x : ConstructorsWithBuilderDefaults.$default$x()), y); + return new ConstructorsWithBuilderDefaults((x$set ? x$value : ConstructorsWithBuilderDefaults.$default$x()), y); } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (((("ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(x=" + this.x) + ", y=") + this.y) + ")"); + return (((("ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(x$value=" + this.x$value) + ", y=") + this.y) + ")"); } } private final @Builder.Default int x; diff --git a/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults2.java b/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults2.java index cc96c674..776899fb 100644 --- a/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults2.java +++ b/test/transform/resource/after-ecj/ConstructorsWithBuilderDefaults2.java @@ -3,21 +3,21 @@ import lombok.Value; import lombok.Builder; final @Builder @Value class ConstructorsWithBuilderDefaults<T> { public static @java.lang.SuppressWarnings("all") class ConstructorsWithBuilderDefaultsBuilder<T> { - private @java.lang.SuppressWarnings("all") java.util.List<T> z; + private @java.lang.SuppressWarnings("all") java.util.List<T> z$value; private @java.lang.SuppressWarnings("all") boolean z$set; - private @java.lang.SuppressWarnings("all") T x; + private @java.lang.SuppressWarnings("all") T x$value; private @java.lang.SuppressWarnings("all") boolean x$set; private @java.lang.SuppressWarnings("all") T q; @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaultsBuilder() { super(); } public @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaultsBuilder<T> z(final java.util.List<T> z) { - this.z = z; + this.z$value = z; z$set = true; return this; } public @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaultsBuilder<T> x(final T x) { - this.x = x; + this.x$value = x; x$set = true; return this; } @@ -26,10 +26,10 @@ final @Builder @Value class ConstructorsWithBuilderDefaults<T> { return this; } public @java.lang.SuppressWarnings("all") ConstructorsWithBuilderDefaults<T> build() { - return new ConstructorsWithBuilderDefaults<T>((z$set ? z : ConstructorsWithBuilderDefaults.<T>$default$z()), (x$set ? x : ConstructorsWithBuilderDefaults.<T>$default$x()), q); + return new ConstructorsWithBuilderDefaults<T>((z$set ? z$value : ConstructorsWithBuilderDefaults.<T>$default$z()), (x$set ? x$value : ConstructorsWithBuilderDefaults.<T>$default$x()), q); } public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() { - return (((((("ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(z=" + this.z) + ", x=") + this.x) + ", q=") + this.q) + ")"); + return (((((("ConstructorsWithBuilderDefaults.ConstructorsWithBuilderDefaultsBuilder(z$value=" + this.z$value) + ", x$value=") + this.x$value) + ", q=") + this.q) + ")"); } } private final @Builder.Default java.util.List<T> z; diff --git a/test/transform/resource/after-ecj/JacksonJsonProperty.java b/test/transform/resource/after-ecj/JacksonJsonProperty.java index 73049b2a..c0485251 100644 --- a/test/transform/resource/after-ecj/JacksonJsonProperty.java +++ b/test/transform/resource/after-ecj/JacksonJsonProperty.java @@ -1,4 +1,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import lombok.Builder; import lombok.Setter; public @Builder class JacksonJsonProperty { @@ -7,7 +9,7 @@ public @Builder class JacksonJsonProperty { @java.lang.SuppressWarnings("all") JacksonJsonPropertyBuilder() { super(); } - public @JsonProperty("kebab-case-prop") @java.lang.SuppressWarnings("all") JacksonJsonPropertyBuilder kebabCaseProp(final String kebabCaseProp) { + public @JsonProperty("kebab-case-prop") @JsonSetter(nulls = Nulls.SKIP) @java.lang.SuppressWarnings("all") JacksonJsonPropertyBuilder kebabCaseProp(final String kebabCaseProp) { this.kebabCaseProp = kebabCaseProp; return this; } @@ -18,7 +20,7 @@ public @Builder class JacksonJsonProperty { return (("JacksonJsonProperty.JacksonJsonPropertyBuilder(kebabCaseProp=" + this.kebabCaseProp) + ")"); } } - public @JsonProperty("kebab-case-prop") @Setter String kebabCaseProp; + public @JsonProperty("kebab-case-prop") @JsonSetter(nulls = Nulls.SKIP) @Setter String kebabCaseProp; @java.lang.SuppressWarnings("all") JacksonJsonProperty(final String kebabCaseProp) { super(); this.kebabCaseProp = kebabCaseProp; @@ -26,7 +28,7 @@ public @Builder class JacksonJsonProperty { public static @java.lang.SuppressWarnings("all") JacksonJsonPropertyBuilder builder() { return new JacksonJsonPropertyBuilder(); } - public @JsonProperty("kebab-case-prop") @java.lang.SuppressWarnings("all") void setKebabCaseProp(final String kebabCaseProp) { + public @JsonProperty("kebab-case-prop") @JsonSetter(nulls = Nulls.SKIP) @java.lang.SuppressWarnings("all") void setKebabCaseProp(final String kebabCaseProp) { this.kebabCaseProp = kebabCaseProp; } }
\ No newline at end of file diff --git a/test/transform/resource/after-ecj/NonNullWithGuava.java b/test/transform/resource/after-ecj/NonNullWithGuava.java new file mode 100644 index 00000000..c7f5a7fe --- /dev/null +++ b/test/transform/resource/after-ecj/NonNullWithGuava.java @@ -0,0 +1,36 @@ +import static com.google.common.base.Preconditions.*; +public class NonNullWithGuava { + private @lombok.NonNull @lombok.Setter String test; + public NonNullWithGuava() { + super(); + } + public void testMethod(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + System.out.println(arg); + } + public void testMethodWithCheck1(@lombok.NonNull String arg) { + checkNotNull(arg); + } + public void testMethodWithCheckAssign(@lombok.NonNull String arg) { + test = checkNotNull(arg); + } + public void testMethodWithCheck2(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg); + } + public void testMethodWithFakeCheck1(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + checkNotNull(""); + } + public void testMethodWithFakeCheck2(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + com.google.common.base.Preconditions.checkNotNull(test); + } + public void testMethodWithFakeCheckAssign(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg, "arg is marked non-null but is null"); + test = checkNotNull(test); + } + public @java.lang.SuppressWarnings("all") void setTest(final @lombok.NonNull String test) { + com.google.common.base.Preconditions.checkNotNull(test, "test is marked non-null but is null"); + this.test = test; + } +} diff --git a/test/transform/resource/after-ecj/NonNullWithJdk.java b/test/transform/resource/after-ecj/NonNullWithJdk.java new file mode 100644 index 00000000..7d522260 --- /dev/null +++ b/test/transform/resource/after-ecj/NonNullWithJdk.java @@ -0,0 +1,37 @@ +//version 7: +import static java.util.Objects.*; +public class NonNullWithJdk { + private @lombok.NonNull @lombok.Setter String test; + public NonNullWithJdk() { + super(); + } + public void testMethod(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + System.out.println(arg); + } + public void testMethodWithCheck1(@lombok.NonNull String arg) { + requireNonNull(arg); + } + public void testMethodWithCheckAssign(@lombok.NonNull String arg) { + test = requireNonNull(arg); + } + public void testMethodWithCheck2(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg); + } + public void testMethodWithFakeCheck1(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + requireNonNull(""); + } + public void testMethodWithFakeCheck2(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + java.util.Objects.requireNonNull(test); + } + public void testMethodWithFakeCheckAssign(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg, "arg is marked non-null but is null"); + test = requireNonNull(test); + } + public @java.lang.SuppressWarnings("all") void setTest(final @lombok.NonNull String test) { + java.util.Objects.requireNonNull(test, "test is marked non-null but is null"); + this.test = test; + } +} diff --git a/test/transform/resource/after-ecj/SuperBuilderWithDefaults.java b/test/transform/resource/after-ecj/SuperBuilderWithDefaults.java index e259b68d..ff1b5931 100644 --- a/test/transform/resource/after-ecj/SuperBuilderWithDefaults.java +++ b/test/transform/resource/after-ecj/SuperBuilderWithDefaults.java @@ -2,9 +2,9 @@ import java.util.List; public class SuperBuilderWithDefaults {
public static @lombok.experimental.SuperBuilder class Parent<N extends Number> {
public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder<N extends Number, C extends Parent<N>, B extends ParentBuilder<N, C, B>> {
- private @java.lang.SuppressWarnings("all") long millis;
+ private @java.lang.SuppressWarnings("all") long millis$value;
private @java.lang.SuppressWarnings("all") boolean millis$set;
- private @java.lang.SuppressWarnings("all") N numberField;
+ private @java.lang.SuppressWarnings("all") N numberField$value;
private @java.lang.SuppressWarnings("all") boolean numberField$set;
public ParentBuilder() {
super();
@@ -12,17 +12,17 @@ public class SuperBuilderWithDefaults { protected abstract @java.lang.SuppressWarnings("all") B self();
public abstract @java.lang.SuppressWarnings("all") C build();
public @java.lang.SuppressWarnings("all") B millis(final long millis) {
- this.millis = millis;
+ this.millis$value = millis;
millis$set = true;
return self();
}
public @java.lang.SuppressWarnings("all") B numberField(final N numberField) {
- this.numberField = numberField;
+ this.numberField$value = numberField;
numberField$set = true;
return self();
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return (((("SuperBuilderWithDefaults.Parent.ParentBuilder(millis=" + this.millis) + ", numberField=") + this.numberField) + ")");
+ return (((("SuperBuilderWithDefaults.Parent.ParentBuilder(millis$value=" + this.millis$value) + ", numberField$value=") + this.numberField$value) + ")");
}
}
private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl<N extends Number> extends ParentBuilder<N, Parent<N>, ParentBuilderImpl<N>> {
@@ -47,11 +47,11 @@ public class SuperBuilderWithDefaults { protected @java.lang.SuppressWarnings("all") Parent(final ParentBuilder<N, ?, ?> b) {
super();
if (b.millis$set)
- this.millis = b.millis;
+ this.millis = b.millis$value;
else
this.millis = Parent.<N>$default$millis();
if (b.numberField$set)
- this.numberField = b.numberField;
+ this.numberField = b.numberField$value;
else
this.numberField = Parent.<N>$default$numberField();
}
@@ -61,7 +61,7 @@ public class SuperBuilderWithDefaults { }
public static @lombok.experimental.SuperBuilder class Child extends Parent<Integer> {
public static abstract @java.lang.SuppressWarnings("all") class ChildBuilder<C extends Child, B extends ChildBuilder<C, B>> extends Parent.ParentBuilder<Integer, C, B> {
- private @java.lang.SuppressWarnings("all") double doubleField;
+ private @java.lang.SuppressWarnings("all") double doubleField$value;
private @java.lang.SuppressWarnings("all") boolean doubleField$set;
public ChildBuilder() {
super();
@@ -69,12 +69,12 @@ public class SuperBuilderWithDefaults { protected abstract @java.lang.Override @java.lang.SuppressWarnings("all") B self();
public abstract @java.lang.Override @java.lang.SuppressWarnings("all") C build();
public @java.lang.SuppressWarnings("all") B doubleField(final double doubleField) {
- this.doubleField = doubleField;
+ this.doubleField$value = doubleField;
doubleField$set = true;
return self();
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return (((("SuperBuilderWithDefaults.Child.ChildBuilder(super=" + super.toString()) + ", doubleField=") + this.doubleField) + ")");
+ return (((("SuperBuilderWithDefaults.Child.ChildBuilder(super=" + super.toString()) + ", doubleField$value=") + this.doubleField$value) + ")");
}
}
private static final @java.lang.SuppressWarnings("all") class ChildBuilderImpl extends ChildBuilder<Child, ChildBuilderImpl> {
@@ -95,7 +95,7 @@ public class SuperBuilderWithDefaults { protected @java.lang.SuppressWarnings("all") Child(final ChildBuilder<?, ?> b) {
super(b);
if (b.doubleField$set)
- this.doubleField = b.doubleField;
+ this.doubleField = b.doubleField$value;
else
this.doubleField = Child.$default$doubleField();
}
diff --git a/test/transform/resource/after-ecj/SuperBuilderWithNonNull.java b/test/transform/resource/after-ecj/SuperBuilderWithNonNull.java index 616d7083..31198ee1 100644 --- a/test/transform/resource/after-ecj/SuperBuilderWithNonNull.java +++ b/test/transform/resource/after-ecj/SuperBuilderWithNonNull.java @@ -2,7 +2,7 @@ import java.util.List; public class SuperBuilderWithNonNull {
public static @lombok.experimental.SuperBuilder class Parent {
public static abstract @java.lang.SuppressWarnings("all") class ParentBuilder<C extends Parent, B extends ParentBuilder<C, B>> {
- private @java.lang.SuppressWarnings("all") String nonNullParentField;
+ private @java.lang.SuppressWarnings("all") String nonNullParentField$value;
private @java.lang.SuppressWarnings("all") boolean nonNullParentField$set;
public ParentBuilder() {
super();
@@ -14,12 +14,12 @@ public class SuperBuilderWithNonNull { {
throw new java.lang.NullPointerException("nonNullParentField is marked non-null but is null");
}
- this.nonNullParentField = nonNullParentField;
+ this.nonNullParentField$value = nonNullParentField;
nonNullParentField$set = true;
return self();
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return (("SuperBuilderWithNonNull.Parent.ParentBuilder(nonNullParentField=" + this.nonNullParentField) + ")");
+ return (("SuperBuilderWithNonNull.Parent.ParentBuilder(nonNullParentField$value=" + this.nonNullParentField$value) + ")");
}
}
private static final @java.lang.SuppressWarnings("all") class ParentBuilderImpl extends ParentBuilder<Parent, ParentBuilderImpl> {
@@ -40,7 +40,7 @@ public class SuperBuilderWithNonNull { protected @java.lang.SuppressWarnings("all") Parent(final ParentBuilder<?, ?> b) {
super();
if (b.nonNullParentField$set)
- this.nonNullParentField = b.nonNullParentField;
+ this.nonNullParentField = b.nonNullParentField$value;
else
this.nonNullParentField = Parent.$default$nonNullParentField();
if ((nonNullParentField == null))
diff --git a/test/transform/resource/before/JacksonJsonProperty.java b/test/transform/resource/before/JacksonJsonProperty.java index f002dc48..f0b7b2f2 100644 --- a/test/transform/resource/before/JacksonJsonProperty.java +++ b/test/transform/resource/before/JacksonJsonProperty.java @@ -1,10 +1,13 @@ import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSetter; +import com.fasterxml.jackson.annotation.Nulls; import lombok.Builder; import lombok.Setter; @Builder public class JacksonJsonProperty { @JsonProperty("kebab-case-prop") + @JsonSetter(nulls = Nulls.SKIP) @Setter public String kebabCaseProp; } diff --git a/test/transform/resource/before/NonNullWithGuava.java b/test/transform/resource/before/NonNullWithGuava.java new file mode 100644 index 00000000..dc877daa --- /dev/null +++ b/test/transform/resource/before/NonNullWithGuava.java @@ -0,0 +1,33 @@ +//CONF: lombok.nonNull.exceptionType = Guava +import static com.google.common.base.Preconditions.*; +public class NonNullWithGuava { + @lombok.NonNull @lombok.Setter private String test; + + public void testMethod(@lombok.NonNull String arg) { + System.out.println(arg); + } + + public void testMethodWithCheck1(@lombok.NonNull String arg) { + checkNotNull(arg); + } + + public void testMethodWithCheckAssign(@lombok.NonNull String arg) { + test = checkNotNull(arg); + } + + public void testMethodWithCheck2(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(arg); + } + + public void testMethodWithFakeCheck1(@lombok.NonNull String arg) { + checkNotNull(""); + } + + public void testMethodWithFakeCheck2(@lombok.NonNull String arg) { + com.google.common.base.Preconditions.checkNotNull(test); + } + + public void testMethodWithFakeCheckAssign(@lombok.NonNull String arg) { + test = checkNotNull(test); + } +} diff --git a/test/transform/resource/before/NonNullWithJdk.java b/test/transform/resource/before/NonNullWithJdk.java new file mode 100644 index 00000000..c8cbf2ee --- /dev/null +++ b/test/transform/resource/before/NonNullWithJdk.java @@ -0,0 +1,34 @@ +//version 7: +//CONF: lombok.nonNull.exceptionType = Jdk +import static java.util.Objects.*; +public class NonNullWithJdk { + @lombok.NonNull @lombok.Setter private String test; + + public void testMethod(@lombok.NonNull String arg) { + System.out.println(arg); + } + + public void testMethodWithCheck1(@lombok.NonNull String arg) { + requireNonNull(arg); + } + + public void testMethodWithCheckAssign(@lombok.NonNull String arg) { + test = requireNonNull(arg); + } + + public void testMethodWithCheck2(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(arg); + } + + public void testMethodWithFakeCheck1(@lombok.NonNull String arg) { + requireNonNull(""); + } + + public void testMethodWithFakeCheck2(@lombok.NonNull String arg) { + java.util.Objects.requireNonNull(test); + } + + public void testMethodWithFakeCheckAssign(@lombok.NonNull String arg) { + test = requireNonNull(test); + } +} diff --git a/website/templates/features/Builder.html b/website/templates/features/Builder.html index af1ffd3a..d22877ea 100644 --- a/website/templates/features/Builder.html +++ b/website/templates/features/Builder.html @@ -50,7 +50,7 @@ </p><p> Now that the "method" mode is clear, putting a <code>@Builder</code> annotation on a constructor functions similarly; effectively, constructors are just static methods that have a special syntax to invoke them: Their 'return type' is the class they construct, and their type parameters are the same as the type parameters of the class itself. </p><p> - Finally, applying <code>@Builder</code> to a class is as if you added <code>@AllArgsConstructor(access = AccessLevel.PACKAGE)</code> to the class and applied the <code>@Builder</code> annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself. If you do have an explicit constructor, put the <code>@Builder</code> annotation on the constructor instead of on the class. + Finally, applying <code>@Builder</code> to a class is as if you added <code>@AllArgsConstructor(access = AccessLevel.PACKAGE)</code> to the class and applied the <code>@Builder</code> annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself. If you do have an explicit constructor, put the <code>@Builder</code> annotation on the constructor instead of on the class. Note that if you put both `@Value` and `@Builder` on a class, the package-private constructor that `@Builder` wants to generate 'wins' and suppresses the constructor that `@Value` wants to make. </p><p> If using <code>@Builder</code> to generate builders to produce instances of your own class (this is always the case unless adding <code>@Builder</code> to a method that doesn't return your own type), you can use <code>@Builder(toBuilder = true)</code> to also generate an instance method in your class called <code>toBuilder()</code>; it creates a new builder that starts out with all the values of this instance. You can put the <code>@Builder.ObtainVia</code> annotation on the parameters (in case of a constructor or method) or fields (in case of <code>@Builder</code> on a type) to indicate alternative means by which the value for that field/parameter is obtained from this instance. For example, you can specify a method to be invoked: <code>@Builder.ObtainVia(method = "calculateFoo")</code>. </p><p> @@ -192,6 +192,8 @@ public class JacksonExample { </p><p> The initializer on a <code>@Builder.Default</code> field is removed and stored in a static method, in order to guarantee that this initializer won't be executed at all if a value is specified in the build. This does mean the initializer cannot refer to <code>this</code>, <code>super</code> or any non-static member. If lombok generates a constructor for you, it'll also initialize this field with the initializer. </p><p> + The generated field in the builder to represent a field with a <code>@Builder.Default</code> set is called <code><em>propertyName</em>$value</code>; an additional boolean field called <code><em>propertyName</em>$set</code> is also generated to track whether it has been set or not. This is an implementation detail; do not write code that interacts with these fields. Instead, invoke the generated builder-setter method if you want to set the property inside a custom method inside the builder. + </p><p> Various well known annotations about nullity cause null checks to be inserted and will be copied to parameter of the builder's 'setter' method. See <a href="/features/GetterSetter">Getter/Setter</a> documentation's small print for more information. </p><p> You can suppress the generation of the <code>builder()</code> method, for example because you <em>just</em> want the <code>toBuilder()</code> functionality, by using: diff --git a/website/templates/features/Value.html b/website/templates/features/Value.html index 5d97a7b8..f6ef9403 100644 --- a/website/templates/features/Value.html +++ b/website/templates/features/Value.html @@ -15,7 +15,7 @@ <p> <code>@Value</code> is the immutable variant of <a href="/features/Data"><code>@Data</code></a>; all fields are made <code>private</code> and <code>final</code> by default, and setters are not generated. The class itself is also made <code>final</code> by default, because immutability is not something that can be forced onto a subclass. Like <code>@Data</code>, useful <code>toString()</code>, <code>equals()</code> and <code>hashCode()</code> methods are also generated, each field gets a getter method, and a constructor that covers every argument (except <code>final</code> fields that are initialized in the field declaration) is also generated. </p><p> - In practice, <code>@Value</code> is shorthand for: <code>final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter</code>, except that explicitly including an implementation of any of the relevant methods simply means that part won't be generated and no warning will be emitted. For example, if you write your own <code>toString</code>, no error occurs, and lombok will not generate a <code>toString</code>. Also, <em>any</em> explicit constructor, no matter the arguments list, implies lombok will not generate a constructor. If you do want lombok to generate the all-args constructor, add <code>@AllArgsConstructor</code> to the class. You can mark any constructor or method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok. + In practice, <code>@Value</code> is shorthand for: <code>final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter</code>, except that explicitly including an implementation of any of the relevant methods simply means that part won't be generated and no warning will be emitted. For example, if you write your own <code>toString</code>, no error occurs, and lombok will not generate a <code>toString</code>. Also, <em>any</em> explicit constructor, no matter the arguments list, implies lombok will not generate a constructor. If you do want lombok to generate the all-args constructor, add <code>@AllArgsConstructor</code> to the class. Note that if both `@Builder` and `@Value` are on a class, the package private allargs constructor that `@Builder` wants to make 'wins' over the public one that `@Value` wants to make. You can mark any constructor or method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok. </p><p> It is possible to override the final-by-default and private-by-default behavior using either an explicit access level on a field, or by using the <code>@NonFinal</code> or <code>@PackagePrivate</code> annotations. <code>@NonFinal</code> can also be used on a class to remove the final keyword. <br /> It is possible to override any default behavior for any of the 'parts' that make up <code>@Value</code> by explicitly using that annotation. |