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 +++++++++++++++++++++++++-- website/templates/credits.html | 2 ++ 2 files changed, 27 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; diff --git a/website/templates/credits.html b/website/templates/credits.html index 3390d762..b5c033ad 100644 --- a/website/templates/credits.html +++ b/website/templates/credits.html @@ -28,6 +28,8 @@ Perry Nguyen (pfn on ##java on freenode) for creating the inspiration for project lombok.
  • Tor Norbye, Jan Lahoda, and Petr Jiricka for helping out with Netbeans internals and/or javac. +
  • + nqzero for the permit-reflect library, whose ideas are also used in lombok.
  • All contributors who submitted patches or helped answering questions!
  • -- 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 +++++++++++++++++++++---- test/pretty/resource/after/Switch11.java | 11 ++++ test/pretty/resource/after/Switch12.java | 28 ++++++++++ test/pretty/resource/before/Switch11.java | 12 +++++ test/pretty/resource/before/Switch12.java | 30 +++++++++++ 6 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 test/pretty/resource/after/Switch11.java create mode 100644 test/pretty/resource/after/Switch12.java create mode 100644 test/pretty/resource/before/Switch11.java create mode 100644 test/pretty/resource/before/Switch12.java (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); } diff --git a/test/pretty/resource/after/Switch11.java b/test/pretty/resource/after/Switch11.java new file mode 100644 index 00000000..d24012a2 --- /dev/null +++ b/test/pretty/resource/after/Switch11.java @@ -0,0 +1,11 @@ +public class Switch11 { + public void basic() { + switch (5) { + case 1: + case 2: + System.out.println("OK"); + break; + default: + } + } +} diff --git a/test/pretty/resource/after/Switch12.java b/test/pretty/resource/after/Switch12.java new file mode 100644 index 00000000..89825223 --- /dev/null +++ b/test/pretty/resource/after/Switch12.java @@ -0,0 +1,28 @@ +public class Switch12 { + public void basic() { + switch (5) { + case 1: + case 2: + System.out.println("OK"); + break; + default: + } + } + public void multiCase() { + switch (5) { + case 1, 2: + System.out.println("OK"); + default: + } + } + + public int switchExpr() { + return switch (5) { + case 1, 2 -> 0; + case 3 -> { + break 10; + } + default -> 10; + } + 10; + } +} diff --git a/test/pretty/resource/before/Switch11.java b/test/pretty/resource/before/Switch11.java new file mode 100644 index 00000000..556631f0 --- /dev/null +++ b/test/pretty/resource/before/Switch11.java @@ -0,0 +1,12 @@ +// version :11 +public class Switch11 { + public void basic() { + switch (5) { + case 1: + case 2: + System.out.println("OK"); + break; + default: + } + } +} diff --git a/test/pretty/resource/before/Switch12.java b/test/pretty/resource/before/Switch12.java new file mode 100644 index 00000000..f1bd8a79 --- /dev/null +++ b/test/pretty/resource/before/Switch12.java @@ -0,0 +1,30 @@ +// version 12: +public class Switch12 { + public void basic() { + switch (5) { + case 1: + case 2: + System.out.println("OK"); + break; + default: + } + } + + public void multiCase() { + switch (5) { + case 1, 2: + System.out.println("OK"); + default: + } + } + + public int switchExpr() { + return switch (5) { + case 1, 2 -> 0; + case 3 -> { + break 10; + } + default -> 10; + } + 10; + } +} -- 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