Skip to content

Commit

Permalink
Fix JDK 20-ea build compatibility
Browse files Browse the repository at this point in the history
With these changes the JDK 20-ea build on GitHub Actions passes again.

Fixes #3610

FUTURE_COPYBARA_INTEGRATE_REVIEW=#3610 from PicnicSupermarket:bugfix/jdk-20-enhanced-for-loop-compat 0b534d2
PiperOrigin-RevId: 498578771
  • Loading branch information
java-team-github-bot authored and Error Prone Team committed Dec 30, 2022
1 parent bcf4dcf commit d7a8bec
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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}.
Expand All @@ -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
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@
<target>11</target>
<parameters />
<compilerArgs>
<arg>--add-exports=java.base/jdk.internal.javac=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
<arg>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
Expand Down

0 comments on commit d7a8bec

Please sign in to comment.