Skip to content

Commit

Permalink
ISSUES-4 factory use mockBuilder (#15)
Browse files Browse the repository at this point in the history
* ISSUES-4 factory use mockBuilder

* ISSUES-4 factory use mockBuilder

* ISSUES-4 factory use mockBuilder
  • Loading branch information
h908714124 authored Nov 30, 2023
1 parent 0c66774 commit 0e910b8
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ TypeSpec generate(BuilderElement builder, MockBuilder mockBuilder) {
}

private TypeSpec generateMock(BuilderElement builder, MockBuilder mockBuilder) {
TypeMirror builderType = builder.element().asType();
TypeSpec.Builder spec = TypeSpec.classBuilder(builder.generatedClass());
FieldSpec mockBuilderField = FieldSpec.builder(mockBuilder.getClassName(), "mockBuilder", FINAL).build();
spec.addField(mockBuilderField);
Expand Down Expand Up @@ -80,7 +79,7 @@ private TypeSpec generateMock(BuilderElement builder, MockBuilder mockBuilder) {
spec.addFields(fields());
spec.addMethods(setterMethods(builder));
spec.addModifiers(PRIVATE, STATIC, FINAL);
spec.addSuperinterface(builderType);
spec.addSuperinterface(builder.element().asType());
buildMethod.addAnnotation(Override.class);
buildMethod.addModifiers(builder.buildMethod().getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ TypeSpec generate() {
}
component.factoryElement().ifPresent(factory -> {
spec.addMethod(generateFactoryMethod(factory));
spec.addType(factoryImpl.generate(factory));
spec.addType(factoryImpl.generate(factory, mockBuilder));
});
component.builderElement().ifPresent(builder -> {
spec.addMethod(generateBuilderMethod(builder));
Expand All @@ -99,12 +99,16 @@ TypeSpec generate() {
}

private MethodSpec generateFactoryMethod(FactoryElement factory) {
return MethodSpec.methodBuilder(FACTORY_METHOD)
MethodSpec.Builder spec = MethodSpec.methodBuilder(FACTORY_METHOD)
.addModifiers(STATIC)
.addModifiers(modifiers)
.returns(TypeName.get(factory.element().asType()))
.addStatement("return new $T()", factory.generatedClass())
.build();
.returns(TypeName.get(factory.element().asType()));
if (component.omitMockBuilder()) {
spec.addStatement("return new $T()", factory.generatedClass());
} else {
spec.addStatement("return new $T(null)", factory.generatedClass());
}
return spec.build();
}

private MethodSpec generateBuilderMethod(BuilderElement builder) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.jbock.simple.processor.writing;

import io.jbock.javapoet.CodeBlock;
import io.jbock.javapoet.FieldSpec;
import io.jbock.javapoet.MethodSpec;
import io.jbock.javapoet.ParameterSpec;
import io.jbock.javapoet.TypeName;
Expand Down Expand Up @@ -40,7 +41,56 @@ private FactoryImpl(
this.names = names;
}

TypeSpec generate(FactoryElement factory) {
TypeSpec generate(FactoryElement factory, MockBuilder mockBuilder) {
if (component.omitMockBuilder()) {
return generateNoMock(factory);
} else {
return generateMock(factory, mockBuilder);
}
}

private TypeSpec generateMock(FactoryElement factory, MockBuilder mockBuilder) {
TypeSpec.Builder spec = TypeSpec.classBuilder(factory.generatedClass());
FieldSpec mockBuilderField = FieldSpec.builder(mockBuilder.getClassName(), "mockBuilder", FINAL).build();
spec.addField(mockBuilderField);
ParameterSpec mockBuilderParam = ParameterSpec.builder(mockBuilder.getClassName(), "mockBuilder").build();
spec.addMethod(MethodSpec.constructorBuilder()
.addParameter(mockBuilderParam)
.addStatement("this.$N = $N", mockBuilderField, mockBuilderParam)
.build());
ExecutableElement abstractMethod = factory.singleAbstractMethod();
MethodSpec.Builder method = MethodSpec.methodBuilder(abstractMethod.getSimpleName().toString());
method.addAnnotation(Override.class);
method.addModifiers(abstractMethod.getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
method.returns(TypeName.get(component.element().asType()));
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
if (b instanceof ParameterBinding) {
continue;
}
Key key = b.key();
CodeBlock invocation = b.invocation(names);
ParameterSpec param = names.apply(key);
if (!key.typeName().isPrimitive()) {
method.addStatement("$1T $2N = this.$3N != null && this.$3N.$2N != null ? this.$3N.$2N : $4L",
key.typeName(), param, mockBuilderField, invocation);
} else {
FieldSpec auxField = FieldSpec.builder(TypeName.BOOLEAN, namedBinding.auxName(), PRIVATE).build();
method.addStatement("$1T $2N = this.$3N != null && this.$3N.$4N ? this.$3N.$2N : $5L",
key.typeName(), param, mockBuilderField, auxField, invocation);
}
}
method.addParameters(parameters());
spec.addModifiers(PRIVATE, STATIC, FINAL);
spec.addSuperinterface(factory.element().asType());
method.addStatement("return new $T($L)", component.generatedClass(), constructorParameters().stream()
.collect(CodeBlock.joining(", ")));
spec.addMethod(method.build());
return spec.build();
}

private TypeSpec generateNoMock(FactoryElement factory) {
TypeSpec.Builder spec = TypeSpec.classBuilder(factory.generatedClass());
spec.addModifiers(PRIVATE, STATIC, FINAL);
spec.addSuperinterface(factory.element().asType());
Expand All @@ -50,27 +100,47 @@ TypeSpec generate(FactoryElement factory) {
method.addModifiers(abstractMethod.getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
method.returns(TypeName.get(component.element().asType()));
List<CodeBlock> constructorParameters = new ArrayList<>();
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
Key key = b.key();
CodeBlock invocation = b.invocation(names);
ParameterSpec param = names.apply(key);
if (namedBinding.isComponentRequest()) {
constructorParameters.add(CodeBlock.of("$N", names.apply(key)));
}
if (b instanceof ParameterBinding) {
method.addParameter(names.apply(b.key()));
} else {
if (!(b instanceof ParameterBinding)) {
method.addStatement("$T $N = $L", key.typeName(), param, invocation);
}
}
method.addStatement("return new $T($L)", component.generatedClass(), constructorParameters.stream()
method.addParameters(parameters());
method.addStatement("return new $T($L)", component.generatedClass(), constructorParameters().stream()
.collect(CodeBlock.joining(", ")));
spec.addMethod(method.build());
return spec.build();
}


private List<CodeBlock> constructorParameters() {
List<CodeBlock> result = new ArrayList<>();
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
Key key = b.key();
if (namedBinding.isComponentRequest()) {
result.add(CodeBlock.of("$N", names.apply(key)));
}
}
return result;
}

private List<ParameterSpec> parameters() {
List<ParameterSpec> result = new ArrayList<>();
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
Key key = b.key();
if (b instanceof ParameterBinding) {
result.add(names.apply(key));
}
}
return result;
}

public static final class Factory {
private final ComponentElement component;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,32 +62,39 @@ ClassName getClassName() {
}

private MethodSpec buildMethod() {
List<CodeBlock> constructorParameters = new ArrayList<>();
MethodSpec.Builder method = MethodSpec.methodBuilder("build");
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
Key key = b.key();
CodeBlock invocation = b.invocation(names);
ParameterSpec param = names.apply(key);
if (namedBinding.isComponentRequest()) {
constructorParameters.add(CodeBlock.of("$N", names.apply(key)));
}
if (b instanceof ParameterBinding) {
method.addParameter(names.apply(b.key()));
} else if (!key.typeName().isPrimitive()) {
method.addStatement("$1T $2N = this.$2N != null ? this.$2N : $3L", key.typeName(), param, invocation);
} else {
FieldSpec auxField = FieldSpec.builder(TypeName.BOOLEAN, namedBinding.auxName(), PRIVATE).build();
method.addStatement("$1T $2N = this.$3N ? this.$2N : $4L", key.typeName(), param, auxField, invocation);
method.addModifiers(modifiers);
component.factoryElement().ifPresent(factory -> {
method.returns(TypeName.get(factory.element().asType()));
method.addStatement("return new $T(this)", factory.generatedClass());
});
component.builderElement().ifPresent(builder -> {
method.returns(TypeName.get(builder.element().asType()));
method.addStatement("return new $T(this)", builder.generatedClass());
});
if (component.factoryElement().isEmpty() && component.builderElement().isEmpty()) {
method.returns(TypeName.get(component.element().asType()));
List<CodeBlock> constructorParameters = new ArrayList<>();
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
Key key = b.key();
CodeBlock invocation = b.invocation(names);
ParameterSpec param = names.apply(key);
if (namedBinding.isComponentRequest()) {
constructorParameters.add(CodeBlock.of("$N", names.apply(key)));
}
if (!key.typeName().isPrimitive()) {
method.addStatement("$1T $2N = this.$2N != null ? this.$2N : $3L", key.typeName(), param, invocation);
} else {
FieldSpec auxField = FieldSpec.builder(TypeName.BOOLEAN, namedBinding.auxName(), PRIVATE).build();
method.addStatement("$1T $2N = this.$3N ? this.$2N : $4L", key.typeName(), param, auxField, invocation);
}
}
method.addStatement("return new $T($L)",
component.generatedClass(),
constructorParameters.stream().collect(CodeBlock.joining(", ")));
}
return method
.addModifiers(modifiers)
.returns(TypeName.get(component.element().asType()))
.addStatement("return new $T($L)",
component.generatedClass(),
constructorParameters.stream().collect(CodeBlock.joining(", ")))
.build();
return method.build();
}

private List<FieldSpec> getFields() {
Expand Down
16 changes: 11 additions & 5 deletions compiler/src/test/java/io/jbock/simple/processor/FactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ void noParameters() {
" }",
"",
" static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
" @Override",
" public TestClass.AComponent create() {",
" TestClass.A a = new TestClass.A();",
" TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A();",
" return new TestClass_AComponent_Impl(a);",
" }",
" }",
Expand Down Expand Up @@ -106,7 +106,7 @@ void factoryParameterIdentity() {
" }",
"",
" public static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
Expand Down Expand Up @@ -161,13 +161,19 @@ void factoryParameter() {
" }",
"",
" static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
" final MockBuilder mockBuilder;",
"",
" Factory_Impl(MockBuilder mockBuilder) {",
" this.mockBuilder = mockBuilder;",
" }",
"",
" @Override",
" public TestClass.AComponent create(String s) {",
" TestClass.A a = new TestClass.A(s);",
" TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A(s);",
" return new TestClass_AComponent_Impl(a);",
" }",
" }",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void qualifiedIdentity() {
" }",
"",
" static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
Expand All @@ -62,8 +62,8 @@ void qualifiedIdentity() {
" }",
"",
" static final class MockBuilder {",
" TestClass.AComponent build(String a, String b) {",
" return new TestClass_AComponent_Impl(a);",
" TestClass.AComponent.Factory build() {",
" return new Factory_Impl(this);",
" }",
" }",
"}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void qualifiedIdentity() {
" }",
"",
" static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ void providesPrimitive() {
" }",
"",
" static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
" @Override",
" public TestClass.AComponent create(int i) {",
" int b = TestClass.AComponent.getB(i);",
" TestClass.A a = new TestClass.A(b);",
" int b = this.mockBuilder != null && this.mockBuilder.b_isSet ? this.mockBuilder.b : TestClass.AComponent.getB(i);",
" TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A(b);",
" return new TestClass_AComponent_Impl(a);",
" }",
" }",
Expand All @@ -104,10 +104,8 @@ void providesPrimitive() {
" private boolean b_isSet;",
" private TestClass.A a;",
"",
" TestClass.AComponent build(int i) {",
" int b = this.b_isSet ? this.b : TestClass.AComponent.getB(i);",
" TestClass.A a = this.a != null ? this.a : new TestClass.A(b);",
" return new TestClass_AComponent_Impl(a);",
" TestClass.AComponent.Factory build() {",
" return new Factory_Impl(this);",
" }",
"",
" void b(int b) {",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void qualifiedIdentity() {
" }",
"",
" static TestClass.AComponent.Factory factory() {",
" return new Factory_Impl();",
" return new Factory_Impl(null);",
" }",
"",
" private static final class Factory_Impl implements TestClass.AComponent.Factory {",
Expand Down

0 comments on commit 0e910b8

Please sign in to comment.