Skip to content

Commit bbfabe4

Browse files
authored
ISSUES-4 add generatePublicMockBuilder (#10)
1 parent 8a4a81a commit bbfabe4

File tree

4 files changed

+53
-11
lines changed

4 files changed

+53
-11
lines changed

compiler/src/main/java/io/jbock/simple/processor/binding/ComponentElement.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,4 +172,20 @@ public Optional<Binding> parameterBinding(Key key) {
172172
public Collection<ParameterBinding> parameterBindings() {
173173
return parameterBindings.get().values();
174174
}
175+
176+
public boolean generatePublicMockBuilder() {
177+
Component annotation = element.getAnnotation(Component.class);
178+
if (annotation == null) {
179+
return false;
180+
}
181+
return annotation.generatePublicMockBuilder();
182+
}
183+
184+
public boolean omitMockBuilder() {
185+
Component annotation = element.getAnnotation(Component.class);
186+
if (annotation == null) {
187+
return false;
188+
}
189+
return annotation.omitMockBuilder();
190+
}
175191
}

compiler/src/main/java/io/jbock/simple/processor/writing/ComponentImpl.java

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535

3636
public class ComponentImpl {
3737

38+
private static final String FACTORY_METHOD = "factory";
39+
private static final String BUILDER_METHOD = "builder";
40+
private static final String CREATE_METHOD = "create";
41+
private static final String MOCK_BUILDER_METHOD = "mockBuilder";
42+
3843
private final ComponentElement component;
3944
private final Map<Key, NamedBinding> sorted;
4045
private final Function<Key, ParameterSpec> names;
@@ -68,7 +73,7 @@ TypeSpec generate() {
6873
spec.addMethod(method.build());
6974
}
7075
component.factoryElement().ifPresent(factory -> {
71-
spec.addMethod(MethodSpec.methodBuilder("factory")
76+
spec.addMethod(MethodSpec.methodBuilder(FACTORY_METHOD)
7277
.addModifiers(STATIC)
7378
.addModifiers(modifiers)
7479
.returns(TypeName.get(factory.element().asType()))
@@ -77,7 +82,7 @@ TypeSpec generate() {
7782
spec.addType(createFactoryImpl(factory));
7883
});
7984
component.builderElement().ifPresent(builder -> {
80-
spec.addMethod(MethodSpec.methodBuilder("builder")
85+
spec.addMethod(MethodSpec.methodBuilder(BUILDER_METHOD)
8186
.addModifiers(STATIC)
8287
.addModifiers(modifiers)
8388
.returns(TypeName.get(builder.element().asType()))
@@ -87,9 +92,11 @@ TypeSpec generate() {
8792
});
8893
if (component.factoryElement().isEmpty() && component.builderElement().isEmpty()) {
8994
spec.addMethod(generateCreateMethod());
90-
spec.addMethod(generateMockCreateMethod());
9195
}
92-
spec.addType(mockBuilder.generate());
96+
if (!component.omitMockBuilder()) {
97+
spec.addMethod(generateMockBuilderMethod());
98+
spec.addType(mockBuilder.generate());
99+
}
93100
spec.addAnnotation(AnnotationSpec.builder(Generated.class)
94101
.addMember("value", CodeBlock.of("$S", SimpleComponentProcessor.class.getCanonicalName()))
95102
.addMember("comments", CodeBlock.of("$S", "https://github.com/jbock-java/simple-component"))
@@ -102,7 +109,7 @@ TypeSpec generate() {
102109

103110
private MethodSpec generateCreateMethod() {
104111
List<CodeBlock> constructorParameters = new ArrayList<>();
105-
MethodSpec.Builder method = MethodSpec.methodBuilder("create");
112+
MethodSpec.Builder method = MethodSpec.methodBuilder(CREATE_METHOD);
106113
for (NamedBinding namedBinding : sorted.values()) {
107114
Binding b = namedBinding.binding();
108115
Key key = b.key();
@@ -123,12 +130,15 @@ private MethodSpec generateCreateMethod() {
123130
.build();
124131
}
125132

126-
MethodSpec generateMockCreateMethod() {
127-
MethodSpec.Builder method = MethodSpec.methodBuilder("mockBuilder");
133+
MethodSpec generateMockBuilderMethod() {
134+
MethodSpec.Builder method = MethodSpec.methodBuilder(MOCK_BUILDER_METHOD);
128135
method.addJavadoc("Visible for testing. Do not call this method from production code.");
129136
method.addStatement("return new $T()", mockBuilder.getClassName());
130137
method.returns(mockBuilder.getClassName());
131138
method.addModifiers(STATIC);
139+
if (component.generatePublicMockBuilder()) {
140+
method.addModifiers(modifiers);
141+
}
132142
return method.build();
133143
}
134144

compiler/src/test/java/io/jbock/simple/processor/ProcessorComponentTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void staticMethodBindings() {
3636
" @Inject static D createD() { return null; }",
3737
" }",
3838
"",
39-
" @Component",
39+
" @Component(generatePublicMockBuilder = true)",
4040
" public interface AComponent {",
4141
" A getA();",
4242
" }",
@@ -67,7 +67,7 @@ void staticMethodBindings() {
6767
" return new TestClass_AComponent_Impl(a);",
6868
" }",
6969
"",
70-
" static MockBuilder mockBuilder() {",
70+
" public static MockBuilder mockBuilder() {",
7171
" return new MockBuilder();",
7272
" }",
7373
"",

simple-component/src/main/java/io/jbock/simple/Component.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
* have the name of the type annotated, appended with {@code _Impl}. For
1313
* example, {@code @Component interface MyComponent {...}} will produce an implementation named
1414
* {@code MyComponent_Impl}.
15-
*
16-
* <h2>Component methods</h2>
15+
* <h2>Component methods
1716
*
1817
* <p>Every type annotated with {@code @Component} must contain at least one abstract component
1918
* method. Component methods may have any name, but must have no parameters and return a bound type.
@@ -56,4 +55,21 @@
5655
@Target(TYPE)
5756
@interface Builder {
5857
}
58+
59+
/**
60+
* By default, the {@code mockBuilder} method is only package-private. This
61+
* should make it less prone to accidental invocation from production code.
62+
*
63+
* <p>In test code, this restriction can be circumvented by placing a public delegate class
64+
* in the component package.
65+
*
66+
* @return {@code true} if the {@code mockBuilder} method should have the same visibility
67+
* as the component.
68+
*/
69+
boolean generatePublicMockBuilder() default false;
70+
71+
/**
72+
* @return {@code true} if the {@code mockBuilder} method should not be generated.
73+
*/
74+
boolean omitMockBuilder() default false;
5975
}

0 commit comments

Comments
 (0)