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 {}