From 94381d0e9a6871d252e363fa98500d50e8e71dd2 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 15 Jan 2020 00:52:53 +0100 Subject: [fixes #2335] ObtainVia(method=) on more than one arg would crash in javac --- src/core/lombok/javac/handlers/HandleBuilder.java | 30 +++++++++++++++++------ 1 file changed, 22 insertions(+), 8 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 1e8b8a22..0bd43ba4 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -45,6 +45,7 @@ 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.JCModifiers; import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree; @@ -553,7 +554,9 @@ public class HandleBuilder extends JavacAnnotationHandler { JCExpression call = maker.NewClass(null, List.nil(), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.nil(), null); JCExpression invoke = call; + ListBuffer preStatements = null; ListBuffer statements = new ListBuffer(); + for (BuilderFieldData bfd : builderFields) { String setterPrefix = !prefix.isEmpty() ? prefix : fluent ? "" : "set"; String prefixedSetterName = bfd.name.toString(); @@ -566,17 +569,22 @@ public class HandleBuilder extends JavacAnnotationHandler { tgt[i] = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field())); } } else { + String name = bfd.obtainVia.method(); + JCMethodInvocation inv; if (bfd.obtainVia.isStatic()) { - for (int i = 0; i < tgt.length; i++) { - JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method())); - tgt[i] = maker.Apply(typeParameterNames(maker, typeParams), c, List.of(maker.Ident(type.toName("this")))); - } + JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(name)); + inv = maker.Apply(typeParameterNames(maker, typeParams), c, List.of(maker.Ident(type.toName("this")))); } else { - for (int i = 0; i < tgt.length; i++) { - JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method())); - tgt[i] = maker.Apply(List.nil(), c, List.nil()); - } + JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(name)); + inv = maker.Apply(List.nil(), c, List.nil()); } + for (int i = 0; i < tgt.length; i++) tgt[i] = maker.Ident(bfd.name); + + // javac appears to cache the type of JCMethodInvocation expressions based on position, meaning, if you have 2 ObtainVia-based method invokes on different types, you get bizarre type mismatch errors. + // going via a local variable declaration solves the problem. + JCExpression varType = JavacHandlerUtil.cloneType(maker, bfd.type, ast, type.getContext()); + if (preStatements == null) preStatements = new ListBuffer(); + preStatements.append(maker.VarDef(maker.Modifiers(Flags.FINAL), bfd.name, varType, inv)); } JCExpression arg; @@ -589,6 +597,7 @@ public class HandleBuilder extends JavacAnnotationHandler { statements.append(maker.If(isNotNull, maker.Exec(invokeBuilder), null)); } } + if (!statements.isEmpty()) { JCExpression tempVarType = namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams); statements.prepend(maker.VarDef(maker.Modifiers(Flags.FINAL), type.toName(BUILDER_TEMP_VAR), tempVarType, invoke)); @@ -596,6 +605,11 @@ public class HandleBuilder extends JavacAnnotationHandler { } else { statements.append(maker.Return(invoke)); } + + if (preStatements != null) { + preStatements.appendList(statements); + statements = preStatements; + } JCBlock body = maker.Block(0, statements.toList()); List annsOnMethod = cfv.generateUnique() ? List.of(maker.Annotation(genTypeRef(type, CheckerFrameworkVersion.NAME__UNIQUE), List.nil())) : List.nil(); return maker.MethodDef(maker.Modifiers(toJavacModifier(access), annsOnMethod), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type, type.toName(builderClassName), !isStatic, typeParams), List.nil(), List.nil(), List.nil(), body, null); -- cgit