Merge branch 'gh-29207'
Closes gh-29207
This commit is contained in:
@@ -37,6 +37,7 @@ import org.springframework.beans.factory.support.InstanceSupplier;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
@@ -108,8 +109,8 @@ class ScopedProxyBeanRegistrationAotProcessor implements BeanRegistrationAotProc
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getTarget(RegisteredBean registeredBean, Executable constructorOrFactoryMethod) {
|
||||
return this.targetBeanDefinition.getResolvableType().toClass();
|
||||
public ClassName getTarget(RegisteredBean registeredBean, Executable constructorOrFactoryMethod) {
|
||||
return ClassName.get(this.targetBeanDefinition.getResolvableType().toClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -94,9 +94,9 @@ class BeanDefinitionMethodGenerator {
|
||||
registerRuntimeHintsIfNecessary(generationContext.getRuntimeHints());
|
||||
BeanRegistrationCodeFragments codeFragments = getCodeFragments(generationContext,
|
||||
beanRegistrationsCode);
|
||||
Class<?> target = codeFragments.getTarget(this.registeredBean,
|
||||
ClassName target = codeFragments.getTarget(this.registeredBean,
|
||||
this.constructorOrFactoryMethod);
|
||||
if (!target.getName().startsWith("java.")) {
|
||||
if (!target.canonicalName().startsWith("java.")) {
|
||||
GeneratedClass generatedClass = generationContext.getGeneratedClasses()
|
||||
.getOrAddForFeatureComponent("BeanDefinitions", target, type -> {
|
||||
type.addJavadoc("Bean definitions for {@link $T}", target);
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.beans.factory.support.InstanceSupplier;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
|
||||
/**
|
||||
@@ -52,9 +53,9 @@ public interface BeanRegistrationCodeFragments {
|
||||
* the code.
|
||||
* @param registeredBean the registered bean
|
||||
* @param constructorOrFactoryMethod the constructor or factory method
|
||||
* @return the target class
|
||||
* @return the target {@link ClassName}
|
||||
*/
|
||||
Class<?> getTarget(RegisteredBean registeredBean,
|
||||
ClassName getTarget(RegisteredBean registeredBean,
|
||||
Executable constructorOrFactoryMethod);
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -51,7 +52,7 @@ public class BeanRegistrationCodeFragmentsDecorator implements BeanRegistrationC
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getTarget(RegisteredBean registeredBean,
|
||||
public ClassName getTarget(RegisteredBean registeredBean,
|
||||
Executable constructorOrFactoryMethod) {
|
||||
|
||||
return this.delegate.getTarget(registeredBean, constructorOrFactoryMethod);
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.support.InstanceSupplier;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.CodeBlock;
|
||||
import org.springframework.javapoet.ParameterizedTypeName;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -70,7 +71,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme
|
||||
|
||||
|
||||
@Override
|
||||
public Class<?> getTarget(RegisteredBean registeredBean,
|
||||
public ClassName getTarget(RegisteredBean registeredBean,
|
||||
Executable constructorOrFactoryMethod) {
|
||||
|
||||
Class<?> target = extractDeclaringClass(registeredBean.getBeanType(), constructorOrFactoryMethod);
|
||||
@@ -79,7 +80,7 @@ class DefaultBeanRegistrationCodeFragments implements BeanRegistrationCodeFragme
|
||||
Assert.state(parent != null, "No parent available for inner bean");
|
||||
target = parent.getBeanClass();
|
||||
}
|
||||
return target;
|
||||
return ClassName.get(target);
|
||||
}
|
||||
|
||||
private Class<?> extractDeclaringClass(ResolvableType beanType, Executable executable) {
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.MethodReference;
|
||||
import org.springframework.aot.generate.MethodReference.ArgumentCodeGenerator;
|
||||
import org.springframework.aot.test.generate.TestGenerationContext;
|
||||
import org.springframework.aot.test.generate.TestTarget;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RegisteredBean;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
@@ -97,7 +96,7 @@ class BeanRegistrationsAotContributionTests {
|
||||
@Test
|
||||
void applyToWhenHasNameGeneratesPrefixedFeatureName() {
|
||||
this.generationContext = new TestGenerationContext(
|
||||
new ClassNameGenerator(TestTarget.class, "Management"));
|
||||
new ClassNameGenerator(TestGenerationContext.TEST_TARGET, "Management"));
|
||||
this.beanFactoryInitializationCode = new MockBeanFactoryInitializationCode(this.generationContext);
|
||||
Map<String, BeanDefinitionMethodGenerator> registrations = new LinkedHashMap<>();
|
||||
RegisteredBean registeredBean = registerBean(
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.beans.testfixture.beans.factory.aot.SimpleBean;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.SimpleBeanConfiguration;
|
||||
import org.springframework.beans.testfixture.beans.factory.aot.SimpleBeanFactoryBean;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -52,45 +53,45 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
@Test
|
||||
void getTargetOnConstructor() {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
SimpleBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean,
|
||||
SimpleBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTargetOnConstructorToPublicFactoryBean() {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
SimpleBeanFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean,
|
||||
SimpleBeanFactoryBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTargetOnConstructorToPublicGenericFactoryBeanExtractTargetFromFactoryBeanType() {
|
||||
RegisteredBean registeredBean = registerTestBean(ResolvableType
|
||||
.forClassWithGenerics(GenericFactoryBean.class, SimpleBean.class));
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
GenericFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean,
|
||||
GenericFactoryBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTargetOnConstructorToPublicGenericFactoryBeanWithBoundExtractTargetFromFactoryBeanType() {
|
||||
RegisteredBean registeredBean = registerTestBean(ResolvableType
|
||||
.forClassWithGenerics(NumberFactoryBean.class, Integer.class));
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
NumberFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(Integer.class);
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean,
|
||||
NumberFactoryBean.class.getDeclaredConstructors()[0]), Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTargetOnConstructorToPublicGenericFactoryBeanUseBeanTypeAsFallback() {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
GenericFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean,
|
||||
GenericFactoryBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTargetOnConstructorToProtectedFactoryBean() {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
PrivilegedTestBeanFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean,
|
||||
PrivilegedTestBeanFactoryBean.class.getDeclaredConstructors()[0]),
|
||||
PrivilegedTestBeanFactoryBean.class);
|
||||
}
|
||||
|
||||
@@ -99,8 +100,8 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
Method method = ReflectionUtils.findMethod(SimpleBeanConfiguration.class, "simpleBean");
|
||||
assertThat(method).isNotNull();
|
||||
assertThat(createInstance(registeredBean).getTarget(registeredBean,
|
||||
method)).isEqualTo(SimpleBeanConfiguration.class);
|
||||
assertTarget(createInstance(registeredBean).getTarget(registeredBean, method),
|
||||
SimpleBeanConfiguration.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,16 +111,15 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
new RootBeanDefinition(String.class));
|
||||
Method method = ReflectionUtils.findMethod(getClass(), "createString");
|
||||
assertThat(method).isNotNull();
|
||||
assertThat(createInstance(innerBean).getTarget(innerBean,
|
||||
method)).isEqualTo(getClass());
|
||||
assertTarget(createInstance(innerBean).getTarget(innerBean, method), getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTargetOnConstructorWithInnerBeanInJavaPackage() {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
RegisteredBean innerBean = RegisteredBean.ofInnerBean(registeredBean, "innerTestBean", new RootBeanDefinition(String.class));
|
||||
assertThat(createInstance(innerBean).getTarget(innerBean,
|
||||
String.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(innerBean).getTarget(innerBean,
|
||||
String.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -127,8 +127,8 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
RegisteredBean registeredBean = registerTestBean(SimpleBean.class);
|
||||
RegisteredBean innerBean = RegisteredBean.ofInnerBean(registeredBean, "innerTestBean",
|
||||
new RootBeanDefinition(StringFactoryBean.class));
|
||||
assertThat(createInstance(innerBean).getTarget(innerBean,
|
||||
StringFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(innerBean).getTarget(innerBean,
|
||||
StringFactoryBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,8 +138,8 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
new RootBeanDefinition(SimpleBean.class));
|
||||
Method method = ReflectionUtils.findMethod(SimpleBeanConfiguration.class, "simpleBean");
|
||||
assertThat(method).isNotNull();
|
||||
assertThat(createInstance(innerBean).getTarget(innerBean, method))
|
||||
.isEqualTo(SimpleBeanConfiguration.class);
|
||||
assertTarget(createInstance(innerBean).getTarget(innerBean, method),
|
||||
SimpleBeanConfiguration.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -147,8 +147,8 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
RegisteredBean registeredBean = registerTestBean(DummyFactory.class);
|
||||
RegisteredBean innerBean = RegisteredBean.ofInnerBean(registeredBean, "innerTestBean",
|
||||
new RootBeanDefinition(SimpleBean.class));
|
||||
assertThat(createInstance(innerBean).getTarget(innerBean,
|
||||
SimpleBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(innerBean).getTarget(innerBean,
|
||||
SimpleBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -156,8 +156,12 @@ class DefaultBeanRegistrationCodeFragmentsTests {
|
||||
RegisteredBean registeredBean = registerTestBean(DummyFactory.class);
|
||||
RegisteredBean innerBean = RegisteredBean.ofInnerBean(registeredBean, "innerTestBean",
|
||||
new RootBeanDefinition(SimpleBean.class));
|
||||
assertThat(createInstance(innerBean).getTarget(innerBean,
|
||||
SimpleBeanFactoryBean.class.getDeclaredConstructors()[0])).isEqualTo(SimpleBean.class);
|
||||
assertTarget(createInstance(innerBean).getTarget(innerBean,
|
||||
SimpleBeanFactoryBean.class.getDeclaredConstructors()[0]), SimpleBean.class);
|
||||
}
|
||||
|
||||
private void assertTarget(ClassName target, Class<?> expected) {
|
||||
assertThat(target).isEqualTo(ClassName.get(expected));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.aot.generate.DefaultGenerationContext;
|
||||
import org.springframework.aot.generate.GenerationContext;
|
||||
import org.springframework.aot.generate.InMemoryGeneratedFiles;
|
||||
import org.springframework.core.test.tools.TestCompiler;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
|
||||
/**
|
||||
* {@link GenerationContext} test implementation that uses
|
||||
@@ -35,6 +36,11 @@ import org.springframework.core.test.tools.TestCompiler;
|
||||
*/
|
||||
public class TestGenerationContext extends DefaultGenerationContext implements UnaryOperator<TestCompiler> {
|
||||
|
||||
/**
|
||||
* The default test target {@link ClassName}.
|
||||
*/
|
||||
public static final ClassName TEST_TARGET = ClassName.get("com.example", "TestTarget");
|
||||
|
||||
/**
|
||||
* Create an instance using the specified {@link ClassNameGenerator}.
|
||||
* @param classNameGenerator the class name generator to use
|
||||
@@ -47,15 +53,15 @@ public class TestGenerationContext extends DefaultGenerationContext implements U
|
||||
* Create an instance using the specified {@code target}.
|
||||
* @param target the default target class to use
|
||||
*/
|
||||
public TestGenerationContext(Class<?> target) {
|
||||
public TestGenerationContext(ClassName target) {
|
||||
this(new ClassNameGenerator(target));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance using {@link TestTarget} as the {@code target}.
|
||||
* Create an instance using {@link #TEST_TARGET} as the {@code target}.
|
||||
*/
|
||||
public TestGenerationContext() {
|
||||
this(TestTarget.class);
|
||||
this(TEST_TARGET);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2022 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.aot.test.generate;
|
||||
|
||||
/**
|
||||
* A <em>default target class</em> used by tests of code generation.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 6.0
|
||||
*/
|
||||
public class TestTarget {
|
||||
}
|
||||
@@ -27,8 +27,8 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Generate unique class names based on a target {@link Class} and a feature
|
||||
* name.
|
||||
* Generate unique class names based on a target {@link ClassName} and a
|
||||
* feature name.
|
||||
*
|
||||
* <p>This class is stateful, so the same instance should be used for all name
|
||||
* generation.
|
||||
@@ -43,7 +43,7 @@ public final class ClassNameGenerator {
|
||||
|
||||
private static final String AOT_FEATURE = "Aot";
|
||||
|
||||
private final Class<?> defaultTarget;
|
||||
private final ClassName defaultTarget;
|
||||
|
||||
private final String featureNamePrefix;
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class ClassNameGenerator {
|
||||
* feature name prefix.
|
||||
* @param defaultTarget the default target class to use
|
||||
*/
|
||||
public ClassNameGenerator(Class<?> defaultTarget) {
|
||||
public ClassNameGenerator(ClassName defaultTarget) {
|
||||
this(defaultTarget, "");
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@ public final class ClassNameGenerator {
|
||||
* @param defaultTarget the default target class to use
|
||||
* @param featureNamePrefix the prefix to use to qualify feature names
|
||||
*/
|
||||
public ClassNameGenerator(Class<?> defaultTarget, String featureNamePrefix) {
|
||||
public ClassNameGenerator(ClassName defaultTarget, String featureNamePrefix) {
|
||||
this(defaultTarget, featureNamePrefix, new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
private ClassNameGenerator(Class<?> defaultTarget, String featureNamePrefix,
|
||||
private ClassNameGenerator(ClassName defaultTarget, String featureNamePrefix,
|
||||
Map<String, AtomicInteger> sequenceGenerator) {
|
||||
Assert.notNull(defaultTarget, "'defaultTarget' must not be null");
|
||||
this.defaultTarget = defaultTarget;
|
||||
@@ -98,16 +98,16 @@ public final class ClassNameGenerator {
|
||||
* {@code null} to use the main target
|
||||
* @return a unique generated class name
|
||||
*/
|
||||
public ClassName generateClassName(String featureName, @Nullable Class<?> target) {
|
||||
public ClassName generateClassName(String featureName, @Nullable ClassName target) {
|
||||
return generateSequencedClassName(getRootName(featureName, target));
|
||||
}
|
||||
|
||||
private String getRootName(String featureName, @Nullable Class<?> target) {
|
||||
private String getRootName(String featureName, @Nullable ClassName target) {
|
||||
Assert.hasLength(featureName, "'featureName' must not be empty");
|
||||
featureName = clean(featureName);
|
||||
Class<?> targetToUse = (target != null ? target : this.defaultTarget);
|
||||
ClassName targetToUse = (target != null ? target : this.defaultTarget);
|
||||
String featureNameToUse = this.featureNamePrefix + featureName;
|
||||
return targetToUse.getName().replace("$", "_") + SEPARATOR + StringUtils.capitalize(featureNameToUse);
|
||||
return toName(targetToUse).replace("$", "_") + SEPARATOR + StringUtils.capitalize(featureNameToUse);
|
||||
}
|
||||
|
||||
private String clean(String name) {
|
||||
@@ -147,4 +147,8 @@ public final class ClassNameGenerator {
|
||||
this.sequenceGenerator);
|
||||
}
|
||||
|
||||
private static String toName(ClassName className) {
|
||||
return GeneratedTypeReference.of(className).getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class GeneratedClasses {
|
||||
* @return an existing or newly generated class
|
||||
*/
|
||||
public GeneratedClass getOrAddForFeatureComponent(String featureName,
|
||||
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
ClassName targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
|
||||
Assert.hasLength(featureName, "'featureName' must not be empty");
|
||||
Assert.notNull(targetComponent, "'targetComponent' must not be null");
|
||||
@@ -111,6 +111,24 @@ public class GeneratedClasses {
|
||||
return generatedClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or add a generated class for the specified {@code featureName}
|
||||
* targeting the specified {@code component}. If this method has previously
|
||||
* been called with the given {@code featureName}/{@code target} the
|
||||
* existing class will be returned, otherwise a new class will be generated,
|
||||
* otherwise a new class will be generated.
|
||||
* @param featureName the name of the feature to associate with the
|
||||
* generated class
|
||||
* @param targetComponent the target component
|
||||
* @param type a {@link Consumer} used to build the type
|
||||
* @return an existing or newly generated class
|
||||
*/
|
||||
public GeneratedClass getOrAddForFeatureComponent(String featureName,
|
||||
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
|
||||
return getOrAddForFeatureComponent(featureName, ClassName.get(targetComponent), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new generated class for the specified {@code featureName} and no
|
||||
* particular component.
|
||||
@@ -135,7 +153,7 @@ public class GeneratedClasses {
|
||||
* @return the newly generated class
|
||||
*/
|
||||
public GeneratedClass addForFeatureComponent(String featureName,
|
||||
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
ClassName targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
|
||||
Assert.hasLength(featureName, "'featureName' must not be empty");
|
||||
Assert.notNull(targetComponent, "'targetComponent' must not be null");
|
||||
@@ -143,8 +161,23 @@ public class GeneratedClasses {
|
||||
return createAndAddGeneratedClass(featureName, targetComponent, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new generated class for the specified {@code featureName} targeting
|
||||
* the specified {@code component}.
|
||||
* @param featureName the name of the feature to associate with the
|
||||
* generated class
|
||||
* @param targetComponent the target component
|
||||
* @param type a {@link Consumer} used to build the type
|
||||
* @return the newly generated class
|
||||
*/
|
||||
public GeneratedClass addForFeatureComponent(String featureName,
|
||||
Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
|
||||
return addForFeatureComponent(featureName, ClassName.get(targetComponent), type);
|
||||
}
|
||||
|
||||
private GeneratedClass createAndAddGeneratedClass(String featureName,
|
||||
@Nullable Class<?> targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
@Nullable ClassName targetComponent, Consumer<TypeSpec.Builder> type) {
|
||||
|
||||
ClassName className = this.classNameGenerator.generateClassName(featureName, targetComponent);
|
||||
GeneratedClass generatedClass = new GeneratedClass(className, type);
|
||||
@@ -171,7 +204,7 @@ public class GeneratedClasses {
|
||||
this.classes, this.classesByOwner);
|
||||
}
|
||||
|
||||
private record Owner(String featureNamePrefix, String featureName, @Nullable Class<?> target) {
|
||||
private record Owner(String featureNamePrefix, String featureName, @Nullable ClassName target) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,71 +32,69 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
*/
|
||||
class ClassNameGeneratorTests {
|
||||
|
||||
private final ClassNameGenerator generator = new ClassNameGenerator(Object.class);
|
||||
private static final ClassName TEST_TARGET = ClassName.get("com.example", "Test");
|
||||
|
||||
private final ClassNameGenerator generator = new ClassNameGenerator(TEST_TARGET);
|
||||
|
||||
@Test
|
||||
void generateClassNameWhenTargetClassIsNullUsesMainTarget() {
|
||||
ClassName generated = this.generator.generateClassName("test", null);
|
||||
assertThat(generated).hasToString("java.lang.Object__Test");
|
||||
assertThat(generated).hasToString("com.example.Test__Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateClassNameUseFeatureNamePrefix() {
|
||||
ClassName generated = new ClassNameGenerator(Object.class, "One")
|
||||
.generateClassName("test", InputStream.class);
|
||||
ClassName generated = new ClassNameGenerator(TEST_TARGET, "One")
|
||||
.generateClassName("test", ClassName.get(InputStream.class));
|
||||
assertThat(generated).hasToString("java.io.InputStream__OneTest");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateClassNameWithNoTextFeatureNamePrefix() {
|
||||
ClassName generated = new ClassNameGenerator(Object.class, " ")
|
||||
.generateClassName("test", InputStream.class);
|
||||
ClassName generated = new ClassNameGenerator(TEST_TARGET, " ")
|
||||
.generateClassName("test", ClassName.get(InputStream.class));
|
||||
assertThat(generated).hasToString("java.io.InputStream__Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generatedClassNameWhenFeatureIsEmptyThrowsException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.generator.generateClassName("", InputStream.class))
|
||||
.isThrownBy(() -> this.generator.generateClassName("", ClassName.get(InputStream.class)))
|
||||
.withMessage("'featureName' must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generatedClassNameWhenFeatureIsNotAllLettersThrowsException() {
|
||||
assertThat(this.generator.generateClassName("name!", InputStream.class))
|
||||
assertThat(this.generator.generateClassName("name!", ClassName.get(InputStream.class)))
|
||||
.hasToString("java.io.InputStream__Name");
|
||||
assertThat(this.generator.generateClassName("1NameHere", InputStream.class))
|
||||
assertThat(this.generator.generateClassName("1NameHere", ClassName.get(InputStream.class)))
|
||||
.hasToString("java.io.InputStream__NameHere");
|
||||
assertThat(this.generator.generateClassName("Y0pe", InputStream.class))
|
||||
assertThat(this.generator.generateClassName("Y0pe", ClassName.get(InputStream.class)))
|
||||
.hasToString("java.io.InputStream__YPe");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateClassNameWithClassWhenLowercaseFeatureNameGeneratesName() {
|
||||
ClassName generated = this.generator.generateClassName("bytes", InputStream.class);
|
||||
ClassName generated = this.generator.generateClassName("bytes", ClassName.get(InputStream.class));
|
||||
assertThat(generated).hasToString("java.io.InputStream__Bytes");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateClassNameWithClassWhenInnerClassGeneratesName() {
|
||||
ClassName generated = this.generator.generateClassName("EventListener", TestBean.class);
|
||||
ClassName innerBean = ClassName.get("com.example", "Test", "InnerBean");
|
||||
ClassName generated = this.generator.generateClassName("EventListener", innerBean);
|
||||
assertThat(generated)
|
||||
.hasToString("org.springframework.aot.generate.ClassNameGeneratorTests_TestBean__EventListener");
|
||||
.hasToString("com.example.Test_InnerBean__EventListener");
|
||||
}
|
||||
|
||||
@Test
|
||||
void generateClassWithClassWhenMultipleCallsGeneratesSequencedName() {
|
||||
ClassName generated1 = this.generator.generateClassName("bytes", InputStream.class);
|
||||
ClassName generated2 = this.generator.generateClassName("bytes", InputStream.class);
|
||||
ClassName generated3 = this.generator.generateClassName("bytes", InputStream.class);
|
||||
ClassName generated1 = this.generator.generateClassName("bytes",ClassName.get(InputStream.class));
|
||||
ClassName generated2 = this.generator.generateClassName("bytes", ClassName.get(InputStream.class));
|
||||
ClassName generated3 = this.generator.generateClassName("bytes", ClassName.get(InputStream.class));
|
||||
assertThat(generated1).hasToString("java.io.InputStream__Bytes");
|
||||
assertThat(generated2).hasToString("java.io.InputStream__Bytes1");
|
||||
assertThat(generated3).hasToString("java.io.InputStream__Bytes2");
|
||||
}
|
||||
|
||||
|
||||
static class TestBean {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.TypeSpec;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -35,10 +36,12 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
*/
|
||||
class DefaultGenerationContextTests {
|
||||
|
||||
private static final ClassName SAMPLE_TARGET = ClassName.get("com.example", "SampleTarget");
|
||||
|
||||
private static final Consumer<TypeSpec.Builder> typeSpecCustomizer = type -> {};
|
||||
|
||||
private final GeneratedClasses generatedClasses = new GeneratedClasses(
|
||||
new ClassNameGenerator(SampleTarget.class));
|
||||
new ClassNameGenerator(SAMPLE_TARGET));
|
||||
|
||||
private final InMemoryGeneratedFiles generatedFiles = new InMemoryGeneratedFiles();
|
||||
|
||||
@@ -48,7 +51,7 @@ class DefaultGenerationContextTests {
|
||||
@Test
|
||||
void createWithOnlyGeneratedFilesCreatesContext() {
|
||||
DefaultGenerationContext context = new DefaultGenerationContext(
|
||||
new ClassNameGenerator(SampleTarget.class), this.generatedFiles);
|
||||
new ClassNameGenerator(SAMPLE_TARGET), this.generatedFiles);
|
||||
assertThat(context.getGeneratedFiles()).isSameAs(this.generatedFiles);
|
||||
assertThat(context.getRuntimeHints()).isInstanceOf(RuntimeHints.class);
|
||||
}
|
||||
@@ -109,7 +112,7 @@ class DefaultGenerationContextTests {
|
||||
@Test
|
||||
void withNameUpdateNamingConvention() {
|
||||
DefaultGenerationContext context = new DefaultGenerationContext(
|
||||
new ClassNameGenerator(SampleTarget.class), this.generatedFiles);
|
||||
new ClassNameGenerator(SAMPLE_TARGET), this.generatedFiles);
|
||||
GenerationContext anotherContext = context.withName("Another");
|
||||
GeneratedClass generatedClass = anotherContext.getGeneratedClasses()
|
||||
.addForFeature("Test", typeSpecCustomizer);
|
||||
@@ -119,7 +122,7 @@ class DefaultGenerationContextTests {
|
||||
@Test
|
||||
void withNameKeepsTrackOfAllGeneratedFiles() {
|
||||
DefaultGenerationContext context = new DefaultGenerationContext(
|
||||
new ClassNameGenerator(SampleTarget.class), this.generatedFiles);
|
||||
new ClassNameGenerator(SAMPLE_TARGET), this.generatedFiles);
|
||||
context.getGeneratedClasses().addForFeature("Test", typeSpecCustomizer);
|
||||
GenerationContext anotherContext = context.withName("Another");
|
||||
assertThat(anotherContext.getGeneratedClasses()).isNotSameAs(context.getGeneratedClasses());
|
||||
@@ -133,7 +136,7 @@ class DefaultGenerationContextTests {
|
||||
@Test
|
||||
void withNameGeneratesUniqueName() {
|
||||
DefaultGenerationContext context = new DefaultGenerationContext(
|
||||
new ClassNameGenerator(Object.class), this.generatedFiles);
|
||||
new ClassNameGenerator(SAMPLE_TARGET), this.generatedFiles);
|
||||
context.withName("Test").getGeneratedClasses()
|
||||
.addForFeature("Feature", typeSpecCustomizer);
|
||||
context.withName("Test").getGeneratedClasses()
|
||||
@@ -142,11 +145,9 @@ class DefaultGenerationContextTests {
|
||||
.addForFeature("Feature", typeSpecCustomizer);
|
||||
context.writeGeneratedContent();
|
||||
assertThat(this.generatedFiles.getGeneratedFiles(Kind.SOURCE)).containsOnlyKeys(
|
||||
"java/lang/Object__TestFeature.java",
|
||||
"java/lang/Object__Test1Feature.java",
|
||||
"java/lang/Object__Test2Feature.java");
|
||||
"com/example/SampleTarget__TestFeature.java",
|
||||
"com/example/SampleTarget__Test1Feature.java",
|
||||
"com/example/SampleTarget__Test2Feature.java");
|
||||
}
|
||||
|
||||
static class SampleTarget {}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.util.function.Consumer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.generate.GeneratedFiles.Kind;
|
||||
import org.springframework.javapoet.ClassName;
|
||||
import org.springframework.javapoet.TypeSpec;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -42,7 +43,7 @@ class GeneratedClassesTests {
|
||||
private static final Consumer<TypeSpec.Builder> emptyTypeCustomizer = type -> {};
|
||||
|
||||
private final GeneratedClasses generatedClasses = new GeneratedClasses(
|
||||
new ClassNameGenerator(Object.class));
|
||||
new ClassNameGenerator(ClassName.get("com.example", "Test")));
|
||||
|
||||
@Test
|
||||
void createWhenClassNameGeneratorIsNullThrowsException() {
|
||||
@@ -76,7 +77,7 @@ class GeneratedClassesTests {
|
||||
@Test
|
||||
void addForFeatureUsesDefaultTarget() {
|
||||
GeneratedClass generatedClass = this.generatedClasses.addForFeature("Test", emptyTypeCustomizer);
|
||||
assertThat(generatedClass.getName()).hasToString("java.lang.Object__Test");
|
||||
assertThat(generatedClass.getName()).hasToString("com.example.Test__Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -234,7 +234,7 @@ public class TestContextAotGenerator {
|
||||
}
|
||||
|
||||
DefaultGenerationContext createGenerationContext(Class<?> testClass) {
|
||||
ClassNameGenerator classNameGenerator = new ClassNameGenerator(testClass);
|
||||
ClassNameGenerator classNameGenerator = new ClassNameGenerator(ClassName.get(testClass));
|
||||
DefaultGenerationContext generationContext =
|
||||
new DefaultGenerationContext(classNameGenerator, this.generatedFiles, this.runtimeHints);
|
||||
return generationContext.withName(nextTestContextId());
|
||||
@@ -245,7 +245,8 @@ public class TestContextAotGenerator {
|
||||
}
|
||||
|
||||
private void generateTestAotMappings(MultiValueMap<ClassName, Class<?>> initializerClassMappings) {
|
||||
ClassNameGenerator classNameGenerator = new ClassNameGenerator(AotTestContextInitializers.class);
|
||||
ClassNameGenerator classNameGenerator = new ClassNameGenerator(
|
||||
ClassName.get(AotTestContextInitializers.class));
|
||||
DefaultGenerationContext generationContext =
|
||||
new DefaultGenerationContext(classNameGenerator, this.generatedFiles, this.runtimeHints);
|
||||
GeneratedClasses generatedClasses = generationContext.getGeneratedClasses();
|
||||
@@ -258,7 +259,8 @@ public class TestContextAotGenerator {
|
||||
}
|
||||
|
||||
private void generateAotTestAttributes() {
|
||||
ClassNameGenerator classNameGenerator = new ClassNameGenerator(AotTestAttributes.class);
|
||||
ClassNameGenerator classNameGenerator = new ClassNameGenerator(
|
||||
ClassName.get(AotTestAttributes.class));
|
||||
DefaultGenerationContext generationContext =
|
||||
new DefaultGenerationContext(classNameGenerator, this.generatedFiles, this.runtimeHints);
|
||||
GeneratedClasses generatedClasses = generationContext.getGeneratedClasses();
|
||||
|
||||
Reference in New Issue
Block a user