Browse Source

Refine MultiStatement#toClodeBlock

Closes gh-28363
pull/28395/head
Stephane Nicoll 4 years ago
parent
commit
10d254983f
  1. 4
      spring-beans/src/main/java/org/springframework/beans/factory/generator/BeanRegistrationBeanFactoryContribution.java
  2. 8
      spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanInstantiationContributorTests.java
  3. 2
      spring-beans/src/test/java/org/springframework/beans/factory/generator/DefaultBeanInstantiationGeneratorTests.java
  4. 28
      spring-core/src/main/java/org/springframework/javapoet/support/MultiStatement.java
  5. 48
      spring-core/src/test/java/org/springframework/javapoet/support/MultiStatementTests.java

4
spring-beans/src/main/java/org/springframework/beans/factory/generator/BeanRegistrationBeanFactoryContribution.java

@ -345,7 +345,7 @@ public class BeanRegistrationBeanFactoryContribution implements BeanFactoryContr
} }
code.add("\n").indent().indent(); code.add("\n").indent().indent();
code.add(".instanceSupplier("); code.add(".instanceSupplier(");
code.add(instanceStatements.toCodeBlock()); code.add(instanceStatements.toLambdaBody());
code.add(")").unindent().unindent(); code.add(")").unindent().unindent();
handleBeanDefinitionMetadata(code); handleBeanDefinitionMetadata(code);
} }
@ -421,7 +421,7 @@ public class BeanRegistrationBeanFactoryContribution implements BeanFactoryContr
if (statements.isEmpty()) { if (statements.isEmpty()) {
return; return;
} }
code.add(statements.toCodeBlock(".customize((" + bdVariable + ") ->")); code.add(statements.toLambdaBody(".customize((" + bdVariable + ") ->"));
code.add(")"); code.add(")");
} }

8
spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanInstantiationContributorTests.java

@ -43,7 +43,7 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
@Test @Test
void contributeWithPackageProtectedFieldInjection() { void contributeWithPackageProtectedFieldInjection() {
CodeContribution contribution = contribute(PackageProtectedFieldInjectionSample.class); CodeContribution contribution = contribute(PackageProtectedFieldInjectionSample.class);
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo(""" assertThat(CodeSnippet.process(contribution.statements().toLambdaBody())).isEqualTo("""
instanceContext.field("environment") instanceContext.field("environment")
.invoke(beanFactory, (attributes) -> bean.environment = attributes.get(0))"""); .invoke(beanFactory, (attributes) -> bean.environment = attributes.get(0))""");
assertThat(contribution.runtimeHints().reflection().typeHints()).singleElement().satisfies(typeHint -> { assertThat(contribution.runtimeHints().reflection().typeHints()).singleElement().satisfies(typeHint -> {
@ -61,7 +61,7 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
@Test @Test
void contributeWithPrivateFieldInjection() { void contributeWithPrivateFieldInjection() {
CodeContribution contribution = contribute(PrivateFieldInjectionSample.class); CodeContribution contribution = contribute(PrivateFieldInjectionSample.class);
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo(""" assertThat(CodeSnippet.process(contribution.statements().toLambdaBody())).isEqualTo("""
instanceContext.field("environment") instanceContext.field("environment")
.invoke(beanFactory, (attributes) -> { .invoke(beanFactory, (attributes) -> {
Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment"); Field environmentField = ReflectionUtils.findField(AutowiredAnnotationBeanInstantiationContributionTests.PrivateFieldInjectionSample.class, "environment");
@ -82,7 +82,7 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
@Test @Test
void contributeWithPublicMethodInjection() { void contributeWithPublicMethodInjection() {
CodeContribution contribution = contribute(PublicMethodInjectionSample.class); CodeContribution contribution = contribute(PublicMethodInjectionSample.class);
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo(""" assertThat(CodeSnippet.process(contribution.statements().toLambdaBody())).isEqualTo("""
instanceContext.method("setTestBean", TestBean.class) instanceContext.method("setTestBean", TestBean.class)
.invoke(beanFactory, (attributes) -> bean.setTestBean(attributes.get(0)))"""); .invoke(beanFactory, (attributes) -> bean.setTestBean(attributes.get(0)))""");
assertThat(contribution.runtimeHints().reflection().typeHints()).singleElement().satisfies(typeHint -> { assertThat(contribution.runtimeHints().reflection().typeHints()).singleElement().satisfies(typeHint -> {
@ -98,7 +98,7 @@ class AutowiredAnnotationBeanInstantiationContributionTests {
@Test @Test
void contributeWithInjectionPoints() { void contributeWithInjectionPoints() {
CodeContribution contribution = contribute(ResourceInjectionBean.class); CodeContribution contribution = contribute(ResourceInjectionBean.class);
assertThat(CodeSnippet.process(contribution.statements().toCodeBlock())).isEqualTo(""" assertThat(CodeSnippet.process(contribution.statements().toLambdaBody())).isEqualTo("""
instanceContext.field("testBean") instanceContext.field("testBean")
.resolve(beanFactory, false).ifResolved((attributes) -> { .resolve(beanFactory, false).ifResolved((attributes) -> {
Field testBeanField = ReflectionUtils.findField(AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean.class, "testBean"); Field testBeanField = ReflectionUtils.findField(AutowiredAnnotationBeanPostProcessorTests.ResourceInjectionBean.class, "testBean");

2
spring-beans/src/test/java/org/springframework/beans/factory/generator/DefaultBeanInstantiationGeneratorTests.java

@ -209,7 +209,7 @@ class DefaultBeanInstantiationGeneratorTests {
} }
private String code(CodeContribution contribution) { private String code(CodeContribution contribution) {
return CodeSnippet.process(contribution.statements().toCodeBlock()); return CodeSnippet.process(contribution.statements().toLambdaBody());
} }
@Nullable @Nullable

28
spring-core/src/main/java/org/springframework/javapoet/support/MultiStatement.java

@ -116,13 +116,24 @@ public final class MultiStatement {
return this; return this;
} }
/**
* Return a {@link CodeBlock} that applies all the {@code statements} of
* this instance.
* @return the code block
*/
public CodeBlock toCodeBlock() {
Builder code = CodeBlock.builder();
this.statements.forEach(statement -> statement.add(code));
return code.build();
}
/** /**
* Return a {@link CodeBlock} that applies all the {@code statements} of this * Return a {@link CodeBlock} that applies all the {@code statements} of this
* instance. If only one statement is available, it is not completed using the * instance. If only one statement is available, it is not completed using the
* {@code ;} termination so that it can be used in the context of a lambda. * {@code ;} termination so that it can be used in the context of a lambda.
* @return the statement(s) * @return the statement(s)
*/ */
public CodeBlock toCodeBlock() { public CodeBlock toLambdaBody() {
Builder code = CodeBlock.builder(); Builder code = CodeBlock.builder();
for (int i = 0; i < this.statements.size(); i++) { for (int i = 0; i < this.statements.size(); i++) {
Statement statement = this.statements.get(i); Statement statement = this.statements.get(i);
@ -137,7 +148,7 @@ public final class MultiStatement {
* @param lambda the context of the lambda, must end with {@code ->} * @param lambda the context of the lambda, must end with {@code ->}
* @return the lambda body * @return the lambda body
*/ */
public CodeBlock toCodeBlock(CodeBlock lambda) { public CodeBlock toLambdaBody(CodeBlock lambda) {
Builder code = CodeBlock.builder(); Builder code = CodeBlock.builder();
code.add(lambda); code.add(lambda);
if (isMulti()) { if (isMulti()) {
@ -146,7 +157,7 @@ public final class MultiStatement {
else { else {
code.add(" "); code.add(" ");
} }
code.add(toCodeBlock()); code.add(toLambdaBody());
if (isMulti()) { if (isMulti()) {
code.add("\n").unindent().add("}"); code.add("\n").unindent().add("}");
} }
@ -159,8 +170,8 @@ public final class MultiStatement {
* @param lambda the context of the lambda, must end with {@code ->} * @param lambda the context of the lambda, must end with {@code ->}
* @return the lambda body * @return the lambda body
*/ */
public CodeBlock toCodeBlock(String lambda) { public CodeBlock toLambdaBody(String lambda) {
return toCodeBlock(CodeBlock.of(lambda)); return toLambdaBody(CodeBlock.of(lambda));
} }
private boolean isMulti() { private boolean isMulti() {
@ -179,6 +190,13 @@ public final class MultiStatement {
this.addStatementTermination = addStatementTermination; this.addStatementTermination = addStatementTermination;
} }
void add(CodeBlock.Builder code) {
code.add(this.codeBlock);
if (this.addStatementTermination) {
code.add(";\n");
}
}
void contribute(CodeBlock.Builder code, boolean multi, boolean isLastStatement) { void contribute(CodeBlock.Builder code, boolean multi, boolean isLastStatement) {
code.add(this.codeBlock); code.add(this.codeBlock);
if (this.addStatementTermination) { if (this.addStatementTermination) {

48
spring-core/src/test/java/org/springframework/javapoet/support/MultiStatementTests.java

@ -44,48 +44,70 @@ class MultiStatementTests {
} }
@Test @Test
void singleStatement() { void singleStatementCodeBlock() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello"); statements.addStatement("field.method($S)", "hello");
CodeBlock codeBlock = statements.toCodeBlock(); 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\")"); assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")");
} }
@Test @Test
void singleStatementWithCallback() { void singleStatementWithCallbackLambdaBody() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement(code -> code.add("field.method($S)", "hello")); statements.addStatement(code -> code.add("field.method($S)", "hello"));
CodeBlock codeBlock = statements.toCodeBlock(); CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")"); assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")");
} }
@Test @Test
void singleStatementWithCodeBlock() { void singleStatementWithCodeBlockLambdaBody() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement(CodeBlock.of("field.method($S)", "hello")); statements.addStatement(CodeBlock.of("field.method($S)", "hello"));
CodeBlock codeBlock = statements.toCodeBlock(); CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")"); assertThat(codeBlock.toString()).isEqualTo("field.method(\"hello\")");
} }
@Test @Test
void multiStatements() { void multiStatementsLambdaBody() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello"); statements.addStatement("field.method($S)", "hello");
statements.addStatement("field.anotherMethod($S)", "hello"); statements.addStatement("field.anotherMethod($S)", "hello");
CodeBlock codeBlock = statements.toCodeBlock(); CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo(""" assertThat(codeBlock.toString()).isEqualTo("""
field.method("hello"); field.method("hello");
field.anotherMethod("hello");"""); field.anotherMethod("hello");""");
} }
@Test @Test
void multiStatementsWithCodeBlockRenderedAsIs() { void multiStatementsWithCodeBlockRenderedAsIsLambdaBody() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello"); statements.addStatement("field.method($S)", "hello");
statements.add(CodeBlock.of(("// Hello\n"))); statements.add(CodeBlock.of(("// Hello\n")));
statements.add(code -> code.add("// World\n")); statements.add(code -> code.add("// World\n"));
statements.addStatement("field.anotherMethod($S)", "hello"); statements.addStatement("field.anotherMethod($S)", "hello");
CodeBlock codeBlock = statements.toCodeBlock(); CodeBlock codeBlock = statements.toLambdaBody();
assertThat(codeBlock.toString()).isEqualTo(""" assertThat(codeBlock.toString()).isEqualTo("""
field.method("hello"); field.method("hello");
// Hello // Hello
@ -97,7 +119,7 @@ class MultiStatementTests {
void singleStatementWithLambda() { void singleStatementWithLambda() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello"); statements.addStatement("field.method($S)", "hello");
CodeBlock codeBlock = statements.toCodeBlock(CodeBlock.of("() ->")); CodeBlock codeBlock = statements.toLambdaBody(CodeBlock.of("() ->"));
assertThat(codeBlock.toString()).isEqualTo("() -> field.method(\"hello\")"); assertThat(codeBlock.toString()).isEqualTo("() -> field.method(\"hello\")");
} }
@ -106,7 +128,7 @@ class MultiStatementTests {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addStatement("field.method($S)", "hello"); statements.addStatement("field.method($S)", "hello");
statements.addStatement("field.anotherMethod($S)", "hello"); statements.addStatement("field.anotherMethod($S)", "hello");
CodeBlock codeBlock = statements.toCodeBlock(CodeBlock.of("() ->")); CodeBlock codeBlock = statements.toLambdaBody(CodeBlock.of("() ->"));
assertThat(codeBlock.toString().lines()).containsExactly( assertThat(codeBlock.toString().lines()).containsExactly(
"() -> {", "() -> {",
" field.method(\"hello\");", " field.method(\"hello\");",
@ -115,11 +137,11 @@ class MultiStatementTests {
} }
@Test @Test
void multiStatementsWithAddAll() { void multiStatementsWithAddAllAndLambda() {
MultiStatement statements = new MultiStatement(); MultiStatement statements = new MultiStatement();
statements.addAll(List.of(0, 1, 2), statements.addAll(List.of(0, 1, 2),
index -> CodeBlock.of("field[$L] = $S", index, "hello")); index -> CodeBlock.of("field[$L] = $S", index, "hello"));
CodeBlock codeBlock = statements.toCodeBlock("() ->"); CodeBlock codeBlock = statements.toLambdaBody("() ->");
assertThat(codeBlock.toString().lines()).containsExactly( assertThat(codeBlock.toString().lines()).containsExactly(
"() -> {", "() -> {",
" field[0] = \"hello\";", " field[0] = \"hello\";",

Loading…
Cancel
Save