diff options
-rw-r--r-- | buildScripts/tests.ant.xml | 6 | ||||
-rw-r--r-- | doc/changelog.markdown | 2 | ||||
-rw-r--r-- | src/core/lombok/javac/JavacAST.java | 28 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/HandleVal.java | 24 | ||||
-rw-r--r-- | src/core/lombok/javac/handlers/JavacHandlerUtil.java | 48 | ||||
-rw-r--r-- | src/delombok/lombok/delombok/PrettyPrinter.java | 13 | ||||
-rw-r--r-- | test/pretty/resource/after/RecordPattern19.java (renamed from test/pretty/resource/after/RecordPattern.java) | 4 | ||||
-rw-r--r-- | test/pretty/resource/after/RecordPattern20.java | 22 | ||||
-rw-r--r-- | test/pretty/resource/before/RecordPattern19.java (renamed from test/pretty/resource/before/RecordPattern.java) | 6 | ||||
-rw-r--r-- | test/pretty/resource/before/RecordPattern20.java | 23 |
10 files changed, 160 insertions, 16 deletions
diff --git a/buildScripts/tests.ant.xml b/buildScripts/tests.ant.xml index d34e1f82..140983bc 100644 --- a/buildScripts/tests.ant.xml +++ b/buildScripts/tests.ant.xml @@ -150,8 +150,8 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn <!-- For non-LTS versions, feel free to aggressively update these to the current non-LTS openjdk version, and delete them once they roll out of the 6 month window. --> - <target name="test.javac19" depends="test.formatter.compile, test.compile" description="runs the tests on your default VM, using javac19 as underlying compiler"> - <test.javacX version="19" /> + <target name="test.javac20" depends="test.formatter.compile, test.compile" description="runs the tests on your default VM, using javac20 as underlying compiler"> + <test.javacX version="20" /> </target> <target name="test.javacCurrent" depends="test.formatter.compile, test.compile" description="runs the tests on your default VM, using its javac as underlying compiler"> @@ -293,5 +293,5 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn </target> <target name="test" depends="test.javacCurrent, test.eclipse-202212" description="runs the tests against the default JVM, javac, and eclipse" /> - <target name="test.broad" depends="test.javac8, test.javac17, test.javac19, test.eclipse-oxygen, test.eclipse-202212, test.eclipse-202006-jdk8" description="runs the tests against the default JVM, javac, and eclipse" /> + <target name="test.broad" depends="test.javac8, test.javac17, test.javac20, test.eclipse-oxygen, test.eclipse-202212, test.eclipse-202006-jdk8" description="runs the tests against the default JVM, javac, and eclipse" /> </project> diff --git a/doc/changelog.markdown b/doc/changelog.markdown index 86ff40e8..47b7bcf1 100644 --- a/doc/changelog.markdown +++ b/doc/changelog.markdown @@ -2,7 +2,7 @@ Lombok Changelog ---------------- ### v1.18.27 "Edgy Guinea Pig" -* We recently released v1.18.26; there is no edge release since then. +* PLATFORM: JDK20 support added. [Issue #3353](https://github.com/projectlombok/lombok/issues/3353). ### v1.18.26 (Feb 3rd, 2023) diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 0919c7d4..c09120c1 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -36,7 +36,6 @@ import javax.annotation.processing.Messager; import javax.tools.Diagnostic; import javax.tools.JavaFileObject; -import com.sun.tools.javac.util.JCDiagnostic; import lombok.core.AST; import lombok.core.CleanupRegistry; import lombok.core.CleanupTask; @@ -53,6 +52,7 @@ import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCCatch; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; +import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop; import com.sun.tools.javac.tree.JCTree.JCExpression; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCIdent; @@ -63,6 +63,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.JCTree.JCWildcard; import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; @@ -415,6 +416,18 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { JCANNOTATEDTYPE_FIELDS_INITIALIZED = true; } + + private static Field JCENHANCEDFORLOOP_VARORRECORDPATTERN_FIELD = Permit.permissiveGetField(JCEnhancedForLoop.class, "varOrRecordPattern"); + private static JCTree getVarOrRecordPattern(JCEnhancedForLoop loop) { + if (JCENHANCEDFORLOOP_VARORRECORDPATTERN_FIELD == null) { + return loop.var; + } + try { + return (JCTree) JCENHANCEDFORLOOP_VARORRECORDPATTERN_FIELD.get(loop); + } catch (Exception ignore) {} + return null; + } + private JavacNode buildTry(JCTry tryNode) { if (setAndGetAsHandled(tryNode)) return null; List<JavacNode> childNodes = new ArrayList<JavacNode>(); @@ -471,6 +484,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { if (statement instanceof JCVariableDecl) return buildLocalVar((JCVariableDecl) statement, Kind.LOCAL); if (statement instanceof JCTry) return buildTry((JCTry) statement); if (statement.getClass().getName().equals("com.sun.tools.javac.tree.JCTree$JCLambda")) return buildLambda(statement); + if (statement instanceof JCEnhancedForLoop) return buildEnhancedForLoop((JCEnhancedForLoop) statement); if (setAndGetAsHandled(statement)) return null; return drill(statement); @@ -500,6 +514,18 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> { return getBodyMethods.get(c); } + private JavacNode buildEnhancedForLoop(JCEnhancedForLoop loop) { + if (setAndGetAsHandled(loop)) return null; + + List<JavacNode> childNodes = new ArrayList<JavacNode>(); + // The order of the child elements is important and must be kept + addIfNotNull(childNodes, buildTree(getVarOrRecordPattern(loop), Kind.STATEMENT)); + addIfNotNull(childNodes, buildTree(loop.expr, Kind.STATEMENT)); + addIfNotNull(childNodes, buildStatement(loop.body)); + + return putInMap(new JavacNode(this, loop, childNodes, Kind.STATEMENT)); + } + private JavacNode drill(JCTree statement) { try { List<JavacNode> childNodes = new ArrayList<JavacNode>(); diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java index d4fb1027..8f4b1a86 100644 --- a/src/core/lombok/javac/handlers/HandleVal.java +++ b/src/core/lombok/javac/handlers/HandleVal.java @@ -24,15 +24,19 @@ 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 java.lang.reflect.Field; + import lombok.ConfigurationKeys; import lombok.val; -import lombok.core.HandlerPriority; import lombok.var; +import lombok.core.HandlerPriority; import lombok.javac.JavacASTAdapter; import lombok.javac.JavacASTVisitor; import lombok.javac.JavacNode; import lombok.javac.JavacResolution; import lombok.javac.ResolutionResetNeeded; +import lombok.permit.Permit; import lombok.spi.Provides; import com.sun.tools.javac.code.Flags; @@ -87,7 +91,8 @@ public class HandleVal extends JavacASTAdapter { if (local.init == null) { if (parentRaw instanceof JCEnhancedForLoop) { JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw; - if (efl.var == local) rhsOfEnhancedForLoop = efl.expr; + JCTree var = EnhancedForLoopReflect.getVarOrRecordPattern(efl); + if (var == local) rhsOfEnhancedForLoop = efl.expr; } } @@ -191,4 +196,19 @@ public class HandleVal extends JavacASTAdapter { recursiveSetGeneratedBy(local.vartype, typeNode); } } + + private static class EnhancedForLoopReflect { + private static final Field varOrRecordPattern = Permit.permissiveGetField(JCEnhancedForLoop.class, "varOrRecordPattern"); + + private static JCTree getVarOrRecordPattern(JCEnhancedForLoop loop) { + if (varOrRecordPattern == null) { + return loop.var; + } + + try { + return (JCTree) varOrRecordPattern.get(loop); + } catch (Exception ignore) {} + return null; + } + } } diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index 9d153a72..593a1aa8 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -512,6 +512,13 @@ public class JavacHandlerUtil { case LOCAL: JCVariableDecl variable = (JCVariableDecl) parentNode.get(); variable.mods.annotations = filterList(variable.mods.annotations, annotation.get()); + + if ((variable.mods.flags & GENERATED_MEMBER) != 0) { + JavacNode typeNode = upToTypeNode(annotation); + if (isRecord(typeNode)) { + RecordComponentReflect.deleteAnnotation((JCClassDecl) typeNode.get(), variable, annotation.get()); + } + } break; case METHOD: JCMethodDecl method = (JCMethodDecl) parentNode.get(); @@ -559,6 +566,47 @@ public class JavacHandlerUtil { return newAnnotations.toList(); } + private static List<JCAnnotation> filterListByPos(List<JCAnnotation> annotations, JCTree jcTree) { + ListBuffer<JCAnnotation> newAnnotations = new ListBuffer<JCAnnotation>(); + for (JCAnnotation ann : annotations) { + if (jcTree.pos != ann.pos) newAnnotations.append(ann); + } + return newAnnotations.toList(); + } + + + static class RecordComponentReflect { + + private static final Field astField; + private static final Method findRecordComponentToRemove; + + static { + Field a = null; + Method m = null; + try { + Class<?> forName = Class.forName("com.sun.tools.javac.code.Symbol$RecordComponent"); + a = Permit.permissiveGetField(forName, "ast"); + m = Permit.permissiveGetMethod(ClassSymbol.class, "findRecordComponentToRemove", JCVariableDecl.class); + } catch (Throwable e) { + // Ignore + } + astField = a; + findRecordComponentToRemove = m; + } + + static void deleteAnnotation(JCClassDecl record, JCVariableDecl component, JCTree annotation) { + if (astField == null || findRecordComponentToRemove == null) return; + + try { + Object toRemove = Permit.invokeSneaky(findRecordComponentToRemove, record.sym, component); + JCVariableDecl variable = (JCVariableDecl) Permit.get(astField, toRemove); + variable.mods.annotations = filterListByPos(variable.mods.annotations, annotation); + } catch (Throwable e) { + // Ignore + } + } + } + /** Serves as return value for the methods that check for the existence of fields and methods. */ public enum MemberExistsResult { NOT_EXISTS, EXISTS_BY_LOMBOK, EXISTS_BY_USER; diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java index 13836d77..b8b38da9 100644 --- a/src/delombok/lombok/delombok/PrettyPrinter.java +++ b/src/delombok/lombok/delombok/PrettyPrinter.java @@ -1253,7 +1253,14 @@ public class PrettyPrinter extends JCTree.Visitor { @Override public void visitForeachLoop(JCEnhancedForLoop tree) { aPrint("for ("); - printVarDefInline(tree.var); + JCTree varOrRecordPattern = readObject(tree, "varOrRecordPattern", null); + if (varOrRecordPattern instanceof JCVariableDecl) { + printVarDefInline((JCVariableDecl) varOrRecordPattern); + } else if (varOrRecordPattern != null) { + print(varOrRecordPattern); + } else { + printVarDefInline(tree.var); + } print(" : "); print(tree.expr); print(") "); @@ -1427,9 +1434,7 @@ public class PrettyPrinter extends JCTree.Visitor { void printBindingPattern(JCTree tree) { JCTree var = readObject(tree, "var", tree); - print((JCExpression) readObject(var, "vartype", null)); - print(" "); - print((Name) readObject(var, "name", null)); + printVarDef0((JCVariableDecl) var); } void printDefaultCase(JCTree tree) { diff --git a/test/pretty/resource/after/RecordPattern.java b/test/pretty/resource/after/RecordPattern19.java index ad9fae0b..68b39266 100644 --- a/test/pretty/resource/after/RecordPattern.java +++ b/test/pretty/resource/after/RecordPattern19.java @@ -3,13 +3,13 @@ record Point(int x, int y) { record Rectangle(Point upperLeft, Point lowerRight) { } -public class RecordPattern { +public class RecordPattern19 { void recordPattern(Object o) { if (o instanceof Point(int x, int y)) { } if (o instanceof Point(int x, int y) p) { } - if (o instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) { + 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/RecordPattern20.java b/test/pretty/resource/after/RecordPattern20.java new file mode 100644 index 00000000..365b139f --- /dev/null +++ b/test/pretty/resource/after/RecordPattern20.java @@ -0,0 +1,22 @@ +record Point(int x, int y) { +} +record Rectangle(Point upperLeft, Point lowerRight) { +} + +public class RecordPattern20 { + 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))) { + } + } + + void forEachSimple(Point[] pointArray) { + for (Point(var x, var y) : pointArray) { + } + } + void forEachNested(Rectangle[] rectangleArray) { + for (Rectangle(Point(var x1, var y1), Point p) : rectangleArray) { + } + } +}
\ No newline at end of file diff --git a/test/pretty/resource/before/RecordPattern.java b/test/pretty/resource/before/RecordPattern19.java index 93c07965..4c417174 100644 --- a/test/pretty/resource/before/RecordPattern.java +++ b/test/pretty/resource/before/RecordPattern19.java @@ -1,16 +1,16 @@ -// version 19: +// version 19:19 record Point(int x, int y) { } record Rectangle(Point upperLeft, Point lowerRight) { } -public class RecordPattern { +public class RecordPattern19 { void recordPattern(Object o) { if (o instanceof Point(int x, int y)) { } if (o instanceof Point(int x, int y) p) { } - if (o instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) { + 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/RecordPattern20.java b/test/pretty/resource/before/RecordPattern20.java new file mode 100644 index 00000000..8604215b --- /dev/null +++ b/test/pretty/resource/before/RecordPattern20.java @@ -0,0 +1,23 @@ +// version 20: +record Point(int x, int y) { +} +record Rectangle(Point upperLeft, Point lowerRight) { +} + +public class RecordPattern20 { + 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))) { + } + } + + void forEachSimple(Point[] pointArray) { + for (Point(var x, var y) : pointArray) { + } + } + void forEachNested(Rectangle[] rectangleArray) { + for (Rectangle(Point(var x1, var y1), Point p) : rectangleArray) { + } + } +}
\ No newline at end of file |