From 94eadb5131b32b6cf599a3f5445524a08ba0569b Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 15 Oct 2018 21:12:45 +0200 Subject: [fixes #1324] toBuilder with @Singular marked collections that are null no longer throws NPE. --- src/core/lombok/javac/handlers/HandleBuilder.java | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'src/core/lombok/javac') diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index bc1a8072..c5c1e1ca 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -484,6 +484,7 @@ public class HandleBuilder extends JavacAnnotationHandler { sb.append("__ERR__"); } + private static final String BUILDER_TEMP_VAR = "builder"; private JCMethodDecl generateToBuilderMethod(String toBuilderMethodName, String builderClassName, JavacNode type, List typeParams, java.util.List builderFields, boolean fluent, JCAnnotation ast) { // return new ThingieBuilder().setA(this.a).setB(this.b); JavacTreeMaker maker = type.getTreeMaker(); @@ -495,6 +496,7 @@ public class HandleBuilder extends JavacAnnotationHandler { JCExpression call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.nil(), null); JCExpression invoke = call; + ListBuffer statements = new ListBuffer(); for (BuilderFieldData bfd : builderFields) { Name setterName = fluent ? bfd.name : type.toName(HandlerUtil.buildAccessorName("set", bfd.name.toString())); JCExpression[] tgt = new JCExpression[bfd.singularData == null ? 1 : 2]; @@ -519,18 +521,21 @@ public class HandleBuilder extends JavacAnnotationHandler { JCExpression arg; if (bfd.singularData == null) { arg = tgt[0]; + invoke = maker.Apply(List.nil(), maker.Select(invoke, setterName), List.of(arg)); } else { - JCExpression eqNull = maker.Binary(CTC_EQUAL, tgt[0], maker.Literal(CTC_BOT, null)); - List tas = cloneTypes(maker, bfd.singularData.getTypeArgs(), ast, type.getContext()); - JCExpression emptyList = maker.Apply(tas, chainDots(type, "java", "util", "Collections", "emptyList"), List.nil()); - arg = maker.Conditional(eqNull, emptyList, tgt[1]); + JCExpression isNotNull = maker.Binary(CTC_NOT_EQUAL, tgt[0], maker.Literal(CTC_BOT, null)); + JCExpression invokeBuilder = maker.Apply(List.nil(), maker.Select(maker.Ident(type.toName(BUILDER_TEMP_VAR)), setterName), List.of(tgt[1])); + statements.append(maker.If(isNotNull, maker.Exec(invokeBuilder), null)); } - - invoke = maker.Apply(List.nil(), maker.Select(invoke, setterName), List.of(arg)); } - JCStatement statement = maker.Return(invoke); - - JCBlock body = maker.Block(0, List.of(statement)); + if (!statements.isEmpty()) { + JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams); + statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), type.toName(BUILDER_TEMP_VAR), tempVarType, invoke)); + statements.append(maker.Return(maker.Ident(type.toName(BUILDER_TEMP_VAR)))); + } else { + statements.append(maker.Return(invoke)); + } + JCBlock body = maker.Block(0, statements.toList()); return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.nil(), List.nil(), List.nil(), body, null); } -- cgit