From 145138b7bcff1a52224ec93370ca888a6cb8af41 Mon Sep 17 00:00:00 2001 From: Stephan Schroevers Date: Fri, 30 Dec 2022 17:03:04 -0800 Subject: [PATCH] Fix JDK 20-ea build compatibility With these changes the JDK 20-ea build on GitHub Actions passes again. Fixes #3610 COPYBARA_INTEGRATE_REVIEW=https://github.com/google/error-prone/pull/3610 from PicnicSupermarket:bugfix/jdk-20-enhanced-for-loop-compat 0b534d2e76ff377499348fea3b33666a9987a291 PiperOrigin-RevId: 498646555 --- .../errorprone/refaster/UEnhancedForLoop.java | 60 ++++++++++++++++++- pom.xml | 1 + 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/google/errorprone/refaster/UEnhancedForLoop.java b/core/src/main/java/com/google/errorprone/refaster/UEnhancedForLoop.java index 6993f0c5b24..803a322dda6 100644 --- a/core/src/main/java/com/google/errorprone/refaster/UEnhancedForLoop.java +++ b/core/src/main/java/com/google/errorprone/refaster/UEnhancedForLoop.java @@ -19,6 +19,7 @@ import static com.google.errorprone.refaster.Unifier.unifications; import com.google.auto.value.AutoValue; +import com.google.common.base.VerifyException; import com.google.errorprone.util.RuntimeVersion; import com.sun.source.tree.EnhancedForLoopTree; import com.sun.source.tree.Tree; @@ -29,6 +30,7 @@ import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeMaker; +import java.util.Arrays; /** * A {@link UTree} representation of a {@link EnhancedForLoopTree}. @@ -39,7 +41,63 @@ abstract class UEnhancedForLoop extends USimpleStatement implements EnhancedForLoopTree { public static UEnhancedForLoop create( UVariableDecl variable, UExpression elements, UStatement statement) { - return new AutoValue_UEnhancedForLoop(variable, elements, (USimpleStatement) statement); + // On JDK 20 and above the `EnhancedForLoopTree` interface contains a additional method + // `getDeclarationKind()`, referencing a type not available prior to JDK 20. AutoValue + // generates a corresponding field and accessor for this property. Here we find and invoke the + // generated constructor with the appropriate arguments, depending on context. + // See https://github.com/openjdk/jdk20/commit/2cb64a75578ccc15a1dfc8c2843aa11d05ca8aa7. + // TODO: Simplify this logic once JDK 19 and older are no longer supported. + return isCompiledWithJdk20Plus() + ? createJdk20PlusEnhancedForLoop(variable, elements, statement) + : createPreJdk20EnhancedForLoop(variable, elements, statement); + } + + private static boolean isCompiledWithJdk20Plus() { + return Arrays.stream(AutoValue_UEnhancedForLoop.class.getDeclaredMethods()) + .anyMatch(m -> "getDeclarationKind".equals(m.getName())); + } + + private static UEnhancedForLoop createPreJdk20EnhancedForLoop( + UVariableDecl variable, UExpression elements, UStatement statement) { + try { + return AutoValue_UEnhancedForLoop.class + .getDeclaredConstructor(UVariableDecl.class, UExpression.class, USimpleStatement.class) + .newInstance(variable, elements, statement); + } catch (ReflectiveOperationException e) { + throw new LinkageError(e.getMessage(), e); + } + } + + private static UEnhancedForLoop createJdk20PlusEnhancedForLoop( + UVariableDecl variable, UExpression elements, UStatement statement) { + Object declarationKind = getVariableDeclarationKind(); + try { + return AutoValue_UEnhancedForLoop.class + .getDeclaredConstructor( + declarationKind.getClass(), + UVariableDecl.class, + UExpression.class, + USimpleStatement.class) + .newInstance(declarationKind, variable, elements, statement); + } catch (ReflectiveOperationException e) { + throw new LinkageError(e.getMessage(), e); + } + } + + private static Object getVariableDeclarationKind() { + Class declarationKind; + try { + declarationKind = Class.forName("com.sun.source.tree.EnhancedForLoopTree$DeclarationKind"); + } catch (ClassNotFoundException e) { + throw new VerifyException("Cannot load `EnhancedForLoopTree.DeclarationKind` enum", e); + } + return Arrays.stream(declarationKind.getEnumConstants()) + .filter(v -> "VARIABLE".equals(v.toString())) + .findFirst() + .orElseThrow( + () -> + new VerifyException( + "Enum value `EnhancedForLoopTree.DeclarationKind.VARIABLE` not found")); } @Override diff --git a/pom.xml b/pom.xml index d9f2d78b615..515f8b7edb6 100644 --- a/pom.xml +++ b/pom.xml @@ -159,6 +159,7 @@ 11 + --add-exports=java.base/jdk.internal.javac=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED