From 9bf0c63c47e7bfcfa80eec5feea1f3b6556df0aa Mon Sep 17 00:00:00 2001
From: Suzanne Millstein <smillst@cs.washington.edu>
Date: Wed, 25 Jun 2025 17:29:28 -0700
Subject: [PATCH] Make the Checker Framework compile with/run on JDK 25
Origin: backport, https://github.com/typetools/checker-framework/commit/9bf0c63c47e7bfcfa80eec5feea1f3b6556df0aa
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1128165
Bug-Ubuntu: https://bugs.launchpad.net/debian/+source/checker-framework-java/+bug/2142432

--- a/javacutil/src/main/java/org/checkerframework/javacutil/Resolver.java
+++ b/javacutil/src/main/java/org/checkerframework/javacutil/Resolver.java
@@ -18,6 +18,7 @@
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
 import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Names;
 import java.lang.reflect.Constructor;
@@ -55,6 +56,13 @@
     // Note that currently access(...) is defined in InvalidSymbolError, a superclass of AccessError
     private static final Method ACCESSERROR_ACCESS;
 
+    /**
+    * Method for new Log.DiscardDiagnosticHandler. Before JDK 25, DiscardDiagnosticHandler was a
+    * static inner class of Log and an instance of log was passed as the first argument. Starting
+    * with JDK 25, DiscardDiagnosticHandler is an inner class of log.
+    */
+    private static final Constructor<DiscardDiagnosticHandler> NEW_DIAGNOSTIC_HANDLER;
+
     static {
         try {
             FIND_METHOD =
@@ -97,6 +105,14 @@
 
             FIND_TYPE = Resolve.class.getDeclaredMethod("findType", Env.class, Name.class);
             FIND_TYPE.setAccessible(true);
+
+            // Pre JDK 25:
+            //   new Log.DiscardDiagnosticHandler(log)
+            // JDK 25:
+            //   log.new DiscardDiagnosticHandler()
+            // But both of those are reflectively accessed the same way.
+            NEW_DIAGNOSTIC_HANDLER = Log.DiscardDiagnosticHandler.class.getConstructor(Log.class);
+            NEW_DIAGNOSTIC_HANDLER.setAccessible(true);
         } catch (Exception e) {
             Error err =
                     new AssertionError(
@@ -160,7 +176,7 @@
      * @return the {@code PackageSymbol} for the package if it is found, {@code null} otherwise
      */
     public @Nullable PackageSymbol findPackage(String name, TreePath path) {
-        Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+        Log.DiagnosticHandler discardDiagnosticHandler = newDiagnosticHandler();
         try {
             Env<AttrContext> env = getEnvForPath(path);
             Element res =
@@ -192,7 +208,7 @@
      * @return the element for the field, {@code null} otherwise
      */
     public @Nullable VariableElement findField(String name, TypeMirror type, TreePath path) {
-        Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+        Log.DiagnosticHandler discardDiagnosticHandler = newDiagnosticHandler();
         try {
             Env<AttrContext> env = getEnvForPath(path);
             Element res =
@@ -226,7 +242,7 @@
      */
     public @Nullable VariableElement findLocalVariableOrParameterOrField(
             String name, TreePath path) {
-        Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+        Log.DiagnosticHandler discardDiagnosticHandler = newDiagnosticHandler();
         try {
             Env<AttrContext> env = getEnvForPath(path);
             Element res = wrapInvocationOnResolveInstance(FIND_VAR, env, names.fromString(name));
@@ -254,7 +270,7 @@
      * @return the element for the class
      */
     public Element findClass(String name, TreePath path) {
-        Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+        Log.DiagnosticHandler discardDiagnosticHandler = newDiagnosticHandler();
         try {
             Env<AttrContext> env = getEnvForPath(path);
             return wrapInvocationOnResolveInstance(FIND_TYPE, env, names.fromString(name));
@@ -272,7 +288,7 @@
      * @return the {@code ClassSymbol} for the class if it is found, {@code null} otherwise
      */
     public @Nullable ClassSymbol findClassInPackage(String name, PackageSymbol pck, TreePath path) {
-        Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+        Log.DiagnosticHandler discardDiagnosticHandler = newDiagnosticHandler();
         try {
             Env<AttrContext> env = getEnvForPath(path);
             Element res =
@@ -308,7 +324,7 @@
             TypeMirror receiverType,
             TreePath path,
             java.util.List<TypeMirror> argumentTypes) {
-        Log.DiagnosticHandler discardDiagnosticHandler = new Log.DiscardDiagnosticHandler(log);
+        Log.DiagnosticHandler discardDiagnosticHandler = newDiagnosticHandler();
         try {
             Env<AttrContext> env = getEnvForPath(path);
 
@@ -411,4 +427,18 @@
                     e);
         }
     }
+
+
+  /**
+   * Creates a new {@code DiscardDiagnosticHandler} with the current {@code log}.
+   *
+   * @return a new {@code DiscardDiagnosticHandler} with the current {@code log}
+   */
+    private Log.DiscardDiagnosticHandler newDiagnosticHandler() {
+        try {
+            return NEW_DIAGNOSTIC_HANDLER.newInstance(log);
+        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+            throw new BugInCF(e);
+        }
+    }
 }
