From 330bcf094157163678be14e84656adad8da16eca Mon Sep 17 00:00:00 2001 From: Will-thom <116388885+Will-thom@users.noreply.github.com> Date: Thu, 21 May 2026 14:50:31 -0300 Subject: [PATCH] Add TestCompiler deprecation warning shortcut Closes gh-36036 Signed-off-by: Will-thom <116388885+Will-thom@users.noreply.github.com> --- .../beans/factory/aot/CodeWarningsTests.java | 2 +- .../core/test/tools/TestCompiler.java | 12 ++ .../core/test/tools/TestCompilerTests.java | 122 ++++++++++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/spring-beans/src/test/java/org/springframework/beans/factory/aot/CodeWarningsTests.java b/spring-beans/src/test/java/org/springframework/beans/factory/aot/CodeWarningsTests.java index 69d6412b43b0..d05d83e4be20 100644 --- a/spring-beans/src/test/java/org/springframework/beans/factory/aot/CodeWarningsTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/factory/aot/CodeWarningsTests.java @@ -49,7 +49,7 @@ class CodeWarningsTests { private static final TestCompiler TEST_COMPILER = TestCompiler.forSystem() - .withCompilerOptions("-Xlint:all", "-Werror"); + .failOnDeprecationWarning(); private final CodeWarnings codeWarnings = new CodeWarnings(); diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java index 6e9bcc9569b8..7a71966f3a60 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java @@ -230,6 +230,18 @@ public TestCompiler failOnWarning() { return withCompilerOptions("-Xlint:all", "-Werror"); } + /** + * Create a new {@link TestCompiler} instance that fails if a deprecation + * warning is encountered. This sets the {@code -Xlint:deprecation}, + * {@code -Xlint:removal}, and {@code -Werror} compiler options. + * @return a new {@code TestCompiler} instance + * @since 7.1 + * @see #withCompilerOptions(String...) + */ + public TestCompiler failOnDeprecationWarning() { + return withCompilerOptions("-Xlint:deprecation", "-Xlint:removal", "-Werror"); + } + /** * Compile content from this instance along with the additional provided * content. diff --git a/spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java b/spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java index 97eb09623b2e..e91cee07ea69 100644 --- a/spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java +++ b/spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java @@ -109,6 +109,21 @@ public String get() { } """; + private static final String HELLO_DEPRECATED_FOR_REMOVAL = """ + package com.example; + + import java.util.function.Supplier; + + public class Hello implements Supplier { + + @Deprecated(forRemoval = true) + public String get() { + return "Hello Deprecated"; + } + + } + """; + @Test @SuppressWarnings("unchecked") void compileWhenHasDifferentClassesWithSameClassNameCompilesBoth() { @@ -212,6 +227,101 @@ public static void main(String[] args) { }); } + @Test + void compileWhenSourceUseDeprecateCodeAndFailOnDeprecationWarningIsSet() { + SourceFile main = sourceFileUsingDeprecatedHello(""" + public static void main(String[] args) { + new Hello().get(); + } + """); + assertThatExceptionOfType(CompilationException.class).isThrownBy( + () -> TestCompiler.forSystem().failOnDeprecationWarning().withSources( + SourceFile.of(HELLO_DEPRECATED), main).compile(compiled -> { + })).satisfies(compilationException -> { + assertThat(compilationException.getProblems(Diagnostic.Kind.ERROR)).singleElement() + .satisfies(error -> assertThat(error.message()) + .contains("-Werror")); + assertThat(compilationException.getProblems(Diagnostic.Kind.MANDATORY_WARNING)).singleElement() + .satisfies(warning -> assertThat(warning.message()) + .contains("get()", "com.example.Hello")); + }); + } + + @Test + @SuppressWarnings("unchecked") + void compileWhenSourceUseDeprecateCodeAndFailOnDeprecationWarningWithSuppressWarnings() { + SourceFile main = sourceFileUsingDeprecatedHello(""" + @SuppressWarnings("deprecation") + public static void main(String[] args) { + new Hello().get(); + } + """); + TestCompiler.forSystem().failOnDeprecationWarning().withSources( + SourceFile.of(HELLO_DEPRECATED), main).compile(compiled -> { + Supplier supplier = compiled.getInstance(Supplier.class, + "com.example.Hello"); + assertThat(supplier.get()).isEqualTo("Hello Deprecated"); + }); + } + + @Test + void compileWhenSourceExposesDeprecateTypeAndFailOnDeprecationWarningIsSet() { + SourceFile main = sourceFileUsingDeprecatedHello(""" + public Hello getHello() { + return new Hello(); + } + """); + assertThatExceptionOfType(CompilationException.class).isThrownBy( + () -> TestCompiler.forSystem().failOnDeprecationWarning().withSources( + SourceFile.of(HELLO_WORLD), main).compile(compiled -> { + })).satisfies(compilationException -> { + assertThat(compilationException.getProblems(Diagnostic.Kind.ERROR)).singleElement() + .satisfies(error -> assertThat(error.message()) + .contains("-Werror")); + assertThat(compilationException.getProblems(Diagnostic.Kind.MANDATORY_WARNING)) + .hasSize(2) + .allSatisfy(warning -> assertThat(warning.message()) + .contains("Hello", "com.example")); + }); + } + + @Test + void compileWhenSourceUseDeprecateForRemovalCodeAndFailOnDeprecationWarningIsSet() { + SourceFile main = sourceFileUsingDeprecatedHello(""" + public static void main(String[] args) { + new Hello().get(); + } + """); + assertThatExceptionOfType(CompilationException.class).isThrownBy( + () -> TestCompiler.forSystem().failOnDeprecationWarning().withSources( + SourceFile.of(HELLO_DEPRECATED_FOR_REMOVAL), main).compile(compiled -> { + })).satisfies(compilationException -> { + assertThat(compilationException.getProblems(Diagnostic.Kind.ERROR)).singleElement() + .satisfies(error -> assertThat(error.message()) + .contains("-Werror")); + assertThat(compilationException.getProblems(Diagnostic.Kind.MANDATORY_WARNING)).singleElement() + .satisfies(warning -> assertThat(warning.message()) + .contains("get()", "com.example.Hello")); + }); + } + + @Test + @SuppressWarnings({ "removal", "unchecked" }) + void compileWhenSourceUseDeprecateForRemovalCodeAndFailOnDeprecationWarningWithSuppressWarnings() { + SourceFile main = sourceFileUsingDeprecatedHello(""" + @SuppressWarnings("removal") + public static void main(String[] args) { + new Hello().get(); + } + """); + TestCompiler.forSystem().failOnDeprecationWarning().withSources( + SourceFile.of(HELLO_DEPRECATED_FOR_REMOVAL), main).compile(compiled -> { + Supplier supplier = compiled.getInstance(Supplier.class, + "com.example.Hello"); + assertThat(supplier.get()).isEqualTo("Hello Deprecated"); + }); + } + @Test void withSourcesArrayAddsSource() { SourceFile sourceFile = SourceFile.of(HELLO_WORLD); @@ -398,6 +508,18 @@ private void assertHasResource(Compiled compiled) { "META-INF/myfile")).hasContent("test"); } + private SourceFile sourceFileUsingDeprecatedHello(String method) { + return SourceFile.of(""" + package com.example; + + public class Main { + + %s + + } + """.formatted(method.indent(1))); + } + @SupportedAnnotationTypes("java.lang.Deprecated") static class TestProcessor extends AbstractProcessor {