From 4a39f8ec47dd965ec47b4379e937ffb2d5152a95 Mon Sep 17 00:00:00 2001 From: monosoul Date: Sun, 14 Apr 2019 20:48:04 +0500 Subject: #1040 remove createFormat() method Method createFormat() causes ambiguous behavior and shouldn't be used with addFormat(), especially because the created format instance doesn't being added to the formatOptions --- src/delombok/lombok/delombok/ant/DelombokTask.java | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/delombok/lombok/delombok/ant/DelombokTask.java b/src/delombok/lombok/delombok/ant/DelombokTask.java index e09b8ed2..cb31ef4d 100644 --- a/src/delombok/lombok/delombok/ant/DelombokTask.java +++ b/src/delombok/lombok/delombok/ant/DelombokTask.java @@ -154,10 +154,6 @@ class Tasks { path.add(set); } - public Format createFormat() { - return new Format(); - } - public void addFormat(Format format) { formatOptions.add(format); } -- cgit From 4cbe67361ba58f86e8847926f07a5172db1f6d2f Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 24 Apr 2019 00:40:44 +0200 Subject: [fixes #2085] JDK12 compatibility. Also acknowledging @nqzero for the permit-reflect library which is inspiring our shenanigans :) --- src/utils/lombok/permit/Permit.java | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/utils/lombok/permit/Permit.java b/src/utils/lombok/permit/Permit.java index 9f0434b8..b7c5f0d9 100644 --- a/src/utils/lombok/permit/Permit.java +++ b/src/utils/lombok/permit/Permit.java @@ -46,8 +46,7 @@ public class Permit { Throwable ex; try { - f = AccessibleObject.class.getDeclaredField("override"); - g = UNSAFE.objectFieldOffset(f); + g = getOverrideFieldOffset(); ex = null; } catch (Throwable t) { f = null; @@ -74,6 +73,30 @@ public class Permit { return accessor; } + private static long getOverrideFieldOffset() throws Throwable { + Field f = null; + Throwable saved = null; + try { + f = AccessibleObject.class.getDeclaredField("override"); + } catch (Throwable t) { + saved = t; + } + + if (f != null) { + return UNSAFE.objectFieldOffset(f); + } + // The below seems very risky, but for all AccessibleObjects in java today it does work, and starting with JDK12, making the field accessible is no longer possible. + try { + return UNSAFE.objectFieldOffset(Fake.class.getDeclaredField("override")); + } catch (Throwable t) { + throw saved; + } + } + + static class Fake { + boolean override; + } + public static Method getMethod(Class c, String mName, Class... parameterTypes) throws NoSuchMethodException { Method m = null; Class oc = c; -- cgit From ccaefff69fc021048ac6918948a0cae29e045b76 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 24 Apr 2019 13:52:17 +0200 Subject: [jdk12] adding support for the new nodes introduced for the improvements to switch statements, and the ‘switch expression’ preview feature, as well as support for the concept of preview features in general. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/delombok/lombok/delombok/Delombok.java | 13 +++++ src/delombok/lombok/delombok/PrettyPrinter.java | 69 +++++++++++++++++++++---- 2 files changed, 73 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index 8f4f99e5..76b2715a 100755 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -93,6 +93,7 @@ public class Delombok { private boolean noCopy; private boolean onlyChanged; private boolean force = false; + private boolean disablePreview; private String classpath, sourcepath, bootclasspath, modulepath; private LinkedHashMap fileToBase = new LinkedHashMap(); private List filesToParse = new ArrayList(); @@ -158,6 +159,10 @@ public class Delombok { @Description("Output only changed files (implies -n)") private boolean onlyChanged; + @Description("By default lombok enables preview features if available (introduced in JDK 12). With this option, lombok won't do that.") + @FullName("disable-preview") + private boolean disablePreview; + private boolean help; } @@ -281,6 +286,7 @@ public class Delombok { if (args.verbose) delombok.setVerbose(true); if (args.nocopy || args.onlyChanged) delombok.setNoCopy(true); + if (args.disablePreview) delombok.setDisablePreview(true); if (args.onlyChanged) delombok.setOnlyChanged(true); if (args.print) { delombok.setOutputToStandardOut(); @@ -516,6 +522,10 @@ public class Delombok { this.noCopy = noCopy; } + public void setDisablePreview(boolean disablePreview) { + this.disablePreview = disablePreview; + } + public void setOnlyChanged(boolean onlyChanged) { this.onlyChanged = onlyChanged; } @@ -684,6 +694,9 @@ public class Delombok { argsList.add("--module-path"); argsList.add(modulepath); } + + if (!disablePreview && Javac.getJavaCompilerVersion() >= 11) argsList.add("--enable-preview"); + String[] argv = argsList.toArray(new String[0]); args.init("javac", argv); options.put("diags.legacy", "TRUE"); diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java index 832dbe0a..3477c51c 100644 --- a/src/delombok/lombok/delombok/PrettyPrinter.java +++ b/src/delombok/lombok/delombok/PrettyPrinter.java @@ -1046,9 +1046,17 @@ public class PrettyPrinter extends JCTree.Visitor { @Override public void visitBreak(JCBreak tree) { aPrint("break"); - if (tree.label != null) { + + JCExpression value = readObject(tree, "value", null); // JDK 12+ + if (value != null) { print(" "); - print(tree.label); + print(value); + } else { + Name label = readObject(tree, "label", null); + if (label != null) { + print(" "); + print(label); + } } println(";", tree); } @@ -1230,16 +1238,41 @@ public class PrettyPrinter extends JCTree.Visitor { } @Override public void visitCase(JCCase tree) { - if (tree.pat == null) { + // Starting with JDK12, switches allow multiple expressions per case, and can take the form of an expression (preview feature). + + List pats = readObject(tree, "pats", null); // JDK 12+ + if (pats == null) { + JCExpression pat = readObject(tree, "pat", null); // JDK -11 + pats = pat == null ? List.nil() : List.of(pat); + } + + if (pats.isEmpty()) { aPrint("default"); } else { aPrint("case "); - print(tree.pat); + print(pats, ", "); + } + + Enum caseKind = readObject(tree, "caseKind", null); // JDK 12+ + + if (caseKind != null && caseKind.name().equalsIgnoreCase("RULE")) { + print(" -> "); + if (tree.stats.head instanceof JCBreak) { + JCBreak b = (JCBreak) tree.stats.head; + print((JCExpression) readObject(b, "value", null)); + print(";"); + needsNewLine = true; + needsAlign = true; + } else { + print(tree.stats.head); + if (tree.stats.head instanceof JCBlock) needsNewLine = false; + } + } else { + println(": "); + indent++; + print(tree.stats, ""); + indent--; } - println(": "); - indent++; - print(tree.stats, ""); - indent--; } @Override public void visitCatch(JCCatch tree) { @@ -1259,10 +1292,26 @@ public class PrettyPrinter extends JCTree.Visitor { print(")"); } println(" {"); - print(tree.cases, "\n"); + print(tree.cases, ""); aPrintln("}", tree); } + void printSwitchExpression(JCTree tree) { + aPrint("switch "); + JCExpression selector = readObject(tree, "selector", null); + if (selector instanceof JCParens) { + print(selector); + } else { + print("("); + print(selector); + print(")"); + } + println(" {"); + List cases = readObject(tree, "cases", null); + print(cases, ""); + aPrint("}"); + } + @Override public void visitTry(JCTry tree) { aPrint("try "); List resources = readObject(tree, "resources", List.nil()); @@ -1481,6 +1530,8 @@ public class PrettyPrinter extends JCTree.Visitor { printAnnotatedType0(tree); } else if ("JCPackageDecl".equals(simpleName)) { // Starting with JDK9, this is inside the import list, but we've already printed it. Just ignore it. + } else if ("JCSwitchExpression".equals(simpleName)) { // Introduced as preview feature in JDK12 + printSwitchExpression(tree); } else { throw new AssertionError("Unhandled tree type: " + tree.getClass() + ": " + tree); } -- cgit From 1730a991b50439f91bba217bb49edc860915ee70 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 24 Apr 2019 13:52:49 +0200 Subject: [val] in ecj we were constructing a different type than for javac, when using ‘val’ on an intersection type. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/eclipseAgent/lombok/eclipse/agent/PatchVal.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java index 12f4ad3d..b32c99cd 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java @@ -263,11 +263,15 @@ public class PatchVal { resolved = null; } if (resolved != null) { - try { - replacement = makeType(resolved, local.type, false); - if (!decomponent) init.resolvedType = replacement.resolveType(scope); - } catch (Exception e) { - // Some type thing failed. + if (resolved.getClass().getSimpleName().startsWith("IntersectionTypeBinding")) { + // We intentionally deconstruct these into simply 'Object', because picking an arbitrary type amongst the intersection feels worse. + } else { + try { + replacement = makeType(resolved, local.type, false); + if (!decomponent) init.resolvedType = replacement.resolveType(scope); + } catch (Exception e) { + // Some type thing failed. + } } } } -- cgit From 0a1e872b96777fc284533f4ebdd41f971f5fe2e9 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 24 Apr 2019 14:05:56 +0200 Subject: [jdk11] delombok was printing most variable declarations that are generated by lombok with ‘var’. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/lombok/javac/JavacTreeMaker.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java index 83d9c53f..81278de2 100644 --- a/src/utils/lombok/javac/JavacTreeMaker.java +++ b/src/utils/lombok/javac/JavacTreeMaker.java @@ -441,7 +441,9 @@ public class JavacTreeMaker { //javac versions: 6-8 private static final MethodId VarDef = MethodId("VarDef"); public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) { - return invoke(VarDef, mods, name, vartype, init); + JCVariableDecl varDef = invoke(VarDef, mods, name, vartype, init); + if (varDef.vartype != null && varDef.vartype.pos == -1) varDef.vartype.pos = 0; + return varDef; } //javac versions: 8 -- cgit From 150be0a186d880503cb23d056ea4cf229ebc37e5 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 24 Apr 2019 14:12:28 +0200 Subject: [trivial] adding a comment to give context to the fix for delombok being overly liberal with applying "var" to things. --- src/utils/lombok/javac/JavacTreeMaker.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java index 81278de2..84293f11 100644 --- a/src/utils/lombok/javac/JavacTreeMaker.java +++ b/src/utils/lombok/javac/JavacTreeMaker.java @@ -442,6 +442,8 @@ public class JavacTreeMaker { private static final MethodId VarDef = MethodId("VarDef"); public JCVariableDecl VarDef(JCModifiers mods, Name name, JCExpression vartype, JCExpression init) { JCVariableDecl varDef = invoke(VarDef, mods, name, vartype, init); + // We use 'position of the type is -1' as indicator in delombok that the original node was written using JDK10's 'var' feature, because javac desugars 'var' to the real type and doesn't leave any markers other than the + // node position to indicate that it did so. Unfortunately, that means vardecls we generate look like 'var' to delombok. Adjust the position to avoid this. if (varDef.vartype != null && varDef.vartype.pos == -1) varDef.vartype.pos = 0; return varDef; } -- cgit From ce0a09177e577c0b4f42379c5cc7ce364f26c905 Mon Sep 17 00:00:00 2001 From: Bulgakov Alexander Date: Fri, 26 Apr 2019 22:10:34 +0300 Subject: #1976. A handlers' order has been changed. The javac's HandleDelegate generates code before the HandleVal. --- src/core/lombok/javac/handlers/HandleDelegate.java | 3 ++- src/core/lombok/javac/handlers/HandleVal.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java index baff7912..367b2cff 100644 --- a/src/core/lombok/javac/handlers/HandleDelegate.java +++ b/src/core/lombok/javac/handlers/HandleDelegate.java @@ -82,7 +82,7 @@ import lombok.javac.JavacTreeMaker; import lombok.javac.ResolutionResetNeeded; @ProviderFor(JavacAnnotationHandler.class) -@HandlerPriority(65536) //2^16; to make sure that we also delegate generated methods. +@HandlerPriority(HandleDelegate.HANDLE_DELEGATE_PRIORITY) //2^16; to make sure that we also delegate generated methods. @ResolutionResetNeeded public class HandleDelegate extends JavacAnnotationHandler { @@ -102,6 +102,7 @@ public class HandleDelegate extends JavacAnnotationHandler { private static final String LEGALITY_OF_DELEGATE = "@Delegate is legal only on instance fields or no-argument instance methods."; private static final String RECURSION_NOT_ALLOWED = "@Delegate does not support recursion (delegating to a type that itself has @Delegate members). Member \"%s\" is @Delegate in type \"%s\""; + public static final int HANDLE_DELEGATE_PRIORITY = 65536; @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 14130bc4..323bb337 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -22,6 +22,7 @@ package lombok.javac.handlers; import static lombok.core.handlers.HandlerUtil.handleFlagUsage; +import static lombok.javac.handlers.HandleDelegate.HANDLE_DELEGATE_PRIORITY; import static lombok.javac.handlers.JavacHandlerUtil.*; import lombok.ConfigurationKeys; import lombok.val; @@ -49,7 +50,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; @ProviderFor(JavacASTVisitor.class) -@HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated. +@HandlerPriority(HANDLE_DELEGATE_PRIORITY + 100) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated. @ResolutionResetNeeded public class HandleVal extends JavacASTAdapter { -- cgit From 75601240760bd81ff95fcde7a1b8185769ce64e8 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Tue, 30 Apr 2019 21:39:51 +0200 Subject: [i2084] Rename .dll to .binary to prevent OWASP Dependency-Check from reporting "problems" --- src/installer/lombok/installer/OsUtils.java | 4 ++-- .../lombok/installer/WindowsDriveInfo-i386.binary | Bin 0 -> 14472 bytes .../lombok/installer/WindowsDriveInfo-i386.dll | Bin 14472 -> 0 bytes .../lombok/installer/WindowsDriveInfo-x86_64.binary | Bin 0 -> 66806 bytes .../lombok/installer/WindowsDriveInfo-x86_64.dll | Bin 66806 -> 0 bytes 5 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 src/installer/lombok/installer/WindowsDriveInfo-i386.binary delete mode 100644 src/installer/lombok/installer/WindowsDriveInfo-i386.dll create mode 100644 src/installer/lombok/installer/WindowsDriveInfo-x86_64.binary delete mode 100644 src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll (limited to 'src') diff --git a/src/installer/lombok/installer/OsUtils.java b/src/installer/lombok/installer/OsUtils.java index 2da7de09..022ff2e5 100644 --- a/src/installer/lombok/installer/OsUtils.java +++ b/src/installer/lombok/installer/OsUtils.java @@ -53,14 +53,14 @@ public final class OsUtils { dll1.deleteOnExit(); dll2.deleteOnExit(); try { - if (unpackDLL("WindowsDriveInfo-i386.dll", dll1)) { + if (unpackDLL("WindowsDriveInfo-i386.binary", dll1)) { System.load(dll1.getAbsolutePath()); return; } } catch (Throwable ignore) {} try { - if (unpackDLL("WindowsDriveInfo-x86_64.dll", dll2)) { + if (unpackDLL("WindowsDriveInfo-x86_64.binary", dll2)) { System.load(dll2.getAbsolutePath()); } } catch (Throwable ignore) {} diff --git a/src/installer/lombok/installer/WindowsDriveInfo-i386.binary b/src/installer/lombok/installer/WindowsDriveInfo-i386.binary new file mode 100644 index 00000000..eb7fa49a Binary files /dev/null and b/src/installer/lombok/installer/WindowsDriveInfo-i386.binary differ diff --git a/src/installer/lombok/installer/WindowsDriveInfo-i386.dll b/src/installer/lombok/installer/WindowsDriveInfo-i386.dll deleted file mode 100644 index eb7fa49a..00000000 Binary files a/src/installer/lombok/installer/WindowsDriveInfo-i386.dll and /dev/null differ diff --git a/src/installer/lombok/installer/WindowsDriveInfo-x86_64.binary b/src/installer/lombok/installer/WindowsDriveInfo-x86_64.binary new file mode 100644 index 00000000..0b7c9a83 Binary files /dev/null and b/src/installer/lombok/installer/WindowsDriveInfo-x86_64.binary differ diff --git a/src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll b/src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll deleted file mode 100644 index 0b7c9a83..00000000 Binary files a/src/installer/lombok/installer/WindowsDriveInfo-x86_64.dll and /dev/null differ -- cgit From ec04d9d7f077b83071de84a337338c9983db43bf Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 30 Apr 2019 22:37:45 +0200 Subject: [trivial] update a comment to be more accurate about the priority of handler for val. --- src/core/lombok/javac/handlers/HandleVal.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index 323bb337..23c27bc0 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -50,7 +50,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.List; @ProviderFor(JavacASTVisitor.class) -@HandlerPriority(HANDLE_DELEGATE_PRIORITY + 100) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated. +@HandlerPriority(HANDLE_DELEGATE_PRIORITY + 100) // run slightly after HandleDelegate; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated. @ResolutionResetNeeded public class HandleVal extends JavacASTAdapter { -- cgit From 5c101911202aa9c15e99e898a62ba935e9e3846e Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Wed, 1 May 2019 00:08:53 +0200 Subject: Update documentation --- src/core/lombok/ConfigurationKeys.java | 6 +++--- src/core/lombok/Generated.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 2b406dbe..ad39f0af 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -51,7 +51,7 @@ public class ConfigurationKeys { * * If {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated, unless {@code lombok.addJavaxGeneratedAnnotation} is set. *
- * BREAKING CHANGE: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9. + * BREAKING CHANGE: Starting with lombok v1.16.20, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9. * * @see ConfigurationKeys#ADD_JAVAX_GENERATED_ANNOTATIONS * @see ConfigurationKeys#ADD_LOMBOK_GENERATED_ANNOTATIONS @@ -65,7 +65,7 @@ public class ConfigurationKeys { * * If {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated. *
- * BREAKING CHANGE: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9. + * BREAKING CHANGE: Starting with lombok v1.16.20, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9. */ public static final ConfigurationKey ADD_JAVAX_GENERATED_ANNOTATIONS = new ConfigurationKey("lombok.addJavaxGeneratedAnnotation", "Generate @javax.annotation.Generated on all generated code (default: follow lombok.addGeneratedAnnotation).") {}; @@ -103,7 +103,7 @@ public class ConfigurationKeys { * NB: GWT projects, and probably android projects, should explicitly set this key to {@code true} for the entire project. * *
- * BREAKING CHANGE: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as {@code @ConstructorProperties} requires extra modules in JDK9. + * BREAKING CHANGE: Starting with lombok v1.16.20, defaults to {@code false} instead of {@code true}, as {@code @ConstructorProperties} requires extra modules in JDK9. * * @see ConfigurationKeys#ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES * @deprecated Since version 2.0, use {@link #ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES} instead. diff --git a/src/core/lombok/Generated.java b/src/core/lombok/Generated.java index b99a1b58..216ab143 100644 --- a/src/core/lombok/Generated.java +++ b/src/core/lombok/Generated.java @@ -33,7 +33,8 @@ import java.lang.annotation.Target; *

* NB: As of v1.16.2 which introduces this annotation, lombok doesn't actually add this annotation; we're setting * it up so that lombok jars in widespread use start having this, which will make it easier to actually apply it - * later on. + * later on. By adding {@code lombok.addLombokGeneratedAnnotation = true} to {@code lombok.config} you can already + * get this behavior. */ @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.CLASS) -- cgit From a3180298305ff64e9f671b51d663b750ba7c8efa Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 1 May 2019 00:41:32 +0200 Subject: [fixes #2083] adds feature ‘access level’ to `@Builder` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/Builder.java | 8 +++ .../eclipse/handlers/EclipseSingularsRecipes.java | 9 +-- .../lombok/eclipse/handlers/HandleBuilder.java | 43 +++++++----- .../eclipse/handlers/HandleSuperBuilder.java | 2 +- .../singulars/EclipseGuavaSingularizer.java | 23 +++---- .../EclipseJavaUtilListSetSingularizer.java | 25 +++---- .../singulars/EclipseJavaUtilMapSingularizer.java | 25 +++---- src/core/lombok/javac/handlers/HandleBuilder.java | 45 +++++++------ .../lombok/javac/handlers/HandleSuperBuilder.java | 2 +- .../javac/handlers/JavacSingularsRecipes.java | 77 +++++++++++----------- .../handlers/singulars/JavacGuavaSingularizer.java | 23 +++---- .../JavacJavaUtilListSetSingularizer.java | 28 ++++---- .../singulars/JavacJavaUtilMapSingularizer.java | 32 ++++----- .../singulars/JavacJavaUtilSingularizer.java | 4 +- 14 files changed, 186 insertions(+), 160 deletions(-) (limited to 'src') diff --git a/src/core/lombok/Builder.java b/src/core/lombok/Builder.java index c83b3670..a60af9ee 100644 --- a/src/core/lombok/Builder.java +++ b/src/core/lombok/Builder.java @@ -146,6 +146,14 @@ public @interface Builder { */ boolean toBuilder() default false; + /** + * Sets the access level of the generated builder class. By default, generated builder classes are {@code public}. + * Note: This does nothing if you write your own builder class (we won't change its access level). + * + * @return The builder class will be generated with this access modifier. + */ + AccessLevel access() default lombok.AccessLevel.PUBLIC; + /** * Put on a field (in case of {@code @Builder} on a type) or a parameter (for {@code @Builder} on a constructor or static method) to * indicate how lombok should obtain a value for this field or parameter given an instance; this is only relevant if {@code toBuilder} is {@code true}. diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java index 81ddbd0a..67a9f97d 100755 --- a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java +++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 The Project Lombok Authors. + * Copyright (C) 2015-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 @@ -58,6 +58,7 @@ import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; +import lombok.AccessLevel; import lombok.core.LombokImmutableList; import lombok.core.SpiLoadUtil; import lombok.core.TypeLibrary; @@ -234,7 +235,7 @@ public class EclipseSingularsRecipes { * If you need more control over the return type and value, use * {@link #generateMethods(SingularData, boolean, EclipseNode, boolean, TypeReferenceMaker, StatementMaker)}. */ - public void generateMethods(SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain) { + public void generateMethods(SingularData data, boolean deprecate, final EclipseNode builderType, boolean fluent, final boolean chain, AccessLevel access) { TypeReferenceMaker returnTypeMaker = new TypeReferenceMaker() { @Override public TypeReference make() { return chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0); @@ -247,14 +248,14 @@ public class EclipseSingularsRecipes { } }; - generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker); + generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access); } /** * Generates the singular, plural, and clear methods for the given {@link SingularData}. * Uses the given {@code returnTypeMaker} and {@code returnStatementMaker} for the generated methods. */ - public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker); + public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access); public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List statements, char[] targetVariableName, String builderVariable); diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java index 7a831f3d..4659e9a3 100755 --- a/src/core/lombok/eclipse/handlers/HandleBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleBuilder.java @@ -157,6 +157,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { long p = (long) ast.sourceStart << 32 | ast.sourceEnd; Builder builderInstance = annotation.getInstance(); + AccessLevel accessForOuters = builderInstance.access(); + if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC; + if (builderInstance.access() == AccessLevel.NONE) { + annotationNode.addError("AccessLevel.NONE is not valid here"); + accessForOuters = AccessLevel.PUBLIC; + } + AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters; // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true); @@ -408,7 +415,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { EclipseNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { - builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast); + builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast, accessForOuters); } else { TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get(); if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) { @@ -469,14 +476,14 @@ public class HandleBuilder extends EclipseAnnotationHandler { } for (BuilderFieldData bfd : builderFields) { - makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain); + makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain, accessForInners); } { MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1); if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0); if (methodExists == MemberExistsResult.NOT_EXISTS) { - MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast); + MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast, accessForInners); if (md != null) injectMethod(builderType, md); } } @@ -499,7 +506,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; if (generateBuilderMethod) { - MethodDeclaration md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast); + MethodDeclaration md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast, accessForOuters); if (md != null) injectMethod(tdParent, md); } @@ -516,7 +523,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { tps[i].name = typeArgsForToBuilder.get(i); } } - MethodDeclaration md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast); + MethodDeclaration md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters); if (md != null) injectMethod(tdParent, md); } @@ -529,13 +536,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { } private static final char[] BUILDER_TEMP_VAR = {'b', 'u', 'i', 'l', 'd', 'e', 'r'}; - private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List builderFields, boolean fluent, ASTNode source) { + private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List builderFields, boolean fluent, ASTNode source, AccessLevel access) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.selector = methodName.toCharArray(); - out.modifiers = ClassFileConstants.AccPublic; + out.modifiers = toEclipseModifier(access); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); AllocationExpression invoke = new AllocationExpression(); @@ -632,7 +639,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { return decl; } - public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source) { + public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source, AccessLevel access) { MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; List statements = new ArrayList(); @@ -677,7 +684,7 @@ public class HandleBuilder extends EclipseAnnotationHandler { statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0)); } - out.modifiers = ClassFileConstants.AccPublic; + out.modifiers = toEclipseModifier(access); out.selector = name.toCharArray(); out.thrownExceptions = copyTypes(thrownExceptions); out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; @@ -736,13 +743,13 @@ public class HandleBuilder extends EclipseAnnotationHandler { return out; } - public MethodDeclaration generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) { + public MethodDeclaration generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source, AccessLevel access) { int pS = source.sourceStart, pE = source.sourceEnd; long p = (long) pS << 32 | pE; MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult); out.selector = builderMethodName.toCharArray(); - out.modifiers = ClassFileConstants.AccPublic; + out.modifiers = toEclipseModifier(access); if (isStatic) out.modifiers |= ClassFileConstants.AccStatic; out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p); @@ -795,16 +802,16 @@ public class HandleBuilder extends EclipseAnnotationHandler { private static final AbstractMethodDeclaration[] EMPTY = {}; - public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain) { + public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain, AccessLevel access) { 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); + makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, sourceNode, fluent, chain, bfd.annotations, access); } else { - bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain); + 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) { + private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain, Annotation[] annotations, AccessLevel access) { TypeDeclaration td = (TypeDeclaration) builderType.get(); AbstractMethodDeclaration[] existing = td.methods; if (existing == null) existing = EMPTY; @@ -820,16 +827,16 @@ public class HandleBuilder extends EclipseAnnotationHandler { String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName()); - MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, ClassFileConstants.AccPublic, + MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, toEclipseModifier(access), sourceNode, Collections.emptyList(), annotations != null ? Arrays.asList(copyAnnotations(sourceNode.get(), annotations)) : Collections.emptyList()); injectMethod(builderType, setter); } - public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source) { + public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source, AccessLevel access) { TypeDeclaration parent = (TypeDeclaration) tdParent.get(); TypeDeclaration builder = new TypeDeclaration(parent.compilationResult); builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; - builder.modifiers |= ClassFileConstants.AccPublic; + builder.modifiers |= toEclipseModifier(access); if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic; builder.typeParameters = copyTypeParams(typeParams, source); builder.name = builderClassName.toCharArray(); diff --git a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java index 6f34eb30..554ab2f0 100755 --- a/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java +++ b/src/core/lombok/eclipse/handlers/HandleSuperBuilder.java @@ -889,7 +889,7 @@ public class HandleSuperBuilder extends EclipseAnnotationHandler { if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) { generateSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, returnTypeMaker.make(), returnStatementMaker.make(), sourceNode, bfd.annotations); } else { - bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker); + bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, true, returnTypeMaker, returnStatementMaker, AccessLevel.PUBLIC); } } diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java index 40f01ee4..54c059b8 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 The Project Lombok Authors. + * Copyright (C) 2015-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 @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import lombok.AccessLevel; import lombok.core.GuavaTypeMap; import lombok.core.LombokImmutableList; import lombok.core.handlers.HandlerUtil; @@ -99,16 +100,16 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker) { - generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); - generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); - generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType); + @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) { + generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access); + generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access); + generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access); } - void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) { + void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); @@ -122,7 +123,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { injectMethod(builderType, md); } - void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { + void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) { LombokImmutableList suffixes = getArgumentSuffixes(); char[][] names = new char[suffixes.size()][]; for (int i = 0; i < suffixes.size(); i++) { @@ -133,7 +134,7 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType)); @@ -166,10 +167,10 @@ abstract class EclipseGuavaSingularizer extends EclipseSingularizer { HandleNonNull.INSTANCE.fix(injectMethod(builderType, md)); } - void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { + void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType)); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java index 32b1f71f..73d6fe9b 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 The Project Lombok Authors. + * Copyright (C) 2015-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 @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import lombok.AccessLevel; import lombok.core.handlers.HandlerUtil; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.HandleNonNull; @@ -90,21 +91,21 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField)); } - @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker) { + @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) { if (useGuavaInstead(builderType)) { - guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker); + guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access); return; } - generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); - generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); - generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType); + generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access); + generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access); + generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access); } - private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) { + private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L); thisDotField.receiver = new ThisReference(0, 0); @@ -123,10 +124,10 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula injectMethod(builderType, md); } - void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { + void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType, false)); @@ -155,10 +156,10 @@ abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingula HandleNonNull.INSTANCE.fix(injectMethod(builderType, md)); } - void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { + void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType, false)); diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java index b24bf97f..9ad1b6fe 100755 --- a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java +++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2018 The Project Lombok Authors. + * Copyright (C) 2015-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 @@ -52,6 +52,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.mangosdk.spi.ProviderFor; +import lombok.AccessLevel; import lombok.core.LombokImmutableList; import lombok.core.handlers.HandlerUtil; import lombok.eclipse.EclipseNode; @@ -135,21 +136,21 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer return Arrays.asList(keyFieldNode, valueFieldNode); } - @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker) { + @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, TypeReferenceMaker returnTypeMaker, StatementMaker returnStatementMaker, AccessLevel access) { if (useGuavaInstead(builderType)) { - guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker); + guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, returnTypeMaker, returnStatementMaker, access); return; } - generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); - generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent); - generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType); + generateSingularMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access); + generatePluralMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, fluent, access); + generateClearMethod(deprecate, returnTypeMaker.make(), returnStatementMaker.make(), data, builderType, access); } - private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) { + private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); String pN = new String(data.getPluralName()); char[] keyFieldName = (pN + "$key").toCharArray(); @@ -179,10 +180,10 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer injectMethod(builderType, md); } - private void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { + private void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); List statements = new ArrayList(); statements.add(createConstructBuilderVarIfNeeded(data, builderType, true)); @@ -236,10 +237,10 @@ public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer HandleNonNull.INSTANCE.fix(injectMethod(builderType, md)); } - private void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) { + private void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent, AccessLevel access) { MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult); md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG; - md.modifiers = ClassFileConstants.AccPublic; + md.modifiers = toEclipseModifier(access); String pN = new String(data.getPluralName()); char[] keyFieldName = (pN + "$key").toCharArray(); diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index d6fb9728..2eaba0fb 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -103,6 +103,13 @@ public class HandleBuilder extends JavacAnnotationHandler { handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); Builder builderInstance = annotation.getInstance(); + AccessLevel accessForOuters = builderInstance.access(); + if (accessForOuters == null) accessForOuters = AccessLevel.PUBLIC; + if (accessForOuters == AccessLevel.NONE) { + annotationNode.addError("AccessLevel.NONE is not valid here"); + accessForOuters = AccessLevel.PUBLIC; + } + AccessLevel accessForInners = accessForOuters == AccessLevel.PROTECTED ? AccessLevel.PUBLIC : accessForOuters; // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true); @@ -355,7 +362,7 @@ public class HandleBuilder extends JavacAnnotationHandler { JavacNode builderType = findInnerClass(tdParent, builderClassName); if (builderType == null) { - builderType = makeBuilderClass(isStatic, annotationNode, tdParent, builderClassName, typeParams, ast); + builderType = makeBuilderClass(isStatic, annotationNode, tdParent, builderClassName, typeParams, ast, accessForOuters); recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext()); } else { JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get(); @@ -413,14 +420,14 @@ public class HandleBuilder extends JavacAnnotationHandler { } for (BuilderFieldData bfd : builderFields) { - makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain); + makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain, accessForInners); } { MemberExistsResult methodExists = methodExists(buildMethodName, builderType, -1); if (methodExists == MemberExistsResult.EXISTS_BY_LOMBOK) methodExists = methodExists(buildMethodName, builderType, 0); if (methodExists == MemberExistsResult.NOT_EXISTS) { - JCMethodDecl md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning); + JCMethodDecl md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning, accessForInners); if (md != null) { injectMethod(builderType, md); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); @@ -444,7 +451,7 @@ public class HandleBuilder extends JavacAnnotationHandler { if (generateBuilderMethod && methodExists(builderMethodName, tdParent, -1) != MemberExistsResult.NOT_EXISTS) generateBuilderMethod = false; if (generateBuilderMethod) { - JCMethodDecl md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams); + JCMethodDecl md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams, accessForOuters); recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); if (md != null) injectMethod(tdParent, md); } @@ -464,7 +471,7 @@ public class HandleBuilder extends JavacAnnotationHandler { } tps = lb.toList(); } - JCMethodDecl md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast); + JCMethodDecl md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast, accessForOuters); if (md != null) { recursiveSetGeneratedBy(md, ast, annotationNode.getContext()); injectMethod(tdParent, md); @@ -513,7 +520,7 @@ public class HandleBuilder extends JavacAnnotationHandler { } 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) { + private JCMethodDecl generateToBuilderMethod(String toBuilderMethodName, String builderClassName, JavacNode type, List typeParams, java.util.List builderFields, boolean fluent, JCAnnotation ast, AccessLevel access) { // return new ThingieBuilder().setA(this.a).setB(this.b); JavacTreeMaker maker = type.getTreeMaker(); @@ -564,7 +571,7 @@ public class HandleBuilder extends JavacAnnotationHandler { 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); + return maker.MethodDef(maker.Modifiers(toJavacModifier(access)), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.nil(), List.nil(), List.nil(), body, null); } private JCMethodDecl generateCleanMethod(java.util.List builderFields, JavacNode type, JCTree source) { @@ -579,7 +586,7 @@ public class HandleBuilder extends JavacAnnotationHandler { statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0)))); JCBlock body = maker.Block(0, statements.toList()); - JCMethodDecl method = maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.nil(), List.nil(), List.nil(), body, null); + JCMethodDecl method = maker.MethodDef(maker.Modifiers(toJavacModifier(AccessLevel.PRIVATE)), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.nil(), List.nil(), List.nil(), body, null); recursiveSetGeneratedBy(method, source, type.getContext()); return method; /* @@ -596,7 +603,7 @@ public class HandleBuilder extends JavacAnnotationHandler { */ } - private JCMethodDecl generateBuildMethod(JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List builderFields, JavacNode type, List thrownExceptions, JCTree source, boolean addCleaning) { + private JCMethodDecl generateBuildMethod(JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List builderFields, JavacNode type, List thrownExceptions, JCTree source, boolean addCleaning, AccessLevel access) { JavacTreeMaker maker = type.getTreeMaker(); JCExpression call; @@ -649,7 +656,7 @@ public class HandleBuilder extends JavacAnnotationHandler { JCBlock body = maker.Block(0, statements.toList()); - return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(buildName), returnType, List.nil(), List.nil(), thrownExceptions, body, null); + return maker.MethodDef(maker.Modifiers(toJavacModifier(access)), type.toName(buildName), returnType, List.nil(), List.nil(), thrownExceptions, body, null); } public static JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List params) { @@ -664,7 +671,7 @@ public class HandleBuilder extends JavacAnnotationHandler { return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.nil(), List.nil(), body, null); } - public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List typeParams) { + public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List typeParams, AccessLevel access) { JavacTreeMaker maker = type.getTreeMaker(); ListBuffer typeArgs = new ListBuffer(); @@ -676,7 +683,7 @@ public class HandleBuilder extends JavacAnnotationHandler { JCStatement statement = maker.Return(call); JCBlock body = maker.Block(0, List.of(statement)); - int modifiers = Flags.PUBLIC; + int modifiers = toJavacModifier(access); if (isStatic) modifiers |= Flags.STATIC; return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), copyTypeParams(source, typeParams), List.nil(), List.nil(), body, null); } @@ -720,16 +727,16 @@ public class HandleBuilder extends JavacAnnotationHandler<