Skip to content

Commit

Permalink
ISSUES-4 builder build uses mock (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 authored Nov 30, 2023
1 parent 1487e8d commit 0c66774
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,54 +42,125 @@ private BuilderImpl(
}

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

private TypeSpec generateMock(BuilderElement builder, MockBuilder mockBuilder) {
TypeMirror builderType = builder.element().asType();
TypeSpec.Builder spec = TypeSpec.classBuilder(builder.generatedClass());
if (!component.omitMockBuilder()) {
FieldSpec field = FieldSpec.builder(mockBuilder.getClassName(), "mockBuilder", FINAL).build();
spec.addField(field);
ParameterSpec param = ParameterSpec.builder(mockBuilder.getClassName(), "mockBuilder").build();
spec.addMethod(MethodSpec.constructorBuilder()
.addParameter(param)
.addStatement("this.$N = $N", field, param)
.build());
}
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());
MethodSpec.Builder buildMethod = MethodSpec.methodBuilder(builder.buildMethod().getSimpleName().toString());
List<CodeBlock> constructorParameters = new ArrayList<>();
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 (namedBinding.isComponentRequest()) {
constructorParameters.add(CodeBlock.of("$N", names.apply(key)));
}
if (b instanceof ParameterBinding) {
spec.addField(FieldSpec.builder(b.key().typeName(), names.apply(b.key()).name).build());
MethodSpec.Builder setterMethod = MethodSpec.methodBuilder(b.element().getSimpleName().toString());
setterMethod.addAnnotation(Override.class);
setterMethod.addParameter(names.apply(b.key()));
setterMethod.addStatement("this.$N = $N", names.apply(b.key()), names.apply(b.key()));
setterMethod.addStatement("return this");
setterMethod.returns(TypeName.get(builderType));
setterMethod.addModifiers(b.element().getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
spec.addMethod(setterMethod.build());
if (!key.typeName().isPrimitive()) {
buildMethod.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();
buildMethod.addStatement("$1T $2N = this.$3N != null && this.$3N.$4N ? this.$3N.$2N : $5L",
key.typeName(), param, mockBuilderField, auxField, invocation);
}
}
spec.addFields(fields());
spec.addMethods(setterMethods(builder));
spec.addModifiers(PRIVATE, STATIC, FINAL);
spec.addSuperinterface(builderType);
buildMethod.addAnnotation(Override.class);
buildMethod.addModifiers(builder.buildMethod().getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
buildMethod.returns(TypeName.get(component.element().asType()));
buildMethod.addStatement("return new $T($L)", component.generatedClass(), constructorParameters().stream()
.collect(CodeBlock.joining(", ")));
spec.addMethod(buildMethod.build());
return spec.build();
}

private TypeSpec generateNoMock(BuilderElement builder) {
TypeMirror builderType = builder.element().asType();
TypeSpec.Builder spec = TypeSpec.classBuilder(builder.generatedClass());
MethodSpec.Builder buildMethod = MethodSpec.methodBuilder(builder.buildMethod().getSimpleName().toString());
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
Key key = b.key();
CodeBlock invocation = b.invocation(names);
ParameterSpec param = names.apply(key);
if (!(b instanceof ParameterBinding)) {
buildMethod.addStatement("$T $N = $L", key.typeName(), param, invocation);
}
}
spec.addFields(fields());
spec.addMethods(setterMethods(builder));
spec.addModifiers(PRIVATE, STATIC, FINAL);
spec.addSuperinterface(builderType);
buildMethod.addAnnotation(Override.class);
buildMethod.addModifiers(builder.buildMethod().getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
buildMethod.returns(TypeName.get(component.element().asType()));
buildMethod.addStatement("return new $T($L)", component.generatedClass(), constructorParameters.stream()
buildMethod.addStatement("return new $T($L)", component.generatedClass(), constructorParameters().stream()
.collect(CodeBlock.joining(", ")));
spec.addMethod(buildMethod.build());
return spec.build();
}

private List<FieldSpec> fields() {
List<FieldSpec> result = new ArrayList<>();
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
if (b instanceof ParameterBinding) {
result.add(FieldSpec.builder(b.key().typeName(), names.apply(b.key()).name).build());
}
}
return result;
}

private List<MethodSpec> setterMethods(BuilderElement builder) {
TypeMirror builderType = builder.element().asType();
List<MethodSpec> result = new ArrayList<>();
for (NamedBinding namedBinding : sorted.values()) {
Binding b = namedBinding.binding();
if (b instanceof ParameterBinding) {
MethodSpec.Builder setterMethod = MethodSpec.methodBuilder(b.element().getSimpleName().toString());
setterMethod.addAnnotation(Override.class);
setterMethod.addParameter(names.apply(b.key()));
setterMethod.addStatement("this.$N = $N", names.apply(b.key()), names.apply(b.key()));
setterMethod.addStatement("return this");
setterMethod.returns(TypeName.get(builderType));
setterMethod.addModifiers(b.element().getModifiers().stream()
.filter(m -> m == PUBLIC || m == PROTECTED).collect(Collectors.toList()));
result.add(setterMethod.build());
}
}
return result;
}

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;
}

public static final class Factory {
private final ComponentElement component;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,16 @@ private MethodSpec generateFactoryMethod(FactoryElement factory) {
}

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

private MethodSpec generateCreateMethod() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ private MethodSpec buildMethod() {
if (namedBinding.isComponentRequest()) {
constructorParameters.add(CodeBlock.of("$N", names.apply(key)));
}
if (namedBinding.binding() instanceof ParameterBinding) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void noParameters() {
" private static final class Builder_Impl implements TestClass.AComponent.Builder {",
" @Override",
" public TestClass.AComponent build() {",
" 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 @@ -186,7 +186,7 @@ void builderParameter() {
"",
" @Override",
" public TestClass.AComponent build() {",
" 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

0 comments on commit 0c66774

Please sign in to comment.