From 3b5d10e2a1f4275e87f6b4fddf7910711a59e3a5 Mon Sep 17 00:00:00 2001 From: Ashley Scopes <73482956+ascopes@users.noreply.github.com> Date: Tue, 20 Oct 2026 07:56:09 +0100 Subject: [PATCH 1/3] Deprecate Java 17 support now it is at end of life. --- .github/workflows/build.yml | 29 +----- java-compiler-testing/pom.xml | 82 +++++++--------- .../ascopes/jct/compilers/JctCompiler.java | 2 +- .../compilers/impl/JavacJctCompilerImpl.java | 23 +---- .../ascopes/jct/utils/LoomPolyfill.java | 18 +--- .../src/main/java/module-info.java | 3 + .../compilers/AbstractJctCompilerTest.java | 1 - .../impl/JavacJctCompilerImplTest.java | 40 +++----- .../ascopes/jct/utils/LoomPolyfillTest.java | 26 +---- .../impl/MemoryFileSystemProviderTest.java | 2 +- pom.xml | 96 +++++++++---------- 11 files changed, 115 insertions(+), 207 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fbe83f61a..49b973026 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -23,38 +23,14 @@ jobs: uses: actions/checkout@v7 ### - ### Lint scripts and configuration files. + ### Lint configuration files. ### - #- name: Validate shell scripts - # uses: ludeeus/action-shellcheck@master - # if: ${{ ! cancelled() }} - # with: - # check_together: 'yes' - # scandir: ./scripts - - name: Validate codecov.yml shell: bash if: ${{ ! cancelled() }} run: curl -si --fail-with-body --data-binary @codecov.yml https://codecov.io/validate - ### - ### Lint GitHub Actions for issues. - ### - - - name: Lint GitHub Actions - shell: bash - if: ${{ ! cancelled() }} - run: >- - docker run - --rm - --user "$(id -u "${USER}"):$(id -g "${USER}")" - --volume "$(pwd):/repo" - --workdir /repo - rhysd/actionlint:latest - -color - -verbose - ### ### Lint Java, export information about current environment for ### the next jobs to utilise. @@ -86,14 +62,13 @@ jobs: matrix: os-name: [ubuntu-latest] java-version: - - 17 # LTS - 21 # LTS - 25 # LTS include: - os-name: windows-11-arm java-version: 23 # Latest Temurin for ARM - os-name: macos-latest - java-version: 25 # LTS + java-version: 21 steps: - name: Checkout repository diff --git a/java-compiler-testing/pom.xml b/java-compiler-testing/pom.xml index bbb5a2acd..f76d07691 100644 --- a/java-compiler-testing/pom.xml +++ b/java-compiler-testing/pom.xml @@ -22,7 +22,7 @@ io.github.ascopes.jct java-compiler-testing-parent - 6.0.2-SNAPSHOT + 7.0.0-SNAPSHOT ../pom.xml @@ -115,13 +115,47 @@ org.apache.maven.plugins maven-compiler-plugin - - + + + com.google.errorprone + error_prone_core + ${errorprone.version} + + + + com.google.guava + guava + [33,) + + + com.uber.nullaway + nullaway + ${nullaway.version} + + + + -Xlint:-module + + --should-stop=ifError=FLOW + + -Xplugin:ErrorProne + -XepDisableWarningsInGeneratedCode + -XepExcludedPaths:.*/target/generated.*?/.* + -XepOpt:NullAway:AnnotatedPackages=io.github.ascopes.jct + + -XepOpt:NullAway:ExcludedFieldAnnotations=org.junit.jupiter.*,org.mockito.* + -XepOpt:NullAway:KnownInitializers=io.github.ascopes.jct.annotations.Initializer,io.github.ascopes.jct.junit.Managed + + + -XDaddTypeAnnotationsToSymbol=true + -XDcompilePolicy=simple @@ -232,48 +266,6 @@ maven-compiler-plugin - - - com.google.errorprone - error_prone_core - ${errorprone.version} - - - - com.google.guava - guava - [33,) - - - com.uber.nullaway - nullaway - ${nullaway.version} - - - - - - -Xlint:-module - - --should-stop=ifError=FLOW - - -Xplugin:ErrorProne - -XepDisableWarningsInGeneratedCode - -XepExcludedPaths:.*/target/generated.*?/.* - -XepOpt:NullAway:AnnotatedPackages=io.github.ascopes.jct - - -XepOpt:NullAway:ExcludedFieldAnnotations=org.junit.jupiter.*,org.mockito.* - -XepOpt:NullAway:KnownInitializers=io.github.ascopes.jct.annotations.Initializer,io.github.ascopes.jct.junit.Managed - - - -XDaddTypeAnnotationsToSymbol=true - -XDcompilePolicy=simple - diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/JctCompiler.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/JctCompiler.java index 5dff4a40b..d113a6bd4 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/JctCompiler.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/JctCompiler.java @@ -632,7 +632,7 @@ default JctCompiler release(SourceVersion release) { * Request that the compiler uses a language version that corresponds to the runtime language * version in use on the current JVM. * - *

For example, running this on JRE 19 would set the release to "19". + *

For example, running this on JRE 25 would set the release to "25". * *

This calls {@link #release(int)} internally. * diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImpl.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImpl.java index 8e9cd43d9..2d40db218 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImpl.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImpl.java @@ -34,9 +34,7 @@ */ public final class JavacJctCompilerImpl extends AbstractJctCompiler { - private static final int JAVA_8 = 8; private static final int JAVA_9 = 9; - private static final int JAVA_20 = 20; private static final String NAME = "JDK Compiler"; /** @@ -60,7 +58,7 @@ public JctFlagBuilderFactory getFlagBuilderFactory() { public Jsr199CompilerFactory getCompilerFactory() { // RequireNonNull to ensure the return result is non-null, since the ToolProvider // method is not annotated. - return () -> requireNonNull(ToolProvider.getSystemJavaCompiler(), + return () -> requireNonNull(ToolProvider.getSystemJavaCompiler(), "ToolProvider.getSystemJavaCompiler()"); } @@ -76,21 +74,10 @@ public JctFileManagerFactory getFileManagerFactory() { * @since 1.0.0 */ public static int getEarliestSupportedVersionInt() { - // Purposely do not hardcode members of the SourceVersion enum here other - // than utility methods, as this prevents compilation problems on various - // versions of the JDK when certain members are unavailable. - - @SuppressWarnings("EnumOrdinal") - var latestSupported = SourceVersion.latestSupported().ordinal(); - - if (latestSupported >= JAVA_20) { - // JDK 20 marks source-version 8 as obsolete, and emits compilation - // warnings that may break tests using "fail on warnings". To avoid this, - // disallow compiling Java 8 sources under Javac in JDK 20 or newer - return JAVA_9; - } - - return JAVA_8; + // JDK 20 marks source-version 8 as obsolete, and emits compilation + // warnings that may break tests using "fail on warnings". To avoid this, + // disallow compiling Java 8 sources under Javac in JDK 20 or newer + return JAVA_9; } /** diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/utils/LoomPolyfill.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/utils/LoomPolyfill.java index 8df7b6c70..8dc17d6ce 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/utils/LoomPolyfill.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/utils/LoomPolyfill.java @@ -15,14 +15,15 @@ */ package io.github.ascopes.jct.utils; -import io.github.ascopes.jct.annotations.DeadCodeGenerated; - /** * Polyfill to enable supporting using the newer Thread APIs on newer platforms. * *

This specifically targets the new APIs introduced as part of Project Loom * in Java 19. * + *

This class is now suitable to be removed as we only target Java 21 and + * newer. + * * @author Ashley Scopes * @since 0.0.1 */ @@ -40,18 +41,9 @@ private LoomPolyfill() { * @param thread the thread to use. * @return the thread ID. */ - @DeadCodeGenerated public static long getThreadId(Thread thread) { - // Note: this test will never get 100% coverage on one JDK, because it totally depends on the - // JDK in use as to which code path runs. - try { - // Where possible, use the newer Loom API to fetch the thread ID. - var method = Thread.class.getDeclaredMethod("threadId"); - return (long) method.invoke(thread); - } catch (Exception ex) { - // Fall back to the old API (which is the only method prior to Java 19). - return thread.getId(); - } + // Now we baseline to Java 21, we don't have to use reflection to invoke this Java 19 API. + return thread.threadId(); } /** diff --git a/java-compiler-testing/src/main/java/module-info.java b/java-compiler-testing/src/main/java/module-info.java index d71767bf9..001badf19 100644 --- a/java-compiler-testing/src/main/java/module-info.java +++ b/java-compiler-testing/src/main/java/module-info.java @@ -24,6 +24,9 @@ *

For Java 11 support, please use version 4 of this library, which is still kept up to date. * Version 5 of this library only supports Java 17 onwards. * + *

For Java 17 support, please use version 6 of this library, which is still kept up to date. + * Version 7 of this library only supports Java 17 onwards. + * *

The Java Compiler Testing API has a number of facilities for assisting in testing * anything related to the Java compiler. This includes Javac plugins and JSR-199 annotation * processors. diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/AbstractJctCompilerTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/AbstractJctCompilerTest.java index 661eb2f89..8cb0a5738 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/AbstractJctCompilerTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/AbstractJctCompilerTest.java @@ -552,7 +552,6 @@ void configureInvokesConfigurerOnTheCompiler() throws Throwable { IllegalThreadStateException.class, NoClassDefFoundError.class, ClassNotFoundException.class, - ThreadDeath.class, }) @ParameterizedTest(name = "for exception of type {0}") void configurePropagatesAnyException(Class exceptionCls) throws Throwable { diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImplTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImplTest.java index fdea9f91d..9d5df5de3 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImplTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/compilers/impl/JavacJctCompilerImplTest.java @@ -130,21 +130,13 @@ void compilersHaveNoDefaultAnnotationProcessorsSet() { @DisplayName("the earliest supported version int has the expected value") @CsvSource(useHeadersInDisplayName = true, value = { "SourceVersion.latest(), expectedResult", - " 9, 8", - " 10, 8", - " 11, 8", - " 12, 8", - " 13, 8", - " 14, 8", - " 15, 8", - " 16, 8", - " 17, 8", - " 18, 8", - " 19, 8", - // JDK-20 marks Java 8 as obsolete, so we do not support it. - // We default to Java 9 regardless in this case. - " 20, 9", " 21, 9", + " 22, 9", + " 23, 9", + " 24, 9", + " 25, 9", + " 26, 9", + " 27, 9", }) @ParameterizedTest(name = "expect {1} when using Javac for JDK {0}") @SuppressWarnings({"EnumOrdinal", "ResultOfMethodCallIgnored"}) @@ -166,22 +158,16 @@ void earliestSupportedVersionReturnsTheExpectedValue(int latest, int expectedRes } } - @DisplayName("the earliest supported version int has the expected value") + @DisplayName("the latest supported version int has the expected value") @CsvSource(useHeadersInDisplayName = true, value = { "SourceVersion.latest(), expectedResult", - " 9, 9", - " 10, 10", - " 11, 11", - " 12, 12", - " 13, 13", - " 14, 14", - " 15, 15", - " 16, 16", - " 17, 17", - " 18, 18", - " 19, 19", - " 20, 20", " 21, 21", + " 22, 22", + " 23, 23", + " 24, 24", + " 25, 25", + " 26, 26", + " 27, 27", }) @ParameterizedTest(name = "expect {1} when using Javac for JDK {0}") @SuppressWarnings({"EnumOrdinal", "ResultOfMethodCallIgnored"}) diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/utils/LoomPolyfillTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/utils/LoomPolyfillTest.java index 6410d2582..8b6234e4e 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/utils/LoomPolyfillTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/utils/LoomPolyfillTest.java @@ -26,8 +26,6 @@ import io.github.ascopes.jct.fixtures.UtilityClassTestTemplate; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.EnabledForJreRange; -import org.junit.jupiter.api.condition.JRE; /** * {@link LoomPolyfill} tests. @@ -41,29 +39,9 @@ public Class getTypeBeingTested() { return LoomPolyfill.class; } - @DisplayName(".getThreadId(Thread) on JRE <= 18 calls .getId()") - @EnabledForJreRange(max = JRE.JAVA_18) + @DisplayName(".getThreadId(Thread) calls .threadId()") @Test - void getThreadIdOnJre18AndOlderUsesThreadGetId() throws Throwable { - // Given - var expectedThreadId = Fixtures.someLong(1, Short.MAX_VALUE); - var thread = mock(Thread.class); - var getIdMethod = Thread.class.getDeclaredMethod("getId"); - - when((long) getIdMethod.invoke(thread)).thenReturn(expectedThreadId); - - // When - var actualThreadId = LoomPolyfill.getThreadId(thread); - - // Then - assertThat(actualThreadId).isEqualTo(expectedThreadId); - getIdMethod.invoke(verify(thread)); - } - - @DisplayName(".getThreadId(Thread) on JRE >= 19 calls .threadId()") - @EnabledForJreRange(min = JRE.JAVA_19) - @Test - void getThreadIdOnJre19AndNewerUsesThreadId() throws Throwable { + void getThreadIdUsesThreadId() throws Throwable { // Given var expectedThreadId = Fixtures.someLong(1, Short.MAX_VALUE); var thread = mock(Thread.class); diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/workspaces/impl/MemoryFileSystemProviderTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/workspaces/impl/MemoryFileSystemProviderTest.java index dff7f2075..9ed6b1571 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/workspaces/impl/MemoryFileSystemProviderTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/workspaces/impl/MemoryFileSystemProviderTest.java @@ -227,7 +227,7 @@ void providerReturnsHandlerForMemoryProtocol(String urlString) throws MalformedU @ValueSource(strings = { "file://foo/bar/baz", "jar:file://foo/bar/baz.jar!/Bork.class", - "jrt:", + "jrt:/", }) @ParameterizedTest(name = "for URL {0}") void providerReturnsNullHandlerForOtherProtocol(String urlString) throws MalformedURLException { diff --git a/pom.xml b/pom.xml index a9aad8b18..30476e86c 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ io.github.ascopes.jct java-compiler-testing-parent - 6.0.2-SNAPSHOT + 7.0.0-SNAPSHOT pom Java Compiler Testing parent project @@ -163,7 +163,7 @@ UTF-8 - 17 + 21 27 @@ -306,6 +306,44 @@ + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${maven-checkstyle-plugin.version} + + + .mvn/checkstyle/checkstyle.xml + true + true + true + ${project.basedir}/src + .mvn/checkstyle/suppressions.xml + info + + + + + + + validate + + check + + + + + + + + com.puppycrawl.tools + checkstyle + ${checkstyle.version} + + + + org.apache.maven.plugins @@ -658,6 +696,12 @@ false + + + org.apache.maven.plugins + maven-checkstyle-plugin + + - org.apache.maven.plugins - maven-checkstyle-plugin - ${maven-checkstyle-plugin.version} - - - .mvn/checkstyle/checkstyle.xml - true - true - true - ${project.basedir}/src - .mvn/checkstyle/suppressions.xml - info - - - - - - - validate - - check - - - - - - - - com.puppycrawl.tools - checkstyle - ${checkstyle.version} - - - - - - - releases From 980dfb2984e4ee012f4b46178a15098bd06af27d Mon Sep 17 00:00:00 2001 From: Ashley Scopes <73482956+ascopes@users.noreply.github.com> Date: Tue, 20 Oct 2026 08:31:35 +0100 Subject: [PATCH 2/3] Remove codeql as it fails on Java 21 --- .github/workflows/codeql.yml | 41 ------------------------------------ 1 file changed, 41 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 7ef1c6e76..000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: CodeQL Analysis -on: - pull_request: - branches: [main] - push: - branches: [main] - workflow_call: {} - workflow_dispatch: {} - -jobs: - codeql: - name: CodeQL analysis (${{ matrix.language }}) - runs-on: ubuntu-latest - - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [java] - - steps: - - name: Checkout repository - uses: actions/checkout@v7 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v4.39.0 - with: - languages: ${{ matrix.language }} - - - name: Autobuild - uses: github/codeql-action/autobuild@v4.39.0 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4.39.0 - with: - category: "/language:${{matrix.language}}" From 4e0b291d929b2fdaefc7f42d5aa6b60c78f176d8 Mon Sep 17 00:00:00 2001 From: Ashley Scopes <73482956+ascopes@users.noreply.github.com> Date: Tue, 20 Oct 2026 08:36:30 +0100 Subject: [PATCH 3/3] Update dogfood test to Java 21 minimum target --- .../ascopes/jct/acceptancetests/dogfood/JctDogfoodTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java-compiler-testing/src/it/dogfood/src/test/java/io/github/ascopes/jct/acceptancetests/dogfood/JctDogfoodTest.java b/java-compiler-testing/src/it/dogfood/src/test/java/io/github/ascopes/jct/acceptancetests/dogfood/JctDogfoodTest.java index 674648715..4d2b21b10 100644 --- a/java-compiler-testing/src/it/dogfood/src/test/java/io/github/ascopes/jct/acceptancetests/dogfood/JctDogfoodTest.java +++ b/java-compiler-testing/src/it/dogfood/src/test/java/io/github/ascopes/jct/acceptancetests/dogfood/JctDogfoodTest.java @@ -52,7 +52,7 @@ class JctDogfoodTest { .resolve("classes"); @DisplayName("JCT can compile itself as a legacy module source") - @JavacCompilerTest(minVersion = 17, configurers = JctCompilationConfigurer.class) + @JavacCompilerTest(minVersion = 21, configurers = JctCompilationConfigurer.class) void jctCanCompileItselfAsLegacyModule(JctCompiler compiler) throws IOException { // Given try (var workspace = Workspaces.newWorkspace()) {