aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--buildScripts/tests.ant.xml6
-rw-r--r--doc/changelog.markdown2
-rw-r--r--src/core/lombok/javac/JavacAST.java28
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java41
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java24
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java48
-rw-r--r--src/delombok/lombok/delombok/PrettyPrinter.java13
-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.java22
-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.java23
11 files changed, 163 insertions, 54 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/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java
index ed713b1d..0467d758 100644
--- a/src/core/lombok/javac/apt/LombokProcessor.java
+++ b/src/core/lombok/javac/apt/LombokProcessor.java
@@ -25,7 +25,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
@@ -305,10 +304,7 @@ public class LombokProcessor extends AbstractProcessor {
// Step 1: Take all CUs which aren't already in the map. Give them the first priority level.
- String randomModuleName = null;
-
for (Element element : roundEnv.getRootElements()) {
- if (randomModuleName == null) randomModuleName = getModuleNameFor(element);
JCCompilationUnit unit = toUnit(element);
if (unit == null) continue;
if (roots.containsKey(unit)) continue;
@@ -353,7 +349,7 @@ public class LombokProcessor extends AbstractProcessor {
newLevels.retainAll(priorityLevelsRequiringResolutionReset);
if (!newLevels.isEmpty()) {
// Force a new round to reset resolution. The next round will cause this method (process) to be called again.
- forceNewRound(randomModuleName, javacFiler);
+ forceNewRound(javacFiler);
return false;
}
// None of the new levels need resolution, so just keep going.
@@ -361,7 +357,7 @@ public class LombokProcessor extends AbstractProcessor {
}
private int dummyCount = 0;
- private void forceNewRound(String randomModuleName, JavacFiler filer) {
+ private void forceNewRound(JavacFiler filer) {
if (!filer.newFiles()) {
try {
filer.getGeneratedSourceNames().add("lombok.dummy.ForceNewRound" + (dummyCount++));
@@ -372,38 +368,7 @@ public class LombokProcessor extends AbstractProcessor {
}
}
}
-
- private String getModuleNameFor(Element element) {
- while (element != null) {
- if (element.getKind().name().equals("MODULE")) return getModuleName(element);
- Element n = element.getEnclosingElement();
- if (n == element) return null;
- element = n;
- }
- return null;
- }
-
- private static Class<?> qualifiedNamableClass = null;
- private static Method qualifiedNamableQualifiedNameMethod = null;
- // QualifiedNameable isn't in java 6, so to remain compatible with java6, use reflection.
- private static String getModuleName(Element element) {
- try {
- if (qualifiedNamableClass == null) qualifiedNamableClass = Class.forName("javax.lang.model.element.QualifiedNamable");
- if (!qualifiedNamableClass.isInstance(element)) return null;
- if (qualifiedNamableQualifiedNameMethod == null) qualifiedNamableQualifiedNameMethod = Permit.getMethod(qualifiedNamableClass, "getQualifiedName");
- String name = Permit.invoke(qualifiedNamableQualifiedNameMethod, element).toString().trim();
- return name.isEmpty() ? null : name;
- } catch (ClassNotFoundException e) {
- return null;
- } catch (NoSuchMethodException e) {
- return null;
- } catch (InvocationTargetException e) {
- return null;
- } catch (IllegalAccessException e) {
- return null;
- }
- }
-
+
private JCCompilationUnit toUnit(Element element) {
TreePath path = null;
if (trees != null) {
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 aaa7a022..ac947581 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -520,6 +520,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();
@@ -567,6 +574,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