diff --git a/src/core/lombok/javac/CompilerMessageSuppressor.java b/src/core/lombok/javac/CompilerMessageSuppressor.java index 7d7b81e677..fc820b908e 100644 --- a/src/core/lombok/javac/CompilerMessageSuppressor.java +++ b/src/core/lombok/javac/CompilerMessageSuppressor.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2021 The Project Lombok Authors. + * Copyright (C) 2011-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 @@ -24,7 +24,10 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collection; import java.util.LinkedList; import java.util.Map; import java.util.Queue; @@ -36,7 +39,6 @@ import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic; -import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; import lombok.permit.Permit; @@ -53,9 +55,14 @@ public final class CompilerMessageSuppressor { private static final Field deferDiagnosticsField, deferredDiagnosticsField, diagnosticHandlerField; private static final ConcurrentMap, Field> handlerDeferredFields = new ConcurrentHashMap, Field>(); private static final Field NULL_FIELD; + private static final Class DIAGNOSTIC_HANDLER; + private static final Class DISCARD_DIAGNOSTIC_HANDLER; + private static final Method POP_DIAGNOSTIC_HANDLER; + private static final Constructor DISCARD_DIAGNOSTIC_HANDLER_CONSTRUCTOR; private Boolean dumpOnError, promptOnError; private DiagnosticListener contextDiagnosticListener, logDiagnosticListener; private final Context context; + private Object diagnosticHandler; private static final ThreadLocal> queueCache = new ThreadLocal>(); @@ -87,6 +94,11 @@ enum Writers { diagnosticHandlerField = getDeclaredField(Log.class, "diagnosticHandler"); NULL_FIELD = getDeclaredField(JavacResolution.class, "NULL_FIELD"); + + DIAGNOSTIC_HANDLER = getClass("com.sun.tools.javac.util.Log$DiagnosticHandler"); + DISCARD_DIAGNOSTIC_HANDLER = getClass("com.sun.tools.javac.util.Log$DiscardDiagnosticHandler"); + POP_DIAGNOSTIC_HANDLER = DIAGNOSTIC_HANDLER != null ? Permit.permissiveGetMethod(Log.class, "popDiagnosticHandler", DIAGNOSTIC_HANDLER) : null; + DISCARD_DIAGNOSTIC_HANDLER_CONSTRUCTOR = DISCARD_DIAGNOSTIC_HANDLER != null ? Permit.permissiveGetConstructor(DISCARD_DIAGNOSTIC_HANDLER, Log.class) : null; } static Field getDeclaredField(Class c, String fieldName) { @@ -97,6 +109,14 @@ static Field getDeclaredField(Class c, String fieldName) { } } + static Class getClass(String name) { + try { + return Class.forName(name); + } catch (Throwable t) { + return null; + } + } + public CompilerMessageSuppressor(Context context) { this.log = Log.instance(context); this.context = context; @@ -118,16 +138,6 @@ public void disableLoggers() { } } catch (Exception e) {} - if (diagnosticHandlerField != null) try { - Object handler = diagnosticHandlerField.get(log); - Field field = getDeferredField(handler); - if (field != null) { - queueCache.set((Queue) field.get(handler)); - Queue empty = new LinkedList(); - field.set(handler, empty); - } - } catch (Exception e) {} - if (dumpOnErrorField != null) try { dumpOnError = (Boolean) dumpOnErrorField.get(log); dumpOnErrorField.set(log, false); @@ -145,6 +155,11 @@ public void disableLoggers() { diagnosticListenerField.set(log, null); } catch (Exception e) { } + + if (DISCARD_DIAGNOSTIC_HANDLER != null) try { + diagnosticHandler = Permit.newInstance(DISCARD_DIAGNOSTIC_HANDLER_CONSTRUCTOR, log); + } catch (Exception e) { + } } private static Field getDeferredField(Object handler) { @@ -183,19 +198,15 @@ public void enableLoggers() { logDiagnosticListener = null; } catch (Exception e) {} - if (diagnosticHandlerField != null && queueCache.get() != null) try { - Object handler = diagnosticHandlerField.get(log); - Field field = getDeferredField(handler); - if (field != null) { - field.set(handler, queueCache.get()); - queueCache.set(null); - } - } catch (Exception e) {} - if (deferDiagnosticsField != null && queueCache.get() != null) try { deferredDiagnosticsField.set(log, queueCache.get()); queueCache.set(null); } catch (Exception e) {} + + if (diagnosticHandler != null) try { + Permit.invoke(POP_DIAGNOSTIC_HANDLER, log, diagnosticHandler); + } catch (Exception e) {} + diagnosticHandler = null; } public void removeAllBetween(JavaFileObject sourcefile, int startPos, int endPos) { @@ -222,11 +233,12 @@ public void removeAllBetween(JavaFileObject sourcefile, int startPos, int endPos if (field == null || receiver == null) return; try { - ListBuffer deferredDiagnostics = (ListBuffer) field.get(receiver); - ListBuffer newDeferredDiagnostics = new ListBuffer(); + Collection deferredDiagnostics = (Collection) field.get(receiver); + if (deferredDiagnostics.isEmpty()) return; + LinkedList newDeferredDiagnostics = new LinkedList(); for (Object diag_ : deferredDiagnostics) { if (!(diag_ instanceof JCDiagnostic)) { - newDeferredDiagnostics.append(diag_); + newDeferredDiagnostics.add(diag_); continue; } JCDiagnostic diag = (JCDiagnostic) diag_; @@ -234,7 +246,7 @@ public void removeAllBetween(JavaFileObject sourcefile, int startPos, int endPos if (here >= startPos && here < endPos && diag.getSource() == sourcefile) { // We eliminate it } else { - newDeferredDiagnostics.append(diag); + newDeferredDiagnostics.add(diag); } } field.set(receiver, newDeferredDiagnostics); diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 9504bc4ac6..fc548bd1b1 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -68,6 +68,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Position; /** * Wraps around javac's internal AST view to add useful features as well as the ability to visit parents from children, @@ -595,6 +596,7 @@ void printMessage(Diagnostic.Kind kind, String message, JavacNode node, Diagnost } public void removeFromDeferredDiagnostics(int startPos, int endPos) { + if (startPos == Position.NOPOS || endPos == Position.NOPOS) return; JCCompilationUnit self = (JCCompilationUnit) top().get(); new CompilerMessageSuppressor(getContext()).removeAllBetween(self.sourcefile, startPos, endPos); } diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java index 6ff6efe732..a8cdfca344 100644 --- a/src/core/lombok/javac/JavacResolution.java +++ b/src/core/lombok/javac/JavacResolution.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2021 The Project Lombok Authors. + * Copyright (C) 2011-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 @@ -416,7 +416,7 @@ private static Iterable concat(final Type t, final Collection 0) winner = t; } if (winner == null) return createJavaLangObject(ast); return typeToJCTree(winner, ast, allowCompound, allowVoid, allowCapture); diff --git a/src/utils/lombok/permit/Permit.java b/src/utils/lombok/permit/Permit.java index d58a35e62d..36e38bcb01 100644 --- a/src/utils/lombok/permit/Permit.java +++ b/src/utils/lombok/permit/Permit.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2021 The Project Lombok Authors. + * Copyright (C) 2018-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 @@ -165,6 +165,14 @@ public static Constructor getConstructor(Class c, Class... paramete return setAccessible(c.getDeclaredConstructor(parameterTypes)); } + public static Constructor permissiveGetConstructor(Class c, Class... parameterTypes) { + try { + return getConstructor(c, parameterTypes); + } catch (Exception ignore) { + return null; + } + } + private static Object reflectiveStaticFieldAccess(Class c, String fName) { try { Field f = c.getDeclaredField(fName); diff --git a/test/transform/resource/after-delombok/ExtensionMethodInLambda.java b/test/transform/resource/after-delombok/ExtensionMethodInLambda.java index 56f374dfe9..99f03234da 100644 --- a/test/transform/resource/after-delombok/ExtensionMethodInLambda.java +++ b/test/transform/resource/after-delombok/ExtensionMethodInLambda.java @@ -2,6 +2,8 @@ import java.util.function.Function; public class ExtensionMethodInLambda { + private static final Function testStatic = s -> ExtensionMethodInLambda.Extensions.reverse(s); + public void testSimple() { String test = "test"; test = ExtensionMethodInLambda.Extensions.map(test, s -> ExtensionMethodInLambda.Extensions.reverse(s)); diff --git a/test/transform/resource/after-ecj/ExtensionMethodInLambda.java b/test/transform/resource/after-ecj/ExtensionMethodInLambda.java index ef2b2cacb4..2d1a4e9577 100644 --- a/test/transform/resource/after-ecj/ExtensionMethodInLambda.java +++ b/test/transform/resource/after-ecj/ExtensionMethodInLambda.java @@ -15,6 +15,9 @@ public static String trim(Integer integer) { return "0"; } } + private static final Function testStatic = ( s) -> ExtensionMethodInLambda.Extensions.reverse(s); + () { + } public ExtensionMethodInLambda() { super(); } diff --git a/test/transform/resource/before/ExtensionMethodInLambda.java b/test/transform/resource/before/ExtensionMethodInLambda.java index c441a9243e..c89933f50a 100644 --- a/test/transform/resource/before/ExtensionMethodInLambda.java +++ b/test/transform/resource/before/ExtensionMethodInLambda.java @@ -4,6 +4,8 @@ @ExtensionMethod(value = ExtensionMethodInLambda.Extensions.class) public class ExtensionMethodInLambda { + private static final Function testStatic = s -> s.reverse(); + public void testSimple() { String test = "test"; test = test.map(s -> s.reverse()); diff --git a/test/transform/resource/messages-delombok/ExtensionMethodInLambda.java.messages b/test/transform/resource/messages-delombok/ExtensionMethodInLambda.java.messages index 7605def9db..70d7a89995 100644 --- a/test/transform/resource/messages-delombok/ExtensionMethodInLambda.java.messages +++ b/test/transform/resource/messages-delombok/ExtensionMethodInLambda.java.messages @@ -1 +1 @@ -19 cannot find symbol symbol: method invalid((s)->s.reverse()) location: variable test of type java.lang.String \ No newline at end of file +21 cannot find symbol symbol: method invalid((s)->s.reverse()) location: variable test of type java.lang.String \ No newline at end of file diff --git a/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages b/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages index da0df31595..63b2ee1e4d 100644 --- a/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages +++ b/test/transform/resource/messages-delombok/ValInvalidParameter.java.messages @@ -1 +1,7 @@ +6 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +7 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +8 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +9 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +10 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved +11 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved 12 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved \ No newline at end of file diff --git a/test/transform/resource/messages-ecj/ExtensionMethodInLambda.java.messages b/test/transform/resource/messages-ecj/ExtensionMethodInLambda.java.messages index 56888c3480..879ae231c1 100644 --- a/test/transform/resource/messages-ecj/ExtensionMethodInLambda.java.messages +++ b/test/transform/resource/messages-ecj/ExtensionMethodInLambda.java.messages @@ -1 +1 @@ -19 The method invalid(( s) -> {}) is undefined for the type String +21 The method invalid(( s) -> {}) is undefined for the type String diff --git a/test/transform/resource/messages-idempotent/ExtensionMethodInLambda.java.messages b/test/transform/resource/messages-idempotent/ExtensionMethodInLambda.java.messages index 15d7087506..7605def9db 100644 --- a/test/transform/resource/messages-idempotent/ExtensionMethodInLambda.java.messages +++ b/test/transform/resource/messages-idempotent/ExtensionMethodInLambda.java.messages @@ -1 +1 @@ -17 cannot find symbol symbol: method invalid((s)->s.reverse()) location: variable test of type java.lang.String \ No newline at end of file +19 cannot find symbol symbol: method invalid((s)->s.reverse()) location: variable test of type java.lang.String \ No newline at end of file