diff --git a/compiler/src/main/java/io/jbock/simple/processor/writing/BuilderImpl.java b/compiler/src/main/java/io/jbock/simple/processor/writing/BuilderImpl.java index cb6de15..718bb22 100644 --- a/compiler/src/main/java/io/jbock/simple/processor/writing/BuilderImpl.java +++ b/compiler/src/main/java/io/jbock/simple/processor/writing/BuilderImpl.java @@ -21,7 +21,6 @@ import java.util.stream.Collectors; import static javax.lang.model.element.Modifier.FINAL; -import static javax.lang.model.element.Modifier.PRIVATE; import static javax.lang.model.element.Modifier.PROTECTED; import static javax.lang.model.element.Modifier.PUBLIC; import static javax.lang.model.element.Modifier.STATIC; @@ -41,49 +40,29 @@ private BuilderImpl( this.names = names; } - TypeSpec generate(BuilderElement builder, MockBuilder mockBuilder, MockBuilder2 mockBuilder2) { - if (component.mockBuilder()) { - return generateMock(builder, mockBuilder, mockBuilder2); - } else { - return generateNoMock(builder); - } - } - - private TypeSpec generateMock(BuilderElement builder, MockBuilder mockBuilder, MockBuilder2 mockBuilder2) { + TypeSpec generate(BuilderElement builder, MockBuilder2 mockBuilder2) { + TypeMirror builderType = builder.element().asType(); TypeSpec.Builder spec = TypeSpec.classBuilder(builder.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()); - spec.addMethod(generateBuildMethod(builder, mockBuilderField)); - spec.addMethod(generateWithMocksMethod(mockBuilder2)); spec.addFields(fields()); spec.addMethods(setterMethods(builder)); + if (component.mockBuilder()) { + spec.addMethod(generateWithMocksMethod(mockBuilder2)); + } spec.addModifiers(PUBLIC, STATIC, FINAL); - spec.addSuperinterface(builder.element().asType()); + spec.addSuperinterface(builderType); + spec.addMethod(generateBuildMethod(builder)); return spec.build(); } - private MethodSpec generateBuildMethod(BuilderElement builder, FieldSpec mockBuilderField) { + private MethodSpec generateBuildMethod(BuilderElement builder) { MethodSpec.Builder buildMethod = MethodSpec.methodBuilder(builder.buildMethod().getSimpleName().toString()); for (NamedBinding namedBinding : sorted.values()) { Binding b = namedBinding.binding(); - if (b instanceof ParameterBinding) { - continue; - } Key key = b.key(); - CodeBlock invocation = b.invocation(names, true, sorted); + CodeBlock invocation = b.invocation(names); ParameterSpec param = names.apply(key); - 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); + if (!(b instanceof ParameterBinding)) { + buildMethod.addStatement("$T $N = $L", key.typeName(), param, invocation); } } buildMethod.addAnnotation(Override.class); @@ -115,33 +94,6 @@ private MethodSpec generateWithMocksMethod(MockBuilder2 mockBuilder2) { return method.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(PUBLIC, 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 List fields() { List result = new ArrayList<>(); for (NamedBinding namedBinding : sorted.values()) { diff --git a/compiler/src/main/java/io/jbock/simple/processor/writing/ComponentImpl.java b/compiler/src/main/java/io/jbock/simple/processor/writing/ComponentImpl.java index 21d0013..d835ad6 100644 --- a/compiler/src/main/java/io/jbock/simple/processor/writing/ComponentImpl.java +++ b/compiler/src/main/java/io/jbock/simple/processor/writing/ComponentImpl.java @@ -15,6 +15,7 @@ import io.jbock.simple.processor.binding.DependencyRequest; import io.jbock.simple.processor.binding.FactoryElement; import io.jbock.simple.processor.binding.Key; +import io.jbock.simple.processor.binding.ParameterBinding; import javax.annotation.processing.Generated; import javax.lang.model.element.Modifier; @@ -39,7 +40,6 @@ public class ComponentImpl { private final ComponentElement component; private final Map sorted; private final Function names; - private final MockBuilder mockBuilder; private final MockBuilder2 mockBuilder2; private final BuilderImpl builderImpl; private final FactoryImpl factoryImpl; @@ -49,14 +49,12 @@ private ComponentImpl( ComponentElement component, Map sorted, Function names, - MockBuilder mockBuilder, MockBuilder2 mockBuilder2, BuilderImpl builderImpl, FactoryImpl factoryImpl) { this.component = component; this.sorted = sorted; this.names = names; - this.mockBuilder = mockBuilder; this.modifiers = component.element().getModifiers().stream() .filter(m -> m == PUBLIC).toArray(Modifier[]::new); this.mockBuilder2 = mockBuilder2; @@ -80,11 +78,14 @@ TypeSpec generate() { } component.factoryElement().ifPresent(factory -> { spec.addMethod(generateFactoryMethod(factory)); - spec.addType(factoryImpl.generate(factory, mockBuilder, mockBuilder2)); + spec.addType(factoryImpl.generate(factory)); + if (component.mockBuilder()) { + spec.addMethod(generateMockBuilderMethodFactory()); + } }); component.builderElement().ifPresent(builder -> { spec.addMethod(generateBuilderMethod(builder)); - spec.addType(builderImpl.generate(builder, mockBuilder, mockBuilder2)); + spec.addType(builderImpl.generate(builder, mockBuilder2)); }); if (component.factoryElement().isEmpty() && component.builderElement().isEmpty()) { spec.addMethod(generateCreateMethod()); @@ -93,7 +94,6 @@ TypeSpec generate() { } } if (component.mockBuilder()) { - spec.addType(mockBuilder.generate()); spec.addType(mockBuilder2.generate()); } spec.addAnnotation(AnnotationSpec.builder(Generated.class) @@ -115,11 +115,7 @@ private MethodSpec generateFactoryMethod(FactoryElement factory) { .addModifiers(STATIC) .addModifiers(modifiers) .returns(factory.generatedClass()); - if (component.mockBuilder()) { - spec.addStatement("return new $T(null)", factory.generatedClass()); - } else { - spec.addStatement("return new $T()", factory.generatedClass()); - } + spec.addStatement("return new $T()", factory.generatedClass()); return spec.build(); } @@ -128,11 +124,7 @@ private MethodSpec generateBuilderMethod(BuilderElement builder) { .addModifiers(STATIC) .addModifiers(modifiers) .returns(builder.generatedClass()); - if (component.mockBuilder()) { - spec.addStatement("return new $T(null)", builder.generatedClass()); - } else { - spec.addStatement("return new $T()", builder.generatedClass()); - } + spec.addStatement("return new $T()", builder.generatedClass()); return spec.build(); } @@ -171,6 +163,27 @@ MethodSpec generateMockBuilderMethod() { return method.build(); } + MethodSpec generateMockBuilderMethodFactory() { + MethodSpec.Builder method = MethodSpec.methodBuilder(MOCK_BUILDER_METHOD); + List constructorParameters = new ArrayList<>(); + for (NamedBinding namedBinding : sorted.values()) { + Binding b = namedBinding.binding(); + if (!(b instanceof ParameterBinding)) { + continue; + } + ParameterSpec param = names.apply(b.key()); + constructorParameters.add(CodeBlock.of("$N", param)); + } + if (component.publicMockBuilder()) { + method.addModifiers(PUBLIC); + } + method.addParameters(factoryImpl.parameters()); + method.returns(mockBuilder2.getClassName()); + method.addStatement("return new $T($L)", mockBuilder2.getClassName(), + constructorParameters.stream().collect(CodeBlock.joining(", "))); + return method.build(); + } + private List getFields() { List fields = new ArrayList<>(); for (NamedBinding namedBinding : sorted.values()) { @@ -199,21 +212,18 @@ private MethodSpec generateAllParametersConstructor() { public static final class Factory { private final ComponentElement component; - private final MockBuilder.Factory mockBuilderFactory; - private final MockBuilder2.Factory mockBuilder2Factory; + private final MockBuilder2.Factory mockBuilderFactory; private final BuilderImpl.Factory builderImplFactory; private final FactoryImpl.Factory factoryImplFactory; @Inject public Factory( ComponentElement component, - MockBuilder.Factory mockBuilderFactory, - MockBuilder2.Factory mockBuilder2Factory, + MockBuilder2.Factory mockBuilderFactory, BuilderImpl.Factory builderImplFactory, FactoryImpl.Factory factoryImplFactory) { this.component = component; this.mockBuilderFactory = mockBuilderFactory; - this.mockBuilder2Factory = mockBuilder2Factory; this.builderImplFactory = builderImplFactory; this.factoryImplFactory = factoryImplFactory; } @@ -226,7 +236,6 @@ ComponentImpl create( sorted, names, mockBuilderFactory.create(sorted, names), - mockBuilder2Factory.create(sorted, names), builderImplFactory.create(sorted, names), factoryImplFactory.create(sorted, names)); } diff --git a/compiler/src/main/java/io/jbock/simple/processor/writing/FactoryImpl.java b/compiler/src/main/java/io/jbock/simple/processor/writing/FactoryImpl.java index d13eadd..c66c7f3 100644 --- a/compiler/src/main/java/io/jbock/simple/processor/writing/FactoryImpl.java +++ b/compiler/src/main/java/io/jbock/simple/processor/writing/FactoryImpl.java @@ -1,7 +1,6 @@ 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; @@ -41,82 +40,7 @@ private FactoryImpl( this.names = names; } - TypeSpec generate(FactoryElement factory, MockBuilder mockBuilder, MockBuilder2 mockBuilder2) { - if (component.mockBuilder()) { - return generateMock(factory, mockBuilder, mockBuilder2); - } else { - return generateNoMock(factory); - } - } - - private TypeSpec generateMock(FactoryElement factory, MockBuilder mockBuilder, MockBuilder2 mockBuilder2) { - 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(); - spec.addMethod(generateBuildMethod(abstractMethod, mockBuilderField)); - spec.addMethod(generateWithMocksMethod(mockBuilder2)); - spec.addModifiers(PUBLIC, STATIC, FINAL); - spec.addSuperinterface(factory.element().asType()); - return spec.build(); - } - - private MethodSpec generateBuildMethod(ExecutableElement abstractMethod, FieldSpec mockBuilderField) { - 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()); - method.addStatement("return new $T($L)", component.generatedClass(), constructorParameters().stream() - .collect(CodeBlock.joining(", "))); - return method.build(); - } - - private MethodSpec generateWithMocksMethod(MockBuilder2 mockBuilder2) { - MethodSpec.Builder method = MethodSpec.methodBuilder("withMocks"); - List constructorParameters = new ArrayList<>(); - for (NamedBinding namedBinding : sorted.values()) { - Binding b = namedBinding.binding(); - if (!(b instanceof ParameterBinding)) { - continue; - } - ParameterSpec param = names.apply(b.key()); - constructorParameters.add(CodeBlock.of("$N", param)); - } - if (component.publicMockBuilder()) { - method.addModifiers(PUBLIC); - } - method.addParameters(parameters()); - method.returns(mockBuilder2.getClassName()); - method.addStatement("return new $T($L)", mockBuilder2.getClassName(), - constructorParameters.stream().collect(CodeBlock.joining(", "))); - return method.build(); - } - - private TypeSpec generateNoMock(FactoryElement factory) { + TypeSpec generate(FactoryElement factory) { TypeSpec.Builder spec = TypeSpec.classBuilder(factory.generatedClass()); spec.addModifiers(PRIVATE, STATIC, FINAL); spec.addSuperinterface(factory.element().asType()); @@ -155,7 +79,7 @@ private List constructorParameters() { return result; } - private List parameters() { + List parameters() { List result = new ArrayList<>(); for (NamedBinding namedBinding : sorted.values()) { Binding b = namedBinding.binding(); diff --git a/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder.java b/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder.java deleted file mode 100644 index d981167..0000000 --- a/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder.java +++ /dev/null @@ -1,155 +0,0 @@ -package io.jbock.simple.processor.writing; - -import io.jbock.javapoet.ClassName; -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; -import io.jbock.javapoet.TypeSpec; -import io.jbock.simple.Inject; -import io.jbock.simple.processor.binding.Binding; -import io.jbock.simple.processor.binding.ComponentElement; -import io.jbock.simple.processor.binding.Key; -import io.jbock.simple.processor.binding.ParameterBinding; - -import javax.lang.model.element.Modifier; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; - -import static javax.lang.model.element.Modifier.FINAL; -import static javax.lang.model.element.Modifier.PRIVATE; -import static javax.lang.model.element.Modifier.PUBLIC; -import static javax.lang.model.element.Modifier.STATIC; - -public class MockBuilder { - - private final ComponentElement component; - private final Map sorted; - private final Function names; - private final Modifier[] modifiers; - - MockBuilder( - ComponentElement component, - Map sorted, - Function names) { - this.component = component; - this.sorted = sorted; - this.names = names; - this.modifiers = component.element().getModifiers().stream() - .filter(m -> m == PUBLIC).toArray(Modifier[]::new); - } - - TypeSpec generate() { - TypeSpec.Builder spec = TypeSpec.classBuilder(getClassName()) - .addModifiers(modifiers) - .addModifiers(STATIC, FINAL); - spec.addMethod(buildMethod()); - spec.addFields(getFields()); - spec.addMethods(getMethods()); - spec.addMethod(generateConstructor()); - return spec.build(); - } - - private MethodSpec generateConstructor() { - return MethodSpec.constructorBuilder().addModifiers(PRIVATE).build(); - } - - ClassName getClassName() { - return component.generatedClass().nestedClass("MockBuilder"); - } - - private MethodSpec buildMethod() { - MethodSpec.Builder method = MethodSpec.methodBuilder("build"); - 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 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.build(); - } - - private List getFields() { - List fields = new ArrayList<>(); - for (NamedBinding namedBinding : sorted.values()) { - if (namedBinding.binding() instanceof ParameterBinding) { - continue; - } - TypeName type = namedBinding.binding().key().typeName(); - FieldSpec field = FieldSpec.builder(type, namedBinding.name(), PRIVATE).build(); - fields.add(field); - if (namedBinding.binding().key().typeName().isPrimitive()) { - FieldSpec auxField = FieldSpec.builder(TypeName.BOOLEAN, namedBinding.auxName(), PRIVATE).build(); - fields.add(auxField); - } - } - return fields; - } - - private List getMethods() { - List methods = new ArrayList<>(); - for (NamedBinding namedBinding : sorted.values()) { - if (namedBinding.binding() instanceof ParameterBinding) { - continue; - } - Binding b = namedBinding.binding(); - Key key = b.key(); - ParameterSpec param = names.apply(key); - MethodSpec.Builder method = MethodSpec.methodBuilder(param.name) - .addModifiers(modifiers) - .addParameter(param) - .addStatement("this.$1N = $1N", param); - if (namedBinding.binding().key().typeName().isPrimitive()) { - FieldSpec auxField = FieldSpec.builder(TypeName.BOOLEAN, namedBinding.auxName(), PRIVATE).build(); - method.addStatement("this.$N = $L", auxField, true); - } - method.addStatement("return this"); - method.returns(getClassName()); - methods.add(method.build()); - } - return methods; - } - - public static final class Factory { - private final ComponentElement component; - - @Inject - public Factory(ComponentElement component) { - this.component = component; - } - - MockBuilder create( - Map sorted, - Function names) { - return new MockBuilder(component, sorted, names); - } - } -} diff --git a/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder2.java b/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder2.java index 1887051..302d194 100644 --- a/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder2.java +++ b/compiler/src/main/java/io/jbock/simple/processor/writing/MockBuilder2.java @@ -73,7 +73,7 @@ private MethodSpec generateConstructor() { } ClassName getClassName() { - return component.generatedClass().nestedClass("MockBuilder2"); + return component.generatedClass().nestedClass("MockBuilder"); } private MethodSpec buildMethod() { diff --git a/compiler/src/test/java/io/jbock/simple/processor/BuilderTest.java b/compiler/src/test/java/io/jbock/simple/processor/BuilderTest.java index 71e25f3..91b8dd1 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/BuilderTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/BuilderTest.java @@ -54,13 +54,13 @@ void noParameters() { " }", "", " static Builder_Impl builder() {", - " return new Builder_Impl(null);", + " return new Builder_Impl();", " }", "", " public static final class Builder_Impl implements TestClass.AComponent.Builder {", " @Override", " public TestClass.AComponent build() {", - " TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A();", + " TestClass.A a = new TestClass.A();", " return new TestClass_AComponent_Impl(a);", " }", " }", @@ -107,22 +107,22 @@ void builderParameterIdentity() { " }", "", " public static Builder_Impl builder() {", - " return new Builder_Impl(null);", + " return new Builder_Impl();", " }", "", " public static final class Builder_Impl implements TestClass.AComponent.Builder {", " String s;", "", " @Override", - " public TestClass.AComponent build() {", - " return new TestClass_AComponent_Impl(s);", - " }", - "", - " @Override", " public Builder_Impl withS(String s) {", " this.s = s;", " return this;", " }", + "", + " @Override", + " public TestClass.AComponent build() {", + " return new TestClass_AComponent_Impl(s);", + " }", " }", "}"); } @@ -175,54 +175,36 @@ void builderParameter() { " }", "", " public static Builder_Impl builder() {", - " return new Builder_Impl(null);", + " return new Builder_Impl();", " }", "", " public static final class Builder_Impl implements TestClass.AComponent.Builder {", " String s;", "", " @Override", - " public TestClass.AComponent build() {", - " TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A(this.s);", - " TestClass.B b = this.mockBuilder != null && this.mockBuilder.b != null ? this.mockBuilder.b : new TestClass.B(a);", - " return new TestClass_AComponent_Impl(b);", - " }", - "", - " public MockBuilder2 withMocks() {", - " return new MockBuilder2(this.s);", - " }", - "", - " @Override", " public Builder_Impl withS(String s) {", " this.s = s;", " return this;", " }", - " }", - "", - " public static final class MockBuilder {", - " private TestClass.A a;", "", - " private MockBuilder() {", + " public MockBuilder withMocks() {", + " return new MockBuilder(this.s);", " }", "", - " public TestClass.AComponent.Builder build() {", - " return new Builder_Impl(this);", - " }", - "", - " public MockBuilder a(TestClass.A a) {", - " this.a = a;", - " return this;", + " @Override", + " public TestClass.AComponent build() {", + " TestClass.A a = new TestClass.A(s);", + " TestClass.B b = new TestClass.B(a);", + " return new TestClass_AComponent_Impl(b);", " }", " }", "", - " public static final class MockBuilder2 {", + " public static final class MockBuilder {", " private final String s;", - "", " private TestClass.A a;", - "", " private TestClass.B b;", "", - " private MockBuilder2(String s) {", + " private MockBuilder(String s) {", " this.s = s;", " }", "", @@ -232,12 +214,12 @@ void builderParameter() { " return new TestClass_AComponent_Impl(b);", " }", "", - " public MockBuilder2 a(TestClass.A a) {", + " public MockBuilder a(TestClass.A a) {", " this.a = a;", " return this;", " }", "", - " public MockBuilder2 b(TestClass.B b) {", + " public MockBuilder b(TestClass.B b) {", " this.b = b;", " return this;", " }", diff --git a/compiler/src/test/java/io/jbock/simple/processor/FactoryTest.java b/compiler/src/test/java/io/jbock/simple/processor/FactoryTest.java index 34b2386..f0ece01 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/FactoryTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/FactoryTest.java @@ -54,13 +54,13 @@ void noParameters() { " }", "", " static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create() {", - " TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A();", + " TestClass.A a = new TestClass.A();", " return new TestClass_AComponent_Impl(a);", " }", " }", @@ -106,18 +106,14 @@ void factoryParameterIdentity() { " }", "", " public static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create(String s) {", " return new TestClass_AComponent_Impl(s);", " }", - "", - " MockBuilder2 withMocks(String s) {", - " return new MockBuilder2(s);", - " }", " }", "}"); } @@ -165,19 +161,13 @@ void factoryParameter() { " }", "", " static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", - " final MockBuilder mockBuilder;", - "", - " Factory_Impl(MockBuilder mockBuilder) {", - " this.mockBuilder = mockBuilder;", - " }", - "", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create(String s) {", - " TestClass.A a = this.mockBuilder != null && this.mockBuilder.a != null ? this.mockBuilder.a : new TestClass.A(s);", + " TestClass.A a = new TestClass.A(s);", " return new TestClass_AComponent_Impl(a);", " }", " }", diff --git a/compiler/src/test/java/io/jbock/simple/processor/JakartaQualifierTest.java b/compiler/src/test/java/io/jbock/simple/processor/JakartaQualifierTest.java index c9a32f4..50bb364 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/JakartaQualifierTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/JakartaQualifierTest.java @@ -51,17 +51,17 @@ void qualifiedIdentity() { " }", "", " static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create(String a, String b) {", " return new TestClass_AComponent_Impl(a);", " }", " }", "", - " static final class MockBuilder2 {", + " static final class MockBuilder {", " TestClass.AComponent build() {", " return new TestClass_AComponent_Impl(a);", " }", diff --git a/compiler/src/test/java/io/jbock/simple/processor/JavaxQualifierTest.java b/compiler/src/test/java/io/jbock/simple/processor/JavaxQualifierTest.java index bf13705..ac63bbc 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/JavaxQualifierTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/JavaxQualifierTest.java @@ -51,10 +51,10 @@ void qualifiedIdentity() { " }", "", " static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create(String a, String b) {", " return new TestClass_AComponent_Impl(a);", diff --git a/compiler/src/test/java/io/jbock/simple/processor/PrimitiveTest.java b/compiler/src/test/java/io/jbock/simple/processor/PrimitiveTest.java index f2a4e47..0a4b9e1 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/PrimitiveTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/PrimitiveTest.java @@ -87,25 +87,28 @@ void providesPrimitive() { " }", "", " public static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create(int i) {", - " 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);", + " int b = TestClass.AComponent.getB(i);", + " TestClass.A a = new TestClass.A(b);", " return new TestClass_AComponent_Impl(a);", " }", " }", "", " public static final class MockBuilder {", + " private final int i;", " private int b;", " private boolean b_isSet;", " private TestClass.A a;", "", - " public TestClass.AComponent.Factory build() {", - " return new Factory_Impl(this);", + " public TestClass.AComponent build() {", + " int b = this.b_isSet ? this.b : TestClass.AComponent.getB(this.i);", + " TestClass.A a = this.a != null ? this.a : new TestClass.A(b);", + " return new TestClass_AComponent_Impl(a);", " }", "", " public MockBuilder b(int b) {", diff --git a/compiler/src/test/java/io/jbock/simple/processor/ProcessorComponentTest.java b/compiler/src/test/java/io/jbock/simple/processor/ProcessorComponentTest.java index 18b04d4..51e229d 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/ProcessorComponentTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/ProcessorComponentTest.java @@ -67,11 +67,11 @@ void staticMethodBindings() { " return new TestClass_AComponent_Impl(a);", " }", "", - " public static MockBuilder2 mockBuilder() {", - " return new MockBuilder2();", + " public static MockBuilder mockBuilder() {", + " return new MockBuilder();", " }", "", - " public static final class MockBuilder2 {", + " public static final class MockBuilder {", " private TestClass.C c;", " private TestClass.B b;", " private TestClass.A a;", @@ -81,15 +81,15 @@ void staticMethodBindings() { " TestClass.A a = this.a != null ? this.a : new TestClass.A(b);", " return new TestClass_AComponent_Impl(a);", " }", - " public MockBuilder2 c(TestClass.C c) {", + " public MockBuilder c(TestClass.C c) {", " this.c = c;", " return this;", " }", - " public MockBuilder2 b(TestClass.B b) {", + " public MockBuilder b(TestClass.B b) {", " this.b = b;", " return this;", " }", - " public MockBuilder2 a(TestClass.A a) {", + " public MockBuilder a(TestClass.A a) {", " this.a = a;", " return this;", " }", @@ -154,17 +154,14 @@ void dependencyDiamond() { " return new TestClass_AComponent_Impl(a);", " }", "", - " static MockBuilder2 mockBuilder() {", - " return new MockBuilder2();", + " static MockBuilder mockBuilder() {", + " return new MockBuilder();", " }", "", - " static final class MockBuilder2 {", + " static final class MockBuilder {", " private TestClass.E e;", - "", " private TestClass.C c;", - "", " private TestClass.B b;", - "", " private TestClass.A a;", "", " TestClass.AComponent build() {", @@ -175,22 +172,22 @@ void dependencyDiamond() { " return new TestClass_AComponent_Impl(a);", " }", "", - " MockBuilder2 e(TestClass.E e) {", + " MockBuilder e(TestClass.E e) {", " this.e = e;", " return this;", " }", "", - " MockBuilder2 c(TestClass.C c) {", + " MockBuilder c(TestClass.C c) {", " this.c = c;", " return this;", " }", "", - " MockBuilder2 b(TestClass.B b) {", + " MockBuilder b(TestClass.B b) {", " this.b = b;", " return this;", " }", "", - " MockBuilder2 a(TestClass.A a) {", + " MockBuilder a(TestClass.A a) {", " this.a = a;", " return this;", " }", diff --git a/compiler/src/test/java/io/jbock/simple/processor/QualifierTest.java b/compiler/src/test/java/io/jbock/simple/processor/QualifierTest.java index 719cf06..af01a98 100644 --- a/compiler/src/test/java/io/jbock/simple/processor/QualifierTest.java +++ b/compiler/src/test/java/io/jbock/simple/processor/QualifierTest.java @@ -80,10 +80,10 @@ void qualifiedIdentity() { " }", "", " static Factory_Impl factory() {", - " return new Factory_Impl(null);", + " return new Factory_Impl();", " }", "", - " public static final class Factory_Impl implements TestClass.AComponent.Factory {", + " private static final class Factory_Impl implements TestClass.AComponent.Factory {", " @Override", " public TestClass.AComponent create(String a, String b) {", " return new TestClass_AComponent_Impl(a);", diff --git a/simple-component/src/main/java/io/jbock/simple/Component.java b/simple-component/src/main/java/io/jbock/simple/Component.java index d2b9191..a72c739 100644 --- a/simple-component/src/main/java/io/jbock/simple/Component.java +++ b/simple-component/src/main/java/io/jbock/simple/Component.java @@ -37,6 +37,8 @@ *

A factory is an interface with a single method that returns a new component instance each time it * is called. The parameters of that method provide the bound instances * required by the component. + * + *

The generated implementation of the factory will be immutable. */ @Target(TYPE) @Retention(SOURCE) @@ -51,6 +53,10 @@ * Additionally, there must be exactly one abstract no-argument method that returns the component * type, called the "build method". The setter methods provide the bound instances * required by the component. + * + *

If the {@code mockBuilder} attribute is {@code true}, then the generated implementation + * of the builder will contain an additional method called {@code withMocks} which + * returns a new {@code MockBuilder}. */ @Retention(SOURCE) @Target(TYPE) @@ -58,8 +64,17 @@ } /** - * By default, the {@code mockBuilder} method is only package-private. This - * makes it harder to invoke from production code, which is probably unintentional anyway. + * If {@code true}, the generated component implementation will contain + * a static {@code mockBuilder} method. However, if this component uses a {@code Builder}, + * the {@code mockBuilder} method will not be generated; see {@linkplain Builder}. + * + * @return {@code true} if the {@code mockBuilder} method should be generated. + */ + boolean mockBuilder() default false; + + /** + * By default, the {@code mockBuilder} (or {@code withMocks}) method is only package-private. + * This makes it harder to accidentally invoke from production code. * *

In test code, {@code mockBuilder} can always be invoked, even if it is only package-visible, * by placing a forwarding delegate class in the correct package. @@ -68,20 +83,15 @@ * like this: * *

{@code
-     * public class MockBuilderAccess {
+     * public class MyComponentAccess {
      *   public static MyComponent_Impl.MockBuilder mockBuilder() {
      *       return MyComponent_Impl.mockBuilder();
      *   }
      * }
      * }
* - * @return {@code true} if the {@code mockBuilder} method should have the same visibility - * as the component. + * @return {@code true} if the {@code mockBuilder} (or {@code withMocks}) method + * should have the same visibility as the component. */ boolean publicMockBuilder() default false; - - /** - * @return {@code true} if the {@code mockBuilder} method should be generated. - */ - boolean mockBuilder() default false; }