Browse Source

Detect use of deprecated API

This commit is a best effort attempt at identifying the members that
code generation invokes and might be deprecated. It introduces
a CodeWarnings helper class that records warnings, with special
handling for `@Deprecated`.

See gh-29597
pull/31407/head
Stéphane Nicoll 1 year ago
parent
commit
ea66883d79
  1. 3
      spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java
  2. 125
      spring-beans/src/main/java/org/springframework/beans/factory/aot/CodeWarnings.java
  3. 13
      spring-beans/src/main/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGenerator.java
  4. 35
      spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java
  5. 123
      spring-beans/src/test/java/org/springframework/beans/factory/aot/CodeWarningsTests.java
  6. 120
      spring-beans/src/test/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGeneratorTests.java
  7. 27
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedBean.java
  8. 34
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedConstructor.java
  9. 27
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedForRemovalBean.java
  10. 34
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedForRemovalConstructor.java
  11. 36
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedForRemovalMemberConfiguration.java
  12. 40
      spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedMemberConfiguration.java

3
spring-beans/src/main/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGenerator.java

@ -164,11 +164,14 @@ class BeanDefinitionMethodGenerator { @@ -164,11 +164,14 @@ class BeanDefinitionMethodGenerator {
this.aotContributions.forEach(aotContribution -> aotContribution.applyTo(generationContext, codeGenerator));
CodeWarnings codeWarnings = new CodeWarnings();
codeWarnings.detectDeprecation(this.registeredBean.getBeanClass());
return generatedMethods.add("getBeanDefinition", method -> {
method.addJavadoc("Get the $L definition for '$L'.",
(this.registeredBean.isInnerBean() ? "inner-bean" : "bean"),
getName());
method.addModifiers(modifier, Modifier.STATIC);
codeWarnings.suppress(method);
method.returns(BeanDefinition.class);
method.addCode(codeGenerator.generateCode(generationContext));
});

125
spring-beans/src/main/java/org/springframework/beans/factory/aot/CodeWarnings.java

@ -0,0 +1,125 @@ @@ -0,0 +1,125 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aot;
import java.lang.reflect.AnnotatedElement;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Stream;
import org.springframework.javapoet.AnnotationSpec;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.MethodSpec;
import org.springframework.lang.Nullable;
/**
* Helper class to register warnings that the compiler may trigger on
* generated code.
*
* @author Stephane Nicoll
* @see SuppressWarnings
*/
class CodeWarnings {
private final Set<String> warnings = new LinkedHashSet<>();
/**
* Register a warning to be included for this block. Does nothing if
* the warning is already registered.
* @param warning the warning to register, if it hasn't been already
*/
public void register(String warning) {
this.warnings.add(warning);
}
/**
* Detect the presence of {@link Deprecated} on the specified elements.
* @param elements the elements to check
* @return {@code this} instance
*/
public CodeWarnings detectDeprecation(AnnotatedElement... elements) {
for (AnnotatedElement element : elements) {
register(element.getAnnotation(Deprecated.class));
}
return this;
}
/**
* Detect the presence of {@link Deprecated} on the specified elements.
* @param elements the elements to check
* @return {@code this} instance
*/
public CodeWarnings detectDeprecation(Stream<AnnotatedElement> elements) {
elements.forEach(element -> register(element.getAnnotation(Deprecated.class)));
return this;
}
/**
* Include a {@link SuppressWarnings} on the specified method if necessary.
* @param method the method to update
*/
public void suppress(MethodSpec.Builder method) {
if (this.warnings.isEmpty()) {
return;
}
method.addAnnotation(buildAnnotationSpec());
}
/**
* Return the currently registered warnings.
* @return the warnings
*/
protected Set<String> getWarnings() {
return Collections.unmodifiableSet(this.warnings);
}
private void register(@Nullable Deprecated annotation) {
if (annotation != null) {
if (annotation.forRemoval()) {
register("removal");
}
else {
register("deprecation");
}
}
}
private AnnotationSpec buildAnnotationSpec() {
return AnnotationSpec.builder(SuppressWarnings.class)
.addMember("value", generateValueCode()).build();
}
private CodeBlock generateValueCode() {
if (this.warnings.size() == 1) {
return CodeBlock.of("$S", this.warnings.iterator().next());
}
CodeBlock values = CodeBlock.join(this.warnings.stream()
.map(warning -> CodeBlock.of("$S", warning)).toList(), ", ");
return CodeBlock.of("{ $L }", values);
}
@Override
public String toString() {
return new StringJoiner(", ", CodeWarnings.class.getSimpleName(), "")
.add(this.warnings.toString())
.toString();
}
}

13
spring-beans/src/main/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGenerator.java

@ -21,6 +21,7 @@ import java.lang.reflect.Executable; @@ -21,6 +21,7 @@ import java.lang.reflect.Executable;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.function.Consumer;
@ -189,11 +190,15 @@ public class InstanceSupplierCodeGenerator { @@ -189,11 +190,15 @@ public class InstanceSupplierCodeGenerator {
private CodeBlock generateCodeForInaccessibleConstructor(String beanName, Class<?> beanClass,
Constructor<?> constructor, boolean dependsOnBean, Consumer<ReflectionHints> hints) {
CodeWarnings codeWarnings = new CodeWarnings();
codeWarnings.detectDeprecation(beanClass, constructor)
.detectDeprecation(Arrays.stream(constructor.getParameters()).map(Parameter::getType));
hints.accept(this.generationContext.getRuntimeHints().reflection());
GeneratedMethod generatedMethod = generateGetInstanceSupplierMethod(method -> {
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(PRIVATE_STATIC);
codeWarnings.suppress(method);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
int parameterOffset = (!dependsOnBean) ? 0 : 1;
method.addStatement(generateResolverForConstructor(beanClass, constructor, parameterOffset));
@ -206,8 +211,12 @@ public class InstanceSupplierCodeGenerator { @@ -206,8 +211,12 @@ public class InstanceSupplierCodeGenerator {
String beanName, Class<?> beanClass, Constructor<?> constructor, Class<?> declaringClass,
boolean dependsOnBean, javax.lang.model.element.Modifier... modifiers) {
CodeWarnings codeWarnings = new CodeWarnings();
codeWarnings.detectDeprecation(beanClass, constructor, declaringClass)
.detectDeprecation(Arrays.stream(constructor.getParameters()).map(Parameter::getType));
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(modifiers);
codeWarnings.suppress(method);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, beanClass));
int parameterOffset = (!dependsOnBean) ? 0 : 1;
@ -300,9 +309,13 @@ public class InstanceSupplierCodeGenerator { @@ -300,9 +309,13 @@ public class InstanceSupplierCodeGenerator {
String factoryMethodName = factoryMethod.getName();
Class<?> suppliedType = ClassUtils.resolvePrimitiveIfNecessary(factoryMethod.getReturnType());
CodeWarnings codeWarnings = new CodeWarnings();
codeWarnings.detectDeprecation(declaringClass, factoryMethod, suppliedType)
.detectDeprecation(Arrays.stream(factoryMethod.getParameters()).map(Parameter::getType));
method.addJavadoc("Get the bean instance supplier for '$L'.", beanName);
method.addModifiers(modifiers);
codeWarnings.suppress(method);
method.returns(ParameterizedTypeName.get(BeanInstanceSupplier.class, suppliedType));
CodeBlock.Builder code = CodeBlock.builder();

35
spring-beans/src/test/java/org/springframework/beans/factory/aot/BeanDefinitionMethodGeneratorTests.java

@ -26,6 +26,7 @@ import java.util.function.Supplier; @@ -26,6 +26,7 @@ import java.util.function.Supplier;
import javax.lang.model.element.Modifier;
import javax.xml.parsers.DocumentBuilderFactory;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.aot.generate.GeneratedMethod;
@ -52,6 +53,7 @@ import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy; @@ -52,6 +53,7 @@ import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy;
import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy.Implementation;
import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy.One;
import org.springframework.beans.testfixture.beans.factory.aot.TestHierarchy.Two;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedBean;
import org.springframework.core.ResolvableType;
import org.springframework.core.test.io.support.MockSpringFactoriesLoader;
import org.springframework.core.test.tools.CompileWithForkedClassLoader;
@ -66,6 +68,7 @@ import org.springframework.util.ReflectionUtils; @@ -66,6 +68,7 @@ import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.assertj.core.api.Assertions.assertThatNoException;
/**
* Tests for {@link BeanDefinitionMethodGenerator} and
@ -740,6 +743,32 @@ class BeanDefinitionMethodGeneratorTests { @@ -740,6 +743,32 @@ class BeanDefinitionMethodGeneratorTests {
});
}
@Nested
@SuppressWarnings("deprecation")
class DeprecationTests {
private static final TestCompiler TEST_COMPILER = TestCompiler.forSystem()
.withCompilerOptions("-Xlint:all", "-Xlint:-rawtypes", "-Werror");
@Test
void generateBeanDefinitionMethodWithDeprecatedTargetClass() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(DeprecatedBean.class);
RegisteredBean registeredBean = registerBean(beanDefinition);
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
methodGeneratorFactory, registeredBean, null,
Collections.emptyList());
MethodReference method = generator.generateBeanDefinitionMethod(
generationContext, beanRegistrationsCode);
compileAndCheckWarnings(method);
}
private void compileAndCheckWarnings(MethodReference methodReference) {
assertThatNoException().isThrownBy(() -> compile(TEST_COMPILER, methodReference,
((instanceSupplier, compiled) -> {})));
}
}
private void testBeanDefinitionMethodInCurrentFile(Class<?> targetType, RootBeanDefinition beanDefinition) {
RegisteredBean registeredBean = registerBean(new RootBeanDefinition(beanDefinition));
BeanDefinitionMethodGenerator generator = new BeanDefinitionMethodGenerator(
@ -764,6 +793,10 @@ class BeanDefinitionMethodGeneratorTests { @@ -764,6 +793,10 @@ class BeanDefinitionMethodGeneratorTests {
}
private void compile(MethodReference method, BiConsumer<RootBeanDefinition, Compiled> result) {
compile(TestCompiler.forSystem(), method, result);
}
private void compile(TestCompiler testCompiler, MethodReference method, BiConsumer<RootBeanDefinition, Compiled> result) {
this.beanRegistrationsCode.getTypeBuilder().set(type -> {
CodeBlock methodInvocation = method.toInvokeCodeBlock(ArgumentCodeGenerator.none(),
this.beanRegistrationsCode.getClassName());
@ -775,7 +808,7 @@ class BeanDefinitionMethodGeneratorTests { @@ -775,7 +808,7 @@ class BeanDefinitionMethodGeneratorTests {
.addCode("return $L;", methodInvocation).build());
});
this.generationContext.writeGeneratedContent();
TestCompiler.forSystem().with(this.generationContext).compile(compiled ->
testCompiler.with(this.generationContext).compile(compiled ->
result.accept((RootBeanDefinition) compiled.getInstance(Supplier.class).get(), compiled));
}

123
spring-beans/src/test/java/org/springframework/beans/factory/aot/CodeWarningsTests.java

@ -0,0 +1,123 @@ @@ -0,0 +1,123 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.factory.aot;
import java.util.function.Consumer;
import javax.lang.model.element.Modifier;
import org.junit.jupiter.api.Test;
import org.springframework.aot.test.generate.TestGenerationContext;
import org.springframework.beans.testfixture.beans.factory.aot.DeferredTypeBuilder;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedBean;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedForRemovalBean;
import org.springframework.core.test.tools.Compiled;
import org.springframework.core.test.tools.TestCompiler;
import org.springframework.javapoet.MethodSpec;
import org.springframework.javapoet.MethodSpec.Builder;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CodeWarnings}.
*
* @author Stephane Nicoll
*/
class CodeWarningsTests {
private static final TestCompiler TEST_COMPILER = TestCompiler.forSystem()
.withCompilerOptions("-Xlint:all", "-Werror");
private final CodeWarnings codeWarnings;
private final TestGenerationContext generationContext;
CodeWarningsTests() {
this.codeWarnings = new CodeWarnings();
this.generationContext = new TestGenerationContext();
}
@Test
void registerNoWarningDoesNotIncludeAnnotation() {
compile(method -> {
this.codeWarnings.suppress(method);
method.addStatement("$T bean = $S", String.class, "Hello");
}, compiled -> assertThat(compiled.getSourceFile()).doesNotContain("@SuppressWarnings"));
}
@Test
@SuppressWarnings("deprecation")
void registerWarningSuppressesIt() {
this.codeWarnings.register("deprecation");
compile(method -> {
this.codeWarnings.suppress(method);
method.addStatement("$T bean = new $T()", DeprecatedBean.class, DeprecatedBean.class);
}, compiled -> assertThat(compiled.getSourceFile())
.contains("@SuppressWarnings(\"deprecation\")"));
}
@Test
@SuppressWarnings({ "deprecation", "removal" })
void registerSeveralWarningsSuppressesThem() {
this.codeWarnings.register("deprecation");
this.codeWarnings.register("removal");
compile(method -> {
this.codeWarnings.suppress(method);
method.addStatement("$T bean = new $T()", DeprecatedBean.class, DeprecatedBean.class);
method.addStatement("$T another = new $T()", DeprecatedForRemovalBean.class, DeprecatedForRemovalBean.class);
}, compiled -> assertThat(compiled.getSourceFile())
.contains("@SuppressWarnings({ \"deprecation\", \"removal\" })"));
}
@Test
@SuppressWarnings("deprecation")
void detectDeprecationOnAnnotatedElementWithDeprecated() {
this.codeWarnings.detectDeprecation(DeprecatedBean.class);
assertThat(this.codeWarnings.getWarnings()).containsExactly("deprecation");
}
@Test
@SuppressWarnings("removal")
void detectDeprecationOnAnnotatedElementWithDeprecatedForRemoval() {
this.codeWarnings.detectDeprecation(DeprecatedForRemovalBean.class);
assertThat(this.codeWarnings.getWarnings()).containsExactly("removal");
}
@Test
void toStringIncludeWarnings() {
this.codeWarnings.register("deprecation");
this.codeWarnings.register("rawtypes");
assertThat(this.codeWarnings).hasToString("CodeWarnings[deprecation, rawtypes]");
}
private void compile(Consumer<Builder> method,
Consumer<Compiled> result) {
DeferredTypeBuilder typeBuilder = new DeferredTypeBuilder();
this.generationContext.getGeneratedClasses().addForFeature("TestCode", typeBuilder);
typeBuilder.set(type -> {
type.addModifiers(Modifier.PUBLIC);
Builder methodBuilder = MethodSpec.methodBuilder("apply")
.addModifiers(Modifier.PUBLIC);
method.accept(methodBuilder);
type.addMethod(methodBuilder.build());
});
this.generationContext.writeGeneratedContent();
TEST_COMPILER.with(this.generationContext).compile(result);
}
}

120
spring-beans/src/test/java/org/springframework/beans/factory/aot/InstanceSupplierCodeGeneratorTests.java

@ -23,6 +23,8 @@ import java.util.function.Supplier; @@ -23,6 +23,8 @@ import java.util.function.Supplier;
import javax.lang.model.element.Modifier;
import org.assertj.core.api.ThrowingConsumer;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.aot.generate.GeneratedClass;
@ -44,6 +46,12 @@ import org.springframework.beans.testfixture.beans.factory.generator.InnerCompon @@ -44,6 +46,12 @@ import org.springframework.beans.testfixture.beans.factory.generator.InnerCompon
import org.springframework.beans.testfixture.beans.factory.generator.InnerComponentConfiguration.EnvironmentAwareComponent;
import org.springframework.beans.testfixture.beans.factory.generator.InnerComponentConfiguration.NoDependencyComponent;
import org.springframework.beans.testfixture.beans.factory.generator.SimpleConfiguration;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedBean;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedConstructor;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedForRemovalBean;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedForRemovalConstructor;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedForRemovalMemberConfiguration;
import org.springframework.beans.testfixture.beans.factory.generator.deprecation.DeprecatedMemberConfiguration;
import org.springframework.beans.testfixture.beans.factory.generator.factory.NumberHolder;
import org.springframework.beans.testfixture.beans.factory.generator.factory.NumberHolderFactoryBean;
import org.springframework.beans.testfixture.beans.factory.generator.factory.SampleFactory;
@ -57,6 +65,7 @@ import org.springframework.javapoet.ParameterizedTypeName; @@ -57,6 +65,7 @@ import org.springframework.javapoet.ParameterizedTypeName;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
/**
* Tests for {@link InstanceSupplierCodeGenerator}.
@ -261,6 +270,108 @@ class InstanceSupplierCodeGeneratorTests { @@ -261,6 +270,108 @@ class InstanceSupplierCodeGeneratorTests {
.satisfies(hasMethodWithMode(ExecutableMode.INTROSPECT));
}
@Nested
@SuppressWarnings("deprecation")
class DeprecationTests {
private static final TestCompiler TEST_COMPILER = TestCompiler.forSystem()
.withCompilerOptions("-Xlint:all", "-Xlint:-rawtypes", "-Werror");
@Test
@Disabled("Need to move to a separate method so that the warning can be suppressed")
void generateWhenTargetClassIsDeprecated() {
compileAndCheckWarnings(new RootBeanDefinition(DeprecatedBean.class));
}
@Test
void generateWhenTargetConstructorIsDeprecated() {
compileAndCheckWarnings(new RootBeanDefinition(DeprecatedConstructor.class));
}
@Test
void generateWhenTargetFactoryMethodIsDeprecated() {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(String.class)
.setFactoryMethodOnBean("deprecatedString", "config").getBeanDefinition();
beanFactory.registerBeanDefinition("config", BeanDefinitionBuilder
.genericBeanDefinition(DeprecatedMemberConfiguration.class).getBeanDefinition());
compileAndCheckWarnings(beanDefinition);
}
@Test
void generateWhenTargetFactoryMethodParameterIsDeprecated() {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(String.class)
.setFactoryMethodOnBean("deprecatedParameter", "config").getBeanDefinition();
beanFactory.registerBeanDefinition("config", BeanDefinitionBuilder
.genericBeanDefinition(DeprecatedMemberConfiguration.class).getBeanDefinition());
beanFactory.registerBeanDefinition("parameter", new RootBeanDefinition(DeprecatedBean.class));
compileAndCheckWarnings(beanDefinition);
}
@Test
void generateWhenTargetFactoryMethodReturnTypeIsDeprecated() {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(DeprecatedBean.class)
.setFactoryMethodOnBean("deprecatedReturnType", "config").getBeanDefinition();
beanFactory.registerBeanDefinition("config", BeanDefinitionBuilder
.genericBeanDefinition(DeprecatedMemberConfiguration.class).getBeanDefinition());
compileAndCheckWarnings(beanDefinition);
}
private void compileAndCheckWarnings(BeanDefinition beanDefinition) {
assertThatNoException().isThrownBy(() -> compile(TEST_COMPILER, beanDefinition,
((instanceSupplier, compiled) -> {})));
}
}
@Nested
@SuppressWarnings("removal")
class DeprecationForRemovalTests {
private static final TestCompiler TEST_COMPILER = TestCompiler.forSystem()
.withCompilerOptions("-Xlint:all", "-Xlint:-rawtypes", "-Werror");
@Test
@Disabled("Need to move to a separate method so that the warning can be suppressed")
void generateWhenTargetClassIsDeprecatedForRemoval() {
compileAndCheckWarnings(new RootBeanDefinition(DeprecatedForRemovalBean.class));
}
@Test
void generateWhenTargetConstructorIsDeprecatedForRemoval() {
compileAndCheckWarnings(new RootBeanDefinition(DeprecatedForRemovalConstructor.class));
}
@Test
void generateWhenTargetFactoryMethodIsDeprecatedForRemoval() {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(String.class)
.setFactoryMethodOnBean("deprecatedString", "config").getBeanDefinition();
beanFactory.registerBeanDefinition("config", BeanDefinitionBuilder
.genericBeanDefinition(DeprecatedForRemovalMemberConfiguration.class).getBeanDefinition());
compileAndCheckWarnings(beanDefinition);
}
@Test
void generateWhenTargetFactoryMethodParameterIsDeprecatedForRemoval() {
BeanDefinition beanDefinition = BeanDefinitionBuilder
.rootBeanDefinition(String.class)
.setFactoryMethodOnBean("deprecatedParameter", "config").getBeanDefinition();
beanFactory.registerBeanDefinition("config", BeanDefinitionBuilder
.genericBeanDefinition(DeprecatedForRemovalMemberConfiguration.class).getBeanDefinition());
beanFactory.registerBeanDefinition("parameter", new RootBeanDefinition(DeprecatedForRemovalBean.class));
compileAndCheckWarnings(beanDefinition);
}
private void compileAndCheckWarnings(BeanDefinition beanDefinition) {
assertThatNoException().isThrownBy(() -> compile(TEST_COMPILER, beanDefinition,
((instanceSupplier, compiled) -> {})));
}
}
private ReflectionHints getReflectionHints() {
return this.generationContext.getRuntimeHints().reflection();
}
@ -285,6 +396,11 @@ class InstanceSupplierCodeGeneratorTests { @@ -285,6 +396,11 @@ class InstanceSupplierCodeGeneratorTests {
}
private void compile(BeanDefinition beanDefinition, BiConsumer<InstanceSupplier<?>, Compiled> result) {
compile(TestCompiler.forSystem(), beanDefinition, result);
}
private void compile(TestCompiler testCompiler, BeanDefinition beanDefinition,
BiConsumer<InstanceSupplier<?>, Compiled> result) {
DefaultListableBeanFactory freshBeanFactory = new DefaultListableBeanFactory(this.beanFactory);
freshBeanFactory.registerBeanDefinition("testBean", beanDefinition);
@ -306,8 +422,8 @@ class InstanceSupplierCodeGeneratorTests { @@ -306,8 +422,8 @@ class InstanceSupplierCodeGeneratorTests {
.addStatement("return $L", generatedCode).build());
});
this.generationContext.writeGeneratedContent();
TestCompiler.forSystem().with(this.generationContext).compile(compiled ->
result.accept((InstanceSupplier<?>) compiled.getInstance(Supplier.class).get(), compiled));
testCompiler.with(this.generationContext).compile(compiled -> result.accept(
(InstanceSupplier<?>) compiled.getInstance(Supplier.class).get(), compiled));
}
}

27
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedBean.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans.factory.generator.deprecation;
/**
* A sample bean that's fully deprecated.
*
* @author Stephane Nicoll
*/
@Deprecated
public class DeprecatedBean {
}

34
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedConstructor.java

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans.factory.generator.deprecation;
import org.springframework.core.env.Environment;
/**
* A sample whose factory method (constructor) is deprecated.
*
* @author Stephane Nicoll
*/
public class DeprecatedConstructor {
@Deprecated
public DeprecatedConstructor(Environment environment) {
}
}

27
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedForRemovalBean.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans.factory.generator.deprecation;
/**
* A sample bean that's fully deprecated for removal.
*
* @author Stephane Nicoll
*/
@Deprecated(forRemoval = true)
public class DeprecatedForRemovalBean {
}

34
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedForRemovalConstructor.java

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans.factory.generator.deprecation;
import org.springframework.core.env.Environment;
/**
* A sample whose factory method (constructor) is deprecated for removal
*
* @author Stephane Nicoll
*/
public class DeprecatedForRemovalConstructor {
@Deprecated(forRemoval = true)
public DeprecatedForRemovalConstructor(Environment environment) {
}
}

36
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedForRemovalMemberConfiguration.java

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans.factory.generator.deprecation;
/**
* A class with deprecated members for removal to test various use cases.
*
* @author Stephane Nicoll
*/
public class DeprecatedForRemovalMemberConfiguration {
@Deprecated(forRemoval = true)
public String deprecatedString() {
return "deprecated";
}
public String deprecatedParameter(DeprecatedForRemovalBean bean) {
return bean.toString();
}
}

40
spring-beans/src/testFixtures/java/org/springframework/beans/testfixture/beans/factory/generator/deprecation/DeprecatedMemberConfiguration.java

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
/*
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.beans.testfixture.beans.factory.generator.deprecation;
/**
* A class with deprecated members to test various use cases.
*
* @author Stephane Nicoll
*/
public class DeprecatedMemberConfiguration {
@Deprecated
public String deprecatedString() {
return "deprecated";
}
public String deprecatedParameter(DeprecatedBean bean) {
return bean.toString();
}
public DeprecatedBean deprecatedReturnType() {
return new DeprecatedBean();
}
}
Loading…
Cancel
Save