diff --git a/src/core/lombok/javac/JavacImportList.java b/src/core/lombok/javac/JavacImportList.java index d498c2ab30..85ec31fbd0 100644 --- a/src/core/lombok/javac/JavacImportList.java +++ b/src/core/lombok/javac/JavacImportList.java @@ -50,7 +50,7 @@ public JavacImportList(JCCompilationUnit cud) { @Override public String getFullyQualifiedNameForSimpleNameNoAliasing(String unqualified) { for (JCTree def : defs) { if (!(def instanceof JCImport)) continue; - JCTree qual = ((JCImport) def).qualid; + JCTree qual = Javac.getQualid((JCImport) def); if (!(qual instanceof JCFieldAccess)) continue; String simpleName = ((JCFieldAccess) qual).name.toString(); if (simpleName.equals(unqualified)) { @@ -68,7 +68,7 @@ public JavacImportList(JCCompilationUnit cud) { for (JCTree def : defs) { if (!(def instanceof JCImport)) continue; if (((JCImport) def).staticImport) continue; - JCTree qual = ((JCImport) def).qualid; + JCTree qual = Javac.getQualid((JCImport) def); if (!(qual instanceof JCFieldAccess)) continue; String simpleName = ((JCFieldAccess) qual).name.toString(); if (!"*".equals(simpleName)) continue; @@ -87,7 +87,7 @@ public JavacImportList(JCCompilationUnit cud) { for (JCTree def : defs) { if (!(def instanceof JCImport)) continue; if (((JCImport) def).staticImport) continue; - JCTree qual = ((JCImport) def).qualid; + JCTree qual = Javac.getQualid((JCImport) def); if (!(qual instanceof JCFieldAccess)) continue; String simpleName = ((JCFieldAccess) qual).name.toString(); if (!"*".equals(simpleName)) continue; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 78c7caf58c..d093e890bc 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -561,7 +561,7 @@ public static void deleteImportFromCompilationUnit(JavacNode node, String name) if (!(def instanceof JCImport)) continue; JCImport imp0rt = (JCImport) def; if (imp0rt.staticImport) continue; - if (!imp0rt.qualid.toString().equals(name)) continue; + if (!Javac.getQualid(imp0rt).toString().equals(name)) continue; JavacAugments.JCImport_deletable.set(imp0rt, true); } } diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java index e4f1760222..e5fb440e7a 100755 --- a/src/delombok/lombok/delombok/Delombok.java +++ b/src/delombok/lombok/delombok/Delombok.java @@ -714,6 +714,7 @@ public boolean delombok() throws IOException { } if (!disablePreview && Javac.getJavaCompilerVersion() >= 11) argsList.add("--enable-preview"); + if (Javac.getJavaCompilerVersion() >= 21) argsList.add("-proc:full"); if (Javac.getJavaCompilerVersion() < 15) { String[] argv = argsList.toArray(new String[0]); diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java index 35dd9d76b6..d74344544d 100644 --- a/src/delombok/lombok/delombok/PrettyPrinter.java +++ b/src/delombok/lombok/delombok/PrettyPrinter.java @@ -92,6 +92,7 @@ import com.sun.tools.javac.util.Position; import lombok.javac.CommentInfo; +import lombok.javac.Javac; import lombok.javac.PackageName; import lombok.permit.Permit; import lombok.javac.CommentInfo.EndConnection; @@ -485,8 +486,9 @@ private Name name_value(Name someName) { } @Override public void visitImport(JCImport tree) { - if (tree.qualid instanceof JCFieldAccess) { - JCFieldAccess fa = ((JCFieldAccess) tree.qualid); + JCTree qualid = Javac.getQualid(tree); + if (qualid instanceof JCFieldAccess) { + JCFieldAccess fa = ((JCFieldAccess) qualid); if (fa.name.length() == 1 && fa.name.contentEquals("*")) { if (fa.selected instanceof JCFieldAccess) { JCFieldAccess lombokExperimental = (JCFieldAccess) fa.selected; @@ -500,7 +502,7 @@ private Name name_value(Name someName) { aPrint("import "); if (tree.staticImport) print("static "); - print(tree.qualid); + print(qualid); println(";", tree); } @@ -1353,6 +1355,12 @@ private void printModifierKeywords(JCModifiers tree) { } else { aPrint("case "); print(pats, ", "); + + JCExpression guard = readObject(tree, "guard", null); // JDK 21+ + if (guard != null) { + print(" when "); + print(guard); + } } Enum caseKind = readObject(tree, "caseKind", null); // JDK 12+ diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java index 5a6165b196..1c9bed09e4 100644 --- a/src/utils/lombok/javac/Javac.java +++ b/src/utils/lombok/javac/Javac.java @@ -51,6 +51,7 @@ import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; +import com.sun.tools.javac.tree.JCTree.JCImport; import com.sun.tools.javac.tree.JCTree.JCLiteral; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -275,6 +276,19 @@ public static JCTree getExtendsClause(JCClassDecl decl) { } } + /** + * In some versions, the field's type is {@code JCTree}, in others it is {@code JCFieldAccess}, which at the JVM level are not the same. + */ + private static final Field JCIMPORT_QUALID = Permit.permissiveGetField(JCImport.class, "qualid"); + + public static JCTree getQualid(JCImport tree) { + try { + return (JCTree) JCIMPORT_QUALID.get(tree); + } catch (IllegalAccessException e) { + throw sneakyThrow(e.getCause()); + } + } + public static Object getDocComments(JCCompilationUnit cu) { try { return JCCOMPILATIONUNIT_DOCCOMMENTS.get(cu); diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java index 09855951f0..04f0e208aa 100644 --- a/src/utils/lombok/javac/JavacTreeMaker.java +++ b/src/utils/lombok/javac/JavacTreeMaker.java @@ -589,9 +589,10 @@ public JCSwitch Switch(JCExpression selector, List cases) { //javac versions: 6-11 private static final MethodId Case11 = MethodId("Case", JCCase.class, JCExpression.class, com.sun.tools.javac.util.List.class); //javac version: 12+ - public static class Case12 { + public static class Case { private static final Class CASE_KIND_CLASS = classForName(TreeMaker.class, "com.sun.source.tree.CaseTree$CaseKind"); static final MethodId Case12 = MethodId("Case", JCCase.class, CASE_KIND_CLASS, com.sun.tools.javac.util.List.class, com.sun.tools.javac.util.List.class, JCTree.class); + static final MethodId Case21 = MethodId("Case", JCCase.class, CASE_KIND_CLASS, com.sun.tools.javac.util.List.class, JCExpression.class, com.sun.tools.javac.util.List.class, JCTree.class); static final Object CASE_KIND_STATEMENT = CASE_KIND_CLASS.getEnumConstants()[0]; } @@ -615,7 +616,10 @@ public JCCase Case(JCExpression pat, List stats) { } else { labels = List.of(pat); } - return invoke(Case12.Case12, Case12.CASE_KIND_STATEMENT, labels, stats, null); + if (tryResolve(Case.Case12)) { + return invoke(Case.Case12, Case.CASE_KIND_STATEMENT, labels, stats, null); + } + return invoke(Case.Case21, Case.CASE_KIND_STATEMENT, labels, null, stats, null); } //javac versions: 17 diff --git a/test/pretty/resource/after/RecordPattern21.java b/test/pretty/resource/after/RecordPattern21.java new file mode 100644 index 0000000000..dd3b9a286c --- /dev/null +++ b/test/pretty/resource/after/RecordPattern21.java @@ -0,0 +1,13 @@ +record Point(int x, int y) { +} +record Rectangle(Point upperLeft, Point lowerRight) { +} + +public class RecordPattern21 { + void recordPattern(Object o) { + if (o instanceof Point(int x, int y)) { + } + if (o instanceof Rectangle(Point(var x1, var y1), Point(int x2, int y2))) { + } + } +} \ No newline at end of file diff --git a/test/pretty/resource/after/Switch21.java b/test/pretty/resource/after/Switch21.java new file mode 100644 index 0000000000..d56ab16a69 --- /dev/null +++ b/test/pretty/resource/after/Switch21.java @@ -0,0 +1,25 @@ +public class Switch21 { + String switchPatternMatching(Object o) { + return switch (o) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> o.toString(); + }; + } + + String switchNull(Object o) { + return switch (o) { + case null, default -> "?"; + }; + } + + String switchGuardPattern(Object o) { + return switch (o) { + case String s when s.length() > 1 -> s; + case String s -> s; + default -> o.toString(); + }; + } +} diff --git a/test/pretty/resource/before/RecordPattern20.java b/test/pretty/resource/before/RecordPattern20.java index 8604215b22..5e257fdacc 100644 --- a/test/pretty/resource/before/RecordPattern20.java +++ b/test/pretty/resource/before/RecordPattern20.java @@ -1,4 +1,4 @@ -// version 20: +// version 20:20 record Point(int x, int y) { } record Rectangle(Point upperLeft, Point lowerRight) { diff --git a/test/pretty/resource/before/RecordPattern21.java b/test/pretty/resource/before/RecordPattern21.java new file mode 100644 index 0000000000..10c97ea021 --- /dev/null +++ b/test/pretty/resource/before/RecordPattern21.java @@ -0,0 +1,14 @@ +// version 21: +record Point(int x, int y) { +} +record Rectangle(Point upperLeft, Point lowerRight) { +} + +public class RecordPattern21 { + void recordPattern(Object o) { + if (o instanceof Point(int x, int y)) { + } + if (o instanceof Rectangle(Point(var x1, var y1), Point(int x2, int y2))) { + } + } +} \ No newline at end of file diff --git a/test/pretty/resource/before/Switch19.java b/test/pretty/resource/before/Switch19.java index 05b279289e..3a4f08bf81 100644 --- a/test/pretty/resource/before/Switch19.java +++ b/test/pretty/resource/before/Switch19.java @@ -1,4 +1,4 @@ -// version 19: +// version 19:20 public class Switch19 { String switchPatternMatching(Object o) { return switch (o) { diff --git a/test/pretty/resource/before/Switch21.java b/test/pretty/resource/before/Switch21.java new file mode 100644 index 0000000000..d32cdc5e87 --- /dev/null +++ b/test/pretty/resource/before/Switch21.java @@ -0,0 +1,26 @@ +// version 21: +public class Switch21 { + String switchPatternMatching(Object o) { + return switch (o) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> o.toString(); + }; + } + + String switchNull(Object o) { + return switch (o) { + case null, default -> "?"; + }; + } + + String switchGuardPattern(Object o) { + return switch (o) { + case String s when s.length() > 1 -> s; + case String s -> s; + default -> o.toString(); + }; + } +}