Complete refactor of AOT concepts

Remove the AOT code that now has an alternative API.

Closes gh-28414
This commit is contained in:
Phillip Webb
2022-05-04 20:23:24 -07:00
parent 702207d9ee
commit 16e7f1f212
83 changed files with 9 additions and 10950 deletions

View File

@@ -1,46 +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.generator;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.RuntimeHints;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultCodeContribution}.
*
* @author Stephane Nicoll
*/
class DefaultCodeContributionTests {
@Test
void newCodeContributionIsEmpty() {
CodeContribution contribution = new DefaultCodeContribution(new RuntimeHints());
assertThat(contribution.statements().isEmpty()).isTrue();
assertThat(contribution.protectedAccess().isAccessible("com.example")).isTrue();
}
@Test
void codeContributionReusesRuntimeHints() {
RuntimeHints runtimeHints = new RuntimeHints();
CodeContribution contribution = new DefaultCodeContribution(runtimeHints);
assertThat(contribution.runtimeHints()).isSameAs(runtimeHints);
}
}

View File

@@ -1,100 +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.generator;
import javax.lang.model.element.Modifier;
import org.junit.jupiter.api.Test;
import org.springframework.javapoet.ClassName;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DefaultGeneratedTypeContext}.
*
* @author Stephane Nicoll
*/
class DefaultGeneratedTypeContextTests {
@Test
void runtimeHints() {
DefaultGeneratedTypeContext context = createComAcmeContext();
assertThat(context.runtimeHints()).isNotNull();
}
@Test
void getGeneratedTypeMatchesGetMainGeneratedTypeForMainPackage() {
DefaultGeneratedTypeContext context = createComAcmeContext();
assertThat(context.getMainGeneratedType().getClassName()).isEqualTo(ClassName.get("com.acme", "Main"));
assertThat(context.getGeneratedType("com.acme")).isSameAs(context.getMainGeneratedType());
}
@Test
void getMainGeneratedTypeIsLazilyCreated() {
DefaultGeneratedTypeContext context = createComAcmeContext();
assertThat(context.hasGeneratedType("com.acme")).isFalse();
context.getMainGeneratedType();
assertThat(context.hasGeneratedType("com.acme")).isTrue();
}
@Test
void getGeneratedTypeRegisterInstance() {
DefaultGeneratedTypeContext context = createComAcmeContext();
assertThat(context.hasGeneratedType("com.example")).isFalse();
GeneratedType generatedType = context.getGeneratedType("com.example");
assertThat(generatedType).isNotNull();
assertThat(generatedType.getClassName().simpleName()).isEqualTo("Main");
assertThat(context.hasGeneratedType("com.example")).isTrue();
}
@Test
void getGeneratedTypeReuseInstance() {
DefaultGeneratedTypeContext context = createComAcmeContext();
GeneratedType generatedType = context.getGeneratedType("com.example");
assertThat(generatedType.getClassName().packageName()).isEqualTo("com.example");
assertThat(context.getGeneratedType("com.example")).isSameAs(generatedType);
}
@Test
void toJavaFilesWithNoTypeIsEmpty() {
DefaultGeneratedTypeContext writerContext = createComAcmeContext();
assertThat(writerContext.toJavaFiles()).hasSize(0);
}
@Test
void toJavaFilesWithDefaultTypeIsAddedLazily() {
DefaultGeneratedTypeContext writerContext = createComAcmeContext();
writerContext.getMainGeneratedType();
assertThat(writerContext.toJavaFiles()).hasSize(1);
}
@Test
void toJavaFilesWithDefaultTypeAndAdditionaTypes() {
DefaultGeneratedTypeContext writerContext = createComAcmeContext();
writerContext.getGeneratedType("com.example");
writerContext.getGeneratedType("com.another");
writerContext.getGeneratedType("com.another.another");
assertThat(writerContext.toJavaFiles()).hasSize(3);
}
private DefaultGeneratedTypeContext createComAcmeContext() {
return new DefaultGeneratedTypeContext("com.acme", packageName ->
GeneratedType.of(ClassName.get(packageName, "Main"), type -> type.addModifiers(Modifier.PUBLIC)));
}
}

View File

@@ -1,82 +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.generator;
import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.aot.hint.TypeReference;
import org.springframework.javapoet.ClassName;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GeneratedTypeReference}.
*
* @author Stephane Nicoll
*/
class GeneratedTypeReferenceTests {
@ParameterizedTest
@MethodSource("reflectionTargetNames")
void hasSuitableReflectionTargetName(TypeReference typeReference, String binaryName) {
assertThat(typeReference.getName()).isEqualTo(binaryName);
}
static Stream<Arguments> reflectionTargetNames() {
return Stream.of(
Arguments.of(GeneratedTypeReference.of(ClassName.get("com.example", "Test")), "com.example.Test"),
Arguments.of(GeneratedTypeReference.of(ClassName.get("com.example", "Test", "Inner")), "com.example.Test$Inner"));
}
@Test
void createWithClassName() {
GeneratedTypeReference typeReference = GeneratedTypeReference.of(
ClassName.get("com.example", "Test"));
assertThat(typeReference.getPackageName()).isEqualTo("com.example");
assertThat(typeReference.getSimpleName()).isEqualTo("Test");
assertThat(typeReference.getCanonicalName()).isEqualTo("com.example.Test");
assertThat(typeReference.getEnclosingType()).isNull();
}
@Test
void createWithClassNameAndParent() {
GeneratedTypeReference typeReference = GeneratedTypeReference.of(
ClassName.get("com.example", "Test").nestedClass("Nested"));
assertThat(typeReference.getPackageName()).isEqualTo("com.example");
assertThat(typeReference.getSimpleName()).isEqualTo("Nested");
assertThat(typeReference.getCanonicalName()).isEqualTo("com.example.Test.Nested");
assertThat(typeReference.getEnclosingType()).satisfies(parentTypeReference -> {
assertThat(parentTypeReference.getPackageName()).isEqualTo("com.example");
assertThat(parentTypeReference.getSimpleName()).isEqualTo("Test");
assertThat(parentTypeReference.getCanonicalName()).isEqualTo("com.example.Test");
assertThat(parentTypeReference.getEnclosingType()).isNull();
});
}
@Test
void equalsWithIdenticalCanonicalNameIsTrue() {
assertThat(GeneratedTypeReference.of(ClassName.get("java.lang", "String")))
.isEqualTo(TypeReference.of(String.class));
}
}

View File

@@ -1,129 +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.generator;
import java.io.IOException;
import java.io.StringWriter;
import javax.lang.model.element.Modifier;
import org.junit.jupiter.api.Test;
import org.springframework.javapoet.ClassName;
import org.springframework.javapoet.CodeBlock;
import org.springframework.javapoet.FieldSpec;
import org.springframework.javapoet.MethodSpec;
import org.springframework.javapoet.TypeName;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GeneratedType}.
*
* @author Stephane Nicoll
*/
class GeneratedTypeTests {
private static final ClassName TEST_CLASS_NAME = ClassName.get("com.acme", "Test");
@Test
void className() {
GeneratedType generatedType = new GeneratedType(TEST_CLASS_NAME,
type -> type.addModifiers(Modifier.STATIC));
assertThat(generatedType.getClassName()).isEqualTo(TEST_CLASS_NAME);
assertThat(generateCode(generatedType)).contains("static class Test {");
}
@Test
void createWithCustomField() {
GeneratedType generatedType = new GeneratedType(TEST_CLASS_NAME,
type -> type.addField(FieldSpec.builder(TypeName.BOOLEAN, "enabled").build()));
assertThat(generateCode(generatedType)).contains("boolean enabled;");
}
@Test
void customizeType() {
GeneratedType generatedType = createTestGeneratedType();
generatedType.customizeType(type -> type.addJavadoc("Test javadoc."))
.customizeType(type -> type.addJavadoc(" Another test javadoc"));
assertThat(generateCode(generatedType)).containsSequence(
"/**\n",
" * Test javadoc. Another test javadoc\n",
" */");
}
@Test
void addMethod() {
GeneratedType generatedType = createTestGeneratedType();
generatedType.addMethod(MethodSpec.methodBuilder("test").returns(Integer.class)
.addCode(CodeBlock.of("return 42;")));
assertThat(generateCode(generatedType)).containsSequence(
"\tInteger test() {\n",
"\t\treturn 42;\n",
"\t}");
}
@Test
void addMultipleMethods() {
GeneratedType generatedType = createTestGeneratedType();
generatedType.addMethod(MethodSpec.methodBuilder("first"));
generatedType.addMethod(MethodSpec.methodBuilder("second"));
assertThat(generateCode(generatedType))
.containsSequence("\tvoid first() {\n", "\t}")
.containsSequence("\tvoid second() {\n", "\t}");
}
@Test
void addSimilarMethodGenerateUniqueNames() {
GeneratedType generatedType = createTestGeneratedType();
MethodSpec firstMethod = generatedType.addMethod(MethodSpec.methodBuilder("test"));
MethodSpec secondMethod = generatedType.addMethod(MethodSpec.methodBuilder("test"));
MethodSpec thirdMethod = generatedType.addMethod(MethodSpec.methodBuilder("test"));
assertThat(firstMethod.name).isEqualTo("test");
assertThat(secondMethod.name).isEqualTo("test_");
assertThat(thirdMethod.name).isEqualTo("test__");
assertThat(generateCode(generatedType))
.containsSequence("\tvoid test() {\n", "\t}")
.containsSequence("\tvoid test_() {\n", "\t}")
.containsSequence("\tvoid test__() {\n", "\t}");
}
@Test
void addMethodWithSameNameAndDifferentArgumentsDoesNotChangeName() {
GeneratedType generatedType = createTestGeneratedType();
generatedType.addMethod(MethodSpec.methodBuilder("test"));
MethodSpec secondMethod = generatedType.addMethod(MethodSpec.methodBuilder("test")
.addParameter(String.class, "param"));
assertThat(secondMethod.name).isEqualTo("test");
}
private GeneratedType createTestGeneratedType() {
return GeneratedType.of(TEST_CLASS_NAME);
}
private String generateCode(GeneratedType generatedType) {
try {
StringWriter out = new StringWriter();
generatedType.toJavaFile().writeTo(out);
return out.toString();
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
}
}

View File

@@ -1,273 +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.generator;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.junit.jupiter.api.Test;
import org.springframework.aot.generator.ProtectedAccess.Options;
import org.springframework.core.ResolvableType;
import org.springframework.core.testfixture.aot.generator.visibility.ProtectedGenericParameter;
import org.springframework.core.testfixture.aot.generator.visibility.ProtectedParameter;
import org.springframework.core.testfixture.aot.generator.visibility.PublicFactoryBean;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
/**
* Tests for {@link ProtectedAccess}.
*
* @author Stephane Nicoll
*/
class ProtectedAccessTests {
public static final Options DEFAULT_OPTIONS = Options.defaults().build();
private final ProtectedAccess protectedAccess = new ProtectedAccess();
@Test
void analyzeWithPublicConstructor() throws NoSuchMethodException {
this.protectedAccess.analyze(PublicClass.class.getConstructor(), DEFAULT_OPTIONS);
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPackagePrivateConstructor() {
this.protectedAccess.analyze(ProtectedAccessor.class.getDeclaredConstructors()[0],
DEFAULT_OPTIONS);
assertPrivilegedAccess(ProtectedAccessor.class);
}
@Test
void analyzeWithPackagePrivateConstructorAndReflectionEnabled() {
Constructor<?> constructor = ProtectedAccessor.class.getDeclaredConstructors()[0];
this.protectedAccess.analyze(constructor,
Options.defaults().useReflection(member -> member.equals(constructor)).build());
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPackagePrivateClass() {
this.protectedAccess.analyze(ProtectedClass.class.getDeclaredConstructors()[0], DEFAULT_OPTIONS);
assertPrivilegedAccess(ProtectedClass.class);
}
@Test
void analyzeWithPackagePrivateDeclaringType() {
this.protectedAccess.analyze(method(ProtectedClass.class, "stringBean"), DEFAULT_OPTIONS);
assertPrivilegedAccess(ProtectedClass.class);
}
@Test
void analyzeWithPackagePrivateConstructorParameter() {
this.protectedAccess.analyze(ProtectedParameter.class.getConstructors()[0], DEFAULT_OPTIONS);
assertPrivilegedAccess(ProtectedParameter.class);
}
@Test
void analyzeWithPackagePrivateConstructorGenericParameter() {
this.protectedAccess.analyze(ProtectedGenericParameter.class.getConstructors()[0], DEFAULT_OPTIONS);
assertPrivilegedAccess(ProtectedParameter.class);
}
@Test
void analyzeWithPackagePrivateMethod() {
this.protectedAccess.analyze(method(PublicClass.class, "getProtectedMethod"), DEFAULT_OPTIONS);
assertPrivilegedAccess(PublicClass.class);
}
@Test
void analyzeWithPackagePrivateMethodAndReflectionEnabled() {
this.protectedAccess.analyze(method(PublicClass.class, "getProtectedMethod"),
Options.defaults().useReflection(member -> !Modifier.isPublic(member.getModifiers())).build());
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPackagePrivateMethodReturnType() {
this.protectedAccess.analyze(method(ProtectedAccessor.class, "methodWithProtectedReturnType"), DEFAULT_OPTIONS);
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPackagePrivateMethodReturnTypeAndAssignReturnTypeFunction() {
this.protectedAccess.analyze(method(ProtectedAccessor.class, "methodWithProtectedReturnType"),
Options.defaults().assignReturnType(member -> false).build());
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPackagePrivateMethodReturnTypeAndAssignReturnType() {
this.protectedAccess.analyze(method(ProtectedAccessor.class, "methodWithProtectedReturnType"),
Options.defaults().assignReturnType(true).build());
assertPrivilegedAccess(ProtectedAccessor.class);
}
@Test
void analyzeWithPackagePrivateMethodParameter() {
this.protectedAccess.analyze(method(ProtectedAccessor.class, "methodWithProtectedParameter",
ProtectedClass.class), DEFAULT_OPTIONS);
assertPrivilegedAccess(ProtectedAccessor.class);
}
@Test
void analyzeWithPackagePrivateField() {
this.protectedAccess.analyze(field(PublicClass.class, "protectedField"), DEFAULT_OPTIONS);
assertPrivilegedAccess(PublicClass.class);
}
@Test
void analyzeWithPackagePrivateFieldAndReflectionEnabled() {
this.protectedAccess.analyze(field(PublicClass.class, "protectedField"),
Options.defaults().useReflection(member -> true).build());
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPublicFieldAndProtectedType() {
this.protectedAccess.analyze(field(PublicClass.class, "protectedClassField"), DEFAULT_OPTIONS);
assertThat(this.protectedAccess.isAccessible("com.example")).isTrue();
}
@Test
void analyzeWithPublicFieldAndProtectedTypeAssigned() {
this.protectedAccess.analyze(field(PublicClass.class, "protectedClassField"),
Options.defaults().assignReturnType(true).build());
assertPrivilegedAccess(ProtectedClass.class);
}
@Test
void analyzeWithPackagePrivateGenericArgument() {
this.protectedAccess.analyze(method(PublicFactoryBean.class, "protectedTypeFactoryBean"),
Options.defaults().assignReturnType(true).build());
assertPrivilegedAccess(PublicFactoryBean.class);
}
@Test
void analyzeTypeWithProtectedGenericArgument() {
this.protectedAccess.analyze(PublicFactoryBean.resolveToProtectedGenericParameter());
assertPrivilegedAccess(PublicFactoryBean.class);
}
@Test
void analyzeWithRecursiveType() {
assertThat(this.protectedAccess.isProtected(ResolvableType.forClassWithGenerics(
SelfReference.class, SelfReference.class))).isEqualTo(SelfReference.class);
}
@Test
void getProtectedPackageWithPublicAccess() throws NoSuchMethodException {
this.protectedAccess.analyze(PublicClass.class.getConstructor(), DEFAULT_OPTIONS);
assertThat(this.protectedAccess.getPrivilegedPackageName("com.example")).isNull();
}
@Test
void getProtectedPackageWithProtectedAccessInOnePackage() {
this.protectedAccess.analyze(method(PublicFactoryBean.class, "protectedTypeFactoryBean"),
Options.defaults().assignReturnType(true).build());
assertThat(this.protectedAccess.getPrivilegedPackageName("com.example"))
.isEqualTo(PublicFactoryBean.class.getPackageName());
}
@Test
void getProtectedPackageWithProtectedAccessInSeveralPackages() {
Method protectedMethodFirstPackage = method(PublicFactoryBean.class, "protectedTypeFactoryBean");
Method protectedMethodSecondPackage = method(ProtectedAccessor.class, "methodWithProtectedParameter",
ProtectedClass.class);
this.protectedAccess.analyze(protectedMethodFirstPackage,
Options.defaults().assignReturnType(true).build());
this.protectedAccess.analyze(protectedMethodSecondPackage, DEFAULT_OPTIONS);
assertThatThrownBy(() -> this.protectedAccess.getPrivilegedPackageName("com.example"))
.isInstanceOfSatisfying(ProtectedAccessException.class, ex ->
assertThat(ex.getProtectedElements().stream().map(ProtectedElement::getMember))
.containsOnly(protectedMethodFirstPackage, protectedMethodSecondPackage));
}
private void assertPrivilegedAccess(Class<?> target) {
assertThat(this.protectedAccess.isAccessible("com.example")).isFalse();
assertThat(this.protectedAccess.getPrivilegedPackageName("com.example")).isEqualTo(target.getPackageName());
assertThat(this.protectedAccess.isAccessible(target.getPackageName())).isTrue();
}
private static Method method(Class<?> type, String name, Class<?>... parameterTypes) {
Method method = ReflectionUtils.findMethod(type, name, parameterTypes);
assertThat(method).isNotNull();
return method;
}
private static Field field(Class<?> type, String name) {
Field field = ReflectionUtils.findField(type, name);
assertThat(field).isNotNull();
return field;
}
@SuppressWarnings("unused")
public static class PublicClass {
String protectedField;
public ProtectedClass protectedClassField;
String getProtectedMethod() {
return this.protectedField;
}
}
@SuppressWarnings("unused")
public static class ProtectedAccessor {
ProtectedAccessor() {
}
public String methodWithProtectedParameter(ProtectedClass type) {
return "test";
}
public ProtectedClass methodWithProtectedReturnType() {
return new ProtectedClass();
}
}
@SuppressWarnings("unused")
static class ProtectedClass {
public ProtectedClass() {
}
public String stringBean() {
return "public";
}
}
static class SelfReference<T extends SelfReference<T>> {
@SuppressWarnings("unchecked")
T getThis() {
return (T) this;
}
}
}

View File

@@ -1,62 +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.generator;
import java.util.function.Function;
import java.util.function.Supplier;
import org.junit.jupiter.api.Test;
import org.springframework.core.ResolvableType;
import org.springframework.javapoet.support.CodeSnippet;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ResolvableTypeGenerator}.
*
* @author Stephane Nicoll
*/
class ResolvableTypeGeneratorTests {
@Test
void generateTypeForResolvableTypeWithGenericParameter() {
assertThat(generateTypeFor(
ResolvableType.forClassWithGenerics(Function.class,
ResolvableType.forClassWithGenerics(Supplier.class, String.class),
ResolvableType.forClassWithGenerics(Supplier.class, Integer.class))))
.isEqualTo("ResolvableType.forClassWithGenerics(Function.class, "
+ "ResolvableType.forClassWithGenerics(Supplier.class, String.class), "
+ "ResolvableType.forClassWithGenerics(Supplier.class, Integer.class))");
}
@Test
void generateTypeForResolvableTypeWithMixedParameter() {
assertThat(generateTypeFor(
ResolvableType.forClassWithGenerics(Function.class,
ResolvableType.forClassWithGenerics(Supplier.class, String.class),
ResolvableType.forClass(Integer.class))))
.isEqualTo("ResolvableType.forClassWithGenerics(Function.class, "
+ "ResolvableType.forClassWithGenerics(Supplier.class, String.class), "
+ "ResolvableType.forClass(Integer.class))");
}
private String generateTypeFor(ResolvableType type) {
return CodeSnippet.process(new ResolvableTypeGenerator().generateTypeFor(type));
}
}

View File

@@ -1,75 +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.javapoet.support;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.javapoet.CodeBlock;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link CodeSnippet}.
*
* @author Stephane Nicoll
*/
class CodeSnippetTests {
@Test
void snippetUsesTabs() {
CodeBlock.Builder code = CodeBlock.builder();
code.beginControlFlow("if (condition)");
code.addStatement("bean.doThis()");
code.endControlFlow();
CodeSnippet codeSnippet = CodeSnippet.of(code.build());
assertThat(codeSnippet.getSnippet()).isEqualTo("""
if (condition) {
bean.doThis();
}
""");
}
@Test
void snippetResolvesImports() {
CodeSnippet codeSnippet = CodeSnippet.of(
CodeBlock.of("$T list = new $T<>()", List.class, ArrayList.class));
assertThat(codeSnippet.getSnippet()).isEqualTo("List list = new ArrayList<>()");
assertThat(codeSnippet.hasImport(List.class)).isTrue();
assertThat(codeSnippet.hasImport(ArrayList.class)).isTrue();
}
@Test
void removeIndent() {
CodeBlock.Builder code = CodeBlock.builder();
code.beginControlFlow("if (condition)");
code.addStatement("doStuff()");
code.endControlFlow();
CodeSnippet snippet = CodeSnippet.of(code.build());
assertThat(snippet.getSnippet().lines()).contains("\tdoStuff();");
assertThat(snippet.removeIndent(1).getSnippet().lines()).contains("doStuff();");
}
@Test
void processProvidesSnippet() {
assertThat(CodeSnippet.process(code -> code.add("$T list;", List.class)))
.isEqualTo("List list;");
}
}

View File

@@ -1,61 +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.javapoet.support;
import org.junit.jupiter.api.Test;
import org.springframework.javapoet.CodeBlock;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link MultiCodeBlock}.
*
* @author Stephane Nicoll
*/
class MultiCodeBlockTests {
@Test
void joinWithNoElement() {
MultiCodeBlock multi = new MultiCodeBlock();
assertThat(multi.join(", ").isEmpty()).isTrue();
}
@Test
void joinWithEmptyElement() {
MultiCodeBlock multi = new MultiCodeBlock();
assertThatIllegalArgumentException().isThrownBy(() -> multi.add(CodeBlock.builder().build()));
}
@Test
void joinWithSingleElement() {
MultiCodeBlock multi = new MultiCodeBlock();
multi.add(CodeBlock.of("$S", "Hello"));
assertThat(multi.join(", ")).hasToString("\"Hello\"");
}
@Test
void joinWithSeveralElement() {
MultiCodeBlock multi = new MultiCodeBlock();
multi.add(CodeBlock.of("$S", "Hello"));
multi.add(code -> code.add("42"));
multi.add("null");
assertThat(multi.join(", ")).hasToString("\"Hello\", 42, null");
}
}

View File

@@ -1,166 +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.javapoet.support;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.javapoet.CodeBlock;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MultiStatement}.
*
* @author Stephane Nicoll
*/
class MultiStatementTests {
@Test
void isEmptyWithNoStatement() {
assertThat(new MultiStatement().isEmpty()).isTrue();
}
@Test
void isEmptyWithStatement() {
MultiStatement statements = new MultiStatement();
statements.addStatement(CodeBlock.of("int i = 0"));
assertThat(statements.isEmpty()).isFalse();
}
@Test
void singleStatementCodeBlock() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
CodeBlock codeBlock = statements.toCodeBlock();
assertThat(codeBlock.toString()).isEqualTo("""
field.method("hello");
""");
}
@Test
void multiStatementsCodeBlock() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
statements.addStatement("field.another($S)", "test");
CodeBlock codeBlock = statements.toCodeBlock();
assertThat(codeBlock.toString()).isEqualTo("""
field.method("hello");
field.another("test");
""");
}
@Test
void singleStatementLambdaBody() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")");
}
@Test
void singleStatementWithCallbackLambdaBody() {
MultiStatement statements = new MultiStatement();
statements.addStatement(code -> code.add("field.method($S)", "hello"));
CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")");
}
@Test
void singleStatementWithCodeBlockLambdaBody() {
MultiStatement statements = new MultiStatement();
statements.addStatement(CodeBlock.of("field.method($S)", "hello"));
CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")");
}
@Test
void multiStatementsLambdaBody() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
statements.addStatement("field.anotherMethod($S)", "hello");
CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("""
field.method("hello");
field.anotherMethod("hello");""");
}
@Test
void multiStatementsWithCodeBlockRenderedAsIsLambdaBody() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
statements.add(CodeBlock.of(("// Hello\n")));
statements.add(code -> code.add("// World\n"));
statements.addStatement("field.anotherMethod($S)", "hello");
CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("""
field.method("hello");
// Hello
// World
field.anotherMethod("hello");""");
}
@Test
void singleStatementWithLambda() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
CodeBlock codeBlock = statements.toLambda(CodeBlock.of("() ->"));
assertThat(codeBlock.toString()).isEqualTo("() -> field.method(\"hello\")");
}
@Test
void multiStatementsWithLambda() {
MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello");
statements.addStatement("field.anotherMethod($S)", "hello");
CodeBlock codeBlock = statements.toLambda(CodeBlock.of("() ->"));
assertThat(codeBlock.toString().lines()).containsExactly(
"() -> {",
" field.method(\"hello\");",
" field.anotherMethod(\"hello\");",
"}");
}
@Test
void multiStatementsWithAddAllAndLambda() {
MultiStatement statements = new MultiStatement();
statements.addAll(List.of(0, 1, 2),
index -> CodeBlock.of("field[$L] = $S", index, "hello"));
CodeBlock codeBlock = statements.toLambda("() ->");
assertThat(codeBlock.toString().lines()).containsExactly(
"() -> {",
" field[0] = \"hello\";",
" field[1] = \"hello\";",
" field[2] = \"hello\";",
"}");
}
@Test
void addWithAnotherMultiStatement() {
MultiStatement statements = new MultiStatement();
statements.addStatement(CodeBlock.of("test.invoke()"));
MultiStatement another = new MultiStatement();
another.addStatement(CodeBlock.of("test.another()"));
statements.add(another);
assertThat(statements.toCodeBlock().toString()).isEqualTo("""
test.invoke();
test.another();
""");
}
}