diff --git a/.github/workflows/ant.yml b/.github/workflows/ant.yml
index 7552c536..390375d2 100644
--- a/.github/workflows/ant.yml
+++ b/.github/workflows/ant.yml
@@ -41,10 +41,10 @@ jobs:
runs-on: ubuntu-24.04
needs: build
env:
- EA_JDK: 24
+ EA_JDK: 25
strategy:
matrix:
- jdk: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
+ jdk: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
goal: [javacCurrent]
include:
- jdk: 11
diff --git a/buildScripts/tests.ant.xml b/buildScripts/tests.ant.xml
index 90fb89c3..1936ab88 100644
--- a/buildScripts/tests.ant.xml
+++ b/buildScripts/tests.ant.xml
@@ -140,24 +140,33 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn
+
+
+
+
+
+
+
+
+
Running TestJavac on JVM${ant.java.version}, with the javac built into your VM distributon.
@@ -337,5 +346,5 @@ This buildfile is part of projectlombok.org. It takes care of compiling and runn
-
+
diff --git a/buildScripts/vm-finder.ant.xml b/buildScripts/vm-finder.ant.xml
index 2a33b2b8..94682fa4 100644
--- a/buildScripts/vm-finder.ant.xml
+++ b/buildScripts/vm-finder.ant.xml
@@ -62,7 +62,7 @@ and rerun the build; this build is capable of finding VMs automatically on many
-
+
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 215a2110..9504bc4a 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2020 The Project Lombok Authors.
+ * Copyright (C) 2009-2025 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
@@ -41,6 +41,7 @@ import lombok.core.CleanupRegistry;
import lombok.core.CleanupTask;
import lombok.permit.Permit;
+import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.model.JavacElements;
@@ -415,7 +416,6 @@ public class JavacAST extends AST {
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) {
@@ -581,9 +581,6 @@ public class JavacAST extends AST {
case ERROR:
errorLogger.error(pos, message);
break;
- case MANDATORY_WARNING:
- errorLogger.mandatoryWarning(pos, message);
- break;
case WARNING:
errorLogger.warning(pos, message);
break;
@@ -596,7 +593,7 @@ public class JavacAST extends AST {
if (newSource != null) errorLogger.useSource(oldSource);
}
}
-
+
public void removeFromDeferredDiagnostics(int startPos, int endPos) {
JCCompilationUnit self = (JCCompilationUnit) top().get();
new CompilerMessageSuppressor(getContext()).removeAllBetween(self.sourcefile, startPos, endPos);
@@ -643,29 +640,23 @@ public class JavacAST extends AST {
this.errorCount = errorCount;
this.warningCount = warningCount;
}
-
+
final JavaFileObject useSource(JavaFileObject file) {
return log.useSource(file);
}
-
+
final void error(DiagnosticPosition pos, String message) {
increment(errorCount);
error1(pos, message);
}
-
+
final void warning(DiagnosticPosition pos, String message) {
increment(warningCount);
warning1(pos, message);
}
-
- final void mandatoryWarning(DiagnosticPosition pos, String message) {
- increment(warningCount);
- mandatoryWarning1(pos, message);
- }
-
+
abstract void error1(DiagnosticPosition pos, String message);
abstract void warning1(DiagnosticPosition pos, String message);
- abstract void mandatoryWarning1(DiagnosticPosition pos, String message);
abstract void note(DiagnosticPosition pos, String message);
private void increment(Field field) {
@@ -689,7 +680,6 @@ public class JavacAST extends AST {
for (Field field : log.getClass().getFields()) {
if (field.getName().equals("multipleErrors")) {
hasMultipleErrors = true;
- break;
}
}
if (hasMultipleErrors) return new JdkBefore9(log, messager, errorCount);
@@ -708,7 +698,7 @@ public class JavacAST extends AST {
private JdkBefore9(Log log, Messager messager, Field errorCount) {
super(log, messager, errorCount, null);
}
-
+
@Override void error1(DiagnosticPosition pos, String message) {
boolean prev = log.multipleErrors;
log.multipleErrors = true;
@@ -718,15 +708,11 @@ public class JavacAST extends AST {
log.multipleErrors = prev;
}
}
-
+
@Override void warning1(DiagnosticPosition pos, String message) {
log.warning(pos, "proc.messager", message);
}
-
- @Override void mandatoryWarning1(DiagnosticPosition pos, String message) {
- log.mandatoryWarning(pos, "proc.messager", message);
- }
-
+
@Override void note(DiagnosticPosition pos, String message) {
log.note(pos, "proc.messager", message);
}
@@ -735,20 +721,20 @@ public class JavacAST extends AST {
static class Jdk9Plus extends ErrorLog {
private static final String PROC_MESSAGER = "proc.messager";
private Object multiple;
- private Method errorMethod, warningMethod, mandatoryWarningMethod, noteMethod;
+ private Method errorMethod, warningMethod, noteMethod;
private Method errorKey, warningKey, noteKey;
private JCDiagnostic.Factory diags;
private Jdk9Plus(Log log, Messager messager, Field errorCount, Field warningCount) {
super(log, messager, errorCount, warningCount);
-
+
try {
final String jcd = "com.sun.tools.javac.util.JCDiagnostic";
Class> df = Class.forName(jcd + "$DiagnosticFlag");
for (Object constant : df.getEnumConstants()) {
if (constant.toString().equals("MULTIPLE")) this.multiple = constant;
}
-
+
Class> errorCls = Class.forName(jcd + "$Error");
Class> warningCls = Class.forName(jcd + "$Warning");
Class> noteCls = Class.forName(jcd + "$Note");
@@ -756,15 +742,17 @@ public class JavacAST extends AST {
Class> lc = log.getClass();
this.errorMethod = Permit.getMethod(lc, "error", df, DiagnosticPosition.class, errorCls);
this.warningMethod = Permit.getMethod(lc, "warning", DiagnosticPosition.class, warningCls);
- this.mandatoryWarningMethod = Permit.getMethod(lc, "mandatoryWarning", DiagnosticPosition.class, warningCls);
this.noteMethod = Permit.getMethod(lc, "note", DiagnosticPosition.class, noteCls);
-
+
Field diagsField = Permit.getField(lc.getSuperclass(), "diags");
this.diags = (JCDiagnostic.Factory) diagsField.get(log);
-
+
Class> dc = this.diags.getClass();
this.errorKey = Permit.getMethod(dc, "errorKey", String.class, Object[].class);
- this.warningKey = Permit.getMethod(dc, "warningKey", String.class, Object[].class);
+ this.warningKey = Permit.permissiveGetMethod(dc, "warningKey", String.class, Object[].class);
+ if (warningKey == null) {
+ this.warningKey = Permit.getMethod(dc, "warningKey", LintCategory.class, String.class, Object[].class);
+ }
this.noteKey = Permit.getMethod(dc, "noteKey", String.class, Object[].class);
} catch (Throwable t) {
//t.printStackTrace();
@@ -775,19 +763,18 @@ public class JavacAST extends AST {
Object error = Permit.invokeSneaky(this.errorKey, diags, PROC_MESSAGER, new Object[] { message });
if (error != null) Permit.invokeSneaky(errorMethod, log, multiple, pos, error);
}
-
+
@Override
void warning1(DiagnosticPosition pos, String message) {
- Object warning = Permit.invokeSneaky(this.warningKey, diags, PROC_MESSAGER, new Object[] { message });
+ Object warning;
+ if (this.warningKey.getParameterTypes().length == 3) {
+ warning = Permit.invokeSneaky(this.warningKey, diags, null, PROC_MESSAGER, new Object[] { message });
+ } else {
+ warning = Permit.invokeSneaky(this.warningKey, diags, PROC_MESSAGER, new Object[] { message });
+ }
if (warning != null) Permit.invokeSneaky(warningMethod, log, pos, warning);
}
-
- @Override
- void mandatoryWarning1(DiagnosticPosition pos, String message) {
- Object warning = Permit.invokeSneaky(this.warningKey, diags, PROC_MESSAGER, new Object[] { message });
- if (warning != null) Permit.invokeSneaky(mandatoryWarningMethod, log, pos, warning);
- }
-
+
@Override
void note(DiagnosticPosition pos, String message) {
Object note = Permit.invokeSneaky(this.noteKey, diags, PROC_MESSAGER, new Object[] { message });
diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java
index 53ed4728..ae0ce282 100644
--- a/src/delombok/lombok/delombok/PrettyPrinter.java
+++ b/src/delombok/lombok/delombok/PrettyPrinter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016-2024 The Project Lombok Authors.
+ * Copyright (C) 2016-2025 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
@@ -92,13 +92,13 @@ import com.sun.tools.javac.util.Name;
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;
import lombok.javac.CommentInfo.StartConnection;
+import lombok.javac.Javac;
import lombok.javac.JavacTreeMaker.TreeTag;
import lombok.javac.JavacTreeMaker.TypeTag;
+import lombok.javac.PackageName;
+import lombok.permit.Permit;
public class PrettyPrinter extends JCTree.Visitor {
private static final String LINE_SEP = System.getProperty("line.separator");
@@ -514,8 +514,22 @@ public class PrettyPrinter extends JCTree.Visitor {
println(";", tree);
}
+ void printModuleImport(JCTree tree) {
+ JCExpression qualid = readObject(tree, "module", null);
+
+ aPrint("import module ");
+ print(qualid);
+ println(";", tree);
+ }
+
private Name currentTypeName;
@Override public void visitClassDef(JCClassDecl tree) {
+ if ((tree.mods.flags & IMPLICIT_CLASS) != 0) {
+ printClassMembers(tree.defs, false, false);
+ consumeComments(endPos(tree));
+ return;
+ }
+
println();
printDocComment(tree);
align();
@@ -697,7 +711,7 @@ public class PrettyPrinter extends JCTree.Visitor {
*/
try {
innermostArrayBracketsAreVarargs = varargs;
- if (tree.vartype == null || tree.vartype.pos == -1) {
+ if (tree.vartype == null || tree.vartype.pos == -1 || endPos(tree.vartype) == -1) {
print("var");
} else {
print(tree.vartype);
@@ -1033,7 +1047,7 @@ public class PrettyPrinter extends JCTree.Visitor {
if ((v & NATIVE) != 0) print("native ");
if ((v & ABSTRACT) != 0) print("abstract ");
if ((v & SEALED) != 0) print("sealed ");
- if ((v & NON_SEALED) != 0) print("non-sealed ");
+ if ((v & NON_SEALED) != 0) print("non-sealed "); // Yes, this is a real keyword.
if ((v & STRICTFP) != 0) print("strictfp ");
if ((v & DEFAULT) != 0 && (v & INTERFACE) == 0) print("default ");
}
@@ -1710,6 +1724,8 @@ public class PrettyPrinter extends JCTree.Visitor {
printRecordPattern(tree);
} else if (className.endsWith("$JCAnyPattern")) { // Introduced in JDK22
print("_");
+ } else if (className.endsWith("$JCModuleImport")) { // Introduced in JDK25
+ printModuleImport(tree);
} else {
throw new AssertionError("Unhandled tree type: " + tree.getClass() + ": " + tree);
}
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index 22edcd05..08c13cc4 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.java
@@ -77,13 +77,14 @@ public class Javac {
private static final AtomicInteger compilerVersion = new AtomicInteger(-1);
- /* This section includes flags that would ordinarily be in Flags, but which are 'too new' (we don't compile against older versions of javac for compatibility). */
+ /* This section includes flags that would ordinarily be in com.sun.tools.javac.code.Flags, but which are 'too new' (we don't compile against older versions of javac for compatibility). */
public static final long RECORD = 1L << 61; // ClassSymbols, MethodSymbols, VarSymbols (Marks types as being records, as well as the 'fields' in the compact declaration, and the canonical constructor)
public static final long COMPACT_RECORD_CONSTRUCTOR = 1L << 51; // MethodSymbols (the 'implicit' many-args constructor that records have)
public static final long UNINITIALIZED_FIELD = 1L << 51; // VarSymbols (To identify fields that the compact record constructor won't initialize)
public static final long GENERATED_MEMBER = 1L << 24; // MethodSymbols, VarSymbols (marks methods and the constructor generated in records)
- public static final long SEALED = 1L << 62; // ClassSymbols (Flag to indicate sealed class/interface declaration)
+ public static final long SEALED = 1L << 62 | 1L << 48; // ClassSymbols (Flag to indicate sealed class/interface declaration) - from the introduction of sealed until ~jdk23, this was 62. In jdk24, it's 48. Ugh.
public static final long NON_SEALED = 1L << 63; // ClassSymbols (Flag to indicate that the class/interface was declared with the non-sealed modifier)
+ public static final long IMPLICIT_CLASS = 1L << 19; // ClassSymbols (Flag to indicate that the class/interface wasn't actually written out; it is an implicitly declared top-level class). Introduced in JDK25, JEP512.
/**
* Returns the version of this java compiler, i.e. the JDK that it shipped in. For example, for javac v1.7, this returns {@code 7}.
diff --git a/test/pretty/resource/after/CompactSourceFile.java b/test/pretty/resource/after/CompactSourceFile.java
new file mode 100644
index 00000000..e60d5b98
--- /dev/null
+++ b/test/pretty/resource/after/CompactSourceFile.java
@@ -0,0 +1,3 @@
+void main() {
+ IO.print("This is valid java as of JDK25");
+}
diff --git a/test/pretty/resource/after/ModuleImport.java b/test/pretty/resource/after/ModuleImport.java
new file mode 100644
index 00000000..90b7ea72
--- /dev/null
+++ b/test/pretty/resource/after/ModuleImport.java
@@ -0,0 +1,4 @@
+import module java.base;
+
+public class ModuleImport {
+}
diff --git a/test/pretty/resource/before/CompactSourceFile.java b/test/pretty/resource/before/CompactSourceFile.java
new file mode 100644
index 00000000..7c598aca
--- /dev/null
+++ b/test/pretty/resource/before/CompactSourceFile.java
@@ -0,0 +1,5 @@
+// version 25:
+
+void main() {
+ IO.print("This is valid java as of JDK25");
+}
diff --git a/test/pretty/resource/before/ModuleImport.java b/test/pretty/resource/before/ModuleImport.java
new file mode 100644
index 00000000..782680f1
--- /dev/null
+++ b/test/pretty/resource/before/ModuleImport.java
@@ -0,0 +1,5 @@
+// version 25:
+
+import module java.base;
+
+public class ModuleImport {}