Skip to content

Commit 52dfef8

Browse files
authored
module impl (#62)
1 parent e597d2a commit 52dfef8

File tree

14 files changed

+155
-181
lines changed

14 files changed

+155
-181
lines changed

compiler/src/main/java/io/jbock/simple/processor/ContextComponent.java

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,23 @@
22

33
import io.jbock.simple.Component;
44
import io.jbock.simple.Inject;
5+
import io.jbock.simple.Provides;
6+
import io.jbock.simple.processor.binding.Binding;
57
import io.jbock.simple.processor.binding.ComponentElement;
8+
import io.jbock.simple.processor.binding.Key;
69
import io.jbock.simple.processor.binding.KeyFactory;
710
import io.jbock.simple.processor.graph.TopologicalSorter;
811
import io.jbock.simple.processor.util.TypeTool;
9-
import io.jbock.simple.processor.writing.Generator;
12+
import io.jbock.simple.processor.writing.ComponentImpl;
13+
import io.jbock.simple.processor.writing.Context;
14+
import io.jbock.simple.processor.writing.ContextModule;
15+
import io.jbock.simple.processor.writing.NamedBinding;
1016

1117
import javax.lang.model.element.TypeElement;
18+
import java.util.List;
19+
import java.util.Map;
1220

13-
@Component
21+
@Component(modules = ContextModule.class)
1422
public interface ContextComponent {
1523

1624
@Component.Builder
@@ -25,10 +33,17 @@ interface Builder {
2533
KeyFactory keyFactory();
2634

2735
ComponentElement componentElement();
28-
29-
Generator generator();
3036

31-
TopologicalSorter topologicalSorter();
37+
ComponentImpl componentImpl();
38+
39+
@Provides
40+
static Context createContext(
41+
TopologicalSorter topologicalSorter,
42+
KeyFactory keyFactory) {
43+
List<Binding> bindings = topologicalSorter.sortedBindings();
44+
Map<Key, NamedBinding> sorted = ContextModule.addNames(keyFactory, bindings);
45+
return new Context(sorted, ContextModule.createNames(sorted));
46+
}
3247

3348
final class Factory {
3449
private final TypeTool tool;

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

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import io.jbock.javapoet.ParameterSpec;
55
import io.jbock.javapoet.ParameterizedTypeName;
66
import io.jbock.javapoet.TypeName;
7-
import io.jbock.simple.Provides;
87
import io.jbock.simple.processor.util.Visitors;
98
import io.jbock.simple.processor.writing.NamedBinding;
109

@@ -30,26 +29,17 @@ public final class InjectBinding extends Binding {
3029

3130
private final KeyFactory keyFactory;
3231

33-
private static final List<String> PROVIDES_METHOD_COMMON_PREFIXES = List.of(
34-
"get",
35-
"provides",
36-
"provide",
37-
"create");
38-
3932
private final Supplier<String> suggestedVariableName = memoize(() -> {
40-
if (element().getAnnotation(Provides.class) != null) {
41-
return lowerFirst(removeMethodNamePrefix(element().getSimpleName().toString()));
42-
}
4333
Element enclosing = element().getEnclosingElement();
44-
if (enclosing != null) {
45-
if (keyFactory().tool().isSameType(key().type(), enclosing.asType())) {
46-
TypeElement enclosingOuter = Visitors.TYPE_ELEMENT_VISITOR.visit(enclosing.getEnclosingElement());
47-
if (enclosingOuter != null && keyFactory().tool().isSameType(key().type(), enclosing.asType())) {
48-
return lowerFirst(enclosingOuter.getSimpleName().toString() + simpleName(key().typeName()));
49-
}
50-
} else {
51-
return lowerFirst(enclosing.getSimpleName().toString() + simpleName(key().typeName()));
52-
}
34+
if (enclosing == null) {
35+
return lowerFirst(simpleName(key().typeName()));
36+
}
37+
if (!keyFactory().tool().isSameType(key().type(), enclosing.asType())) {
38+
return lowerFirst(enclosing.getSimpleName().toString() + simpleName(key().typeName()));
39+
}
40+
TypeElement enclosingOuter = Visitors.TYPE_ELEMENT_VISITOR.visit(enclosing.getEnclosingElement());
41+
if (enclosingOuter != null && keyFactory().tool().isSameType(key().type(), enclosing.asType())) {
42+
return lowerFirst(enclosingOuter.getSimpleName().toString() + simpleName(key().typeName()));
5343
}
5444
return lowerFirst(simpleName(key().typeName()));
5545
});
@@ -61,15 +51,6 @@ private String simpleName(TypeName typeName) {
6151
return verySimpleTypeName(typeName.toString());
6252
}
6353

64-
private static String removeMethodNamePrefix(String s) {
65-
for (String p : PROVIDES_METHOD_COMMON_PREFIXES) {
66-
if (s.startsWith(p) && s.length() > p.length()) {
67-
return s.substring(p.length());
68-
}
69-
}
70-
return s;
71-
}
72-
7354
static String simpleTypeName(ParameterizedTypeName type) {
7455
StringBuilder sb = new StringBuilder();
7556
sb.append(type.rawType.simpleName());
@@ -92,6 +73,9 @@ static String verySimpleTypeName(String typeName) {
9273
if (i >= 0) {
9374
typeName = typeName.substring(i + 1);
9475
}
76+
if (Character.isLowerCase(typeName.charAt(0))) {
77+
typeName = Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
78+
}
9579
return typeName;
9680
}
9781

compiler/src/main/java/io/jbock/simple/processor/step/ComponentStep.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,14 @@
44
import io.jbock.javapoet.TypeSpec;
55
import io.jbock.simple.Component;
66
import io.jbock.simple.Inject;
7+
import io.jbock.simple.Modulus;
78
import io.jbock.simple.processor.ContextComponent;
8-
import io.jbock.simple.processor.binding.Binding;
99
import io.jbock.simple.processor.binding.KeyFactory;
1010
import io.jbock.simple.processor.util.SpecWriter;
1111
import io.jbock.simple.processor.util.TypeTool;
1212
import io.jbock.simple.processor.util.ValidationFailure;
1313
import io.jbock.simple.processor.validation.ExecutableElementValidator;
1414
import io.jbock.simple.processor.validation.TypeElementValidator;
15-
import io.jbock.simple.processor.writing.Generator;
1615

1716
import javax.annotation.processing.Messager;
1817
import javax.lang.model.element.Element;
@@ -73,6 +72,11 @@ private void process(TypeElement typeElement) {
7372
typeElementValidator.validate(typeElement);
7473
ContextComponent context = contextComponentFactory.create(typeElement);
7574
KeyFactory keyFactory = context.keyFactory();
75+
for (TypeElement module : context.componentElement().modules()) {
76+
if (module.getAnnotation(Modulus.class) == null) {
77+
throw new ValidationFailure("The module must be annotated with @Modulus", typeElement);
78+
}
79+
}
7680
keyFactory.factoryElement().ifPresent(factory -> {
7781
ExecutableElement method = factory.singleAbstractMethod();
7882
if (!tool.types().isSameType(method.getReturnType(), typeElement.asType())) {
@@ -84,9 +88,7 @@ private void process(TypeElement typeElement) {
8488
executableElementValidator.validate(m);
8589
}
8690
}
87-
Generator generator = context.generator();
88-
List<Binding> bindings = context.topologicalSorter().sortedBindings();
89-
TypeSpec typeSpec = generator.generate(bindings);
91+
TypeSpec typeSpec = context.componentImpl().generate();
9092
specWriter.write(context.componentElement().generatedClass(), typeSpec);
9193
}
9294
}

compiler/src/main/java/io/jbock/simple/processor/step/ProvidesStep.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import io.jbock.auto.common.BasicAnnotationProcessor.Step;
44
import io.jbock.simple.Component;
55
import io.jbock.simple.Inject;
6+
import io.jbock.simple.Modulus;
67
import io.jbock.simple.Provides;
78
import io.jbock.simple.processor.util.ValidationFailure;
89

@@ -50,8 +51,8 @@ public Set<? extends Element> process(Map<String, Set<Element>> elementsByAnnota
5051
throw new ValidationFailure("The @Provides method may not return void", m);
5152
}
5253
Element enclosing = m.getEnclosingElement();
53-
if (enclosing.getAnnotation(Component.class) == null) {
54-
throw new ValidationFailure("The @Provides method must be nested inside a @Component", m);
54+
if (enclosing.getAnnotation(Component.class) == null && enclosing.getAnnotation(Modulus.class) == null) {
55+
throw new ValidationFailure("The @Provides method must be nested inside a @Component or @Modulus", m);
5556
}
5657
bindingRegistry.register(m);
5758
}

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

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,19 @@
2525
import static javax.lang.model.element.Modifier.PUBLIC;
2626
import static javax.lang.model.element.Modifier.STATIC;
2727

28-
public class BuilderImpl {
28+
public final class BuilderImpl {
2929

3030
private final ComponentElement component;
3131
private final Map<Key, NamedBinding> sorted;
3232
private final Function<Key, ParameterSpec> names;
3333

34-
private BuilderImpl(
34+
@Inject
35+
public BuilderImpl(
3536
ComponentElement component,
36-
Map<Key, NamedBinding> sorted,
37-
Function<Key, ParameterSpec> names) {
37+
Context context) {
3838
this.component = component;
39-
this.sorted = sorted;
40-
this.names = names;
39+
this.sorted = context.sorted();
40+
this.names = context.names();
4141
}
4242

4343
TypeSpec generate(BuilderElement builder, MockBuilder mockBuilder) {
@@ -136,22 +136,4 @@ private List<CodeBlock> constructorParameters() {
136136
}
137137
return result;
138138
}
139-
140-
public static final class Factory {
141-
private final ComponentElement component;
142-
143-
@Inject
144-
public Factory(ComponentElement component) {
145-
this.component = component;
146-
}
147-
148-
BuilderImpl create(
149-
Map<Key, NamedBinding> sorted,
150-
Function<Key, ParameterSpec> names) {
151-
return new BuilderImpl(
152-
component,
153-
sorted,
154-
names);
155-
}
156-
}
157139
}

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

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,26 @@ public class ComponentImpl {
4747
private final FactoryImpl factoryImpl;
4848
private final Modifier[] modifiers;
4949

50-
private ComponentImpl(
50+
@Inject
51+
public ComponentImpl(
5152
KeyFactory keyFactory,
5253
ComponentElement component,
53-
Map<Key, NamedBinding> sorted,
54-
Function<Key, ParameterSpec> names,
54+
Context context,
5555
MockBuilder mockBuilder,
5656
BuilderImpl builderImpl,
5757
FactoryImpl factoryImpl) {
5858
this.keyFactory = keyFactory;
5959
this.component = component;
60-
this.sorted = sorted;
61-
this.names = names;
60+
this.sorted = context.sorted();
61+
this.names = context.names();
6262
this.modifiers = component.element().getModifiers().stream()
6363
.filter(m -> m == PUBLIC).toArray(Modifier[]::new);
6464
this.mockBuilder = mockBuilder;
6565
this.builderImpl = builderImpl;
6666
this.factoryImpl = factoryImpl;
6767
}
6868

69-
TypeSpec generate() {
69+
public TypeSpec generate() {
7070
TypeSpec.Builder spec = TypeSpec.classBuilder(component.generatedClass())
7171
.addModifiers(modifiers)
7272
.addModifiers(FINAL)
@@ -219,38 +219,4 @@ private MethodSpec generateAllParametersConstructor() {
219219
}
220220
return constructor.build();
221221
}
222-
223-
public static final class Factory {
224-
private final KeyFactory keyFactory;
225-
private final ComponentElement component;
226-
private final MockBuilder.Factory mockBuilderFactory;
227-
private final BuilderImpl.Factory builderImplFactory;
228-
private final FactoryImpl.Factory factoryImplFactory;
229-
230-
@Inject
231-
public Factory(
232-
KeyFactory keyFactory,
233-
ComponentElement component,
234-
MockBuilder.Factory mockBuilderFactory,
235-
BuilderImpl.Factory builderImplFactory,
236-
FactoryImpl.Factory factoryImplFactory) {
237-
this.keyFactory = keyFactory;
238-
this.component = component;
239-
this.mockBuilderFactory = mockBuilderFactory;
240-
this.builderImplFactory = builderImplFactory;
241-
this.factoryImplFactory = factoryImplFactory;
242-
}
243-
244-
ComponentImpl create(
245-
Map<Key, NamedBinding> sorted,
246-
Function<Key, ParameterSpec> names) {
247-
return new ComponentImpl(
248-
keyFactory, component,
249-
sorted,
250-
names,
251-
mockBuilderFactory.create(sorted, names),
252-
builderImplFactory.create(sorted, names),
253-
factoryImplFactory.create(sorted, names));
254-
}
255-
}
256222
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package io.jbock.simple.processor.writing;
2+
3+
import io.jbock.javapoet.ParameterSpec;
4+
import io.jbock.simple.processor.binding.Key;
5+
6+
import java.util.Map;
7+
import java.util.function.Function;
8+
9+
public final class Context {
10+
11+
private final Map<Key, NamedBinding> sorted;
12+
private final Function<Key, ParameterSpec> names;
13+
14+
public Context(Map<Key, NamedBinding> sorted, Function<Key, ParameterSpec> names) {
15+
this.sorted = sorted;
16+
this.names = names;
17+
}
18+
19+
Map<Key, NamedBinding> sorted() {
20+
return sorted;
21+
}
22+
23+
Function<Key, ParameterSpec> names() {
24+
return names;
25+
}
26+
}

compiler/src/main/java/io/jbock/simple/processor/writing/Generator.java renamed to compiler/src/main/java/io/jbock/simple/processor/writing/ContextModule.java

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
package io.jbock.simple.processor.writing;
22

33
import io.jbock.javapoet.ParameterSpec;
4-
import io.jbock.javapoet.TypeSpec;
5-
import io.jbock.simple.Inject;
4+
import io.jbock.simple.Modulus;
65
import io.jbock.simple.processor.binding.Binding;
76
import io.jbock.simple.processor.binding.Key;
87
import io.jbock.simple.processor.binding.KeyFactory;
@@ -15,25 +14,12 @@
1514
import java.util.Map;
1615
import java.util.function.Function;
1716

18-
public class Generator {
17+
@Modulus
18+
public interface ContextModule {
1919

20-
private final ComponentImpl.Factory componentImpl;
21-
private final KeyFactory keyFactory;
22-
23-
@Inject
24-
public Generator(
25-
ComponentImpl.Factory componentImpl,
26-
KeyFactory keyFactory) {
27-
this.componentImpl = componentImpl;
28-
this.keyFactory = keyFactory;
29-
}
30-
31-
public TypeSpec generate(List<Binding> bindings) {
32-
Map<Key, NamedBinding> sorted = addNames(bindings);
33-
return componentImpl.create(sorted, createNames(sorted)).generate();
34-
}
35-
36-
private Map<Key, NamedBinding> addNames(List<Binding> bindings) {
20+
static Map<Key, NamedBinding> addNames(
21+
KeyFactory keyFactory,
22+
List<Binding> bindings) {
3723
UniqueNameSet uniqueNameSet = new UniqueNameSet();
3824
uniqueNameSet.claim("mockBuilder");
3925
uniqueNameSet.claim("withMocks");
@@ -47,7 +33,7 @@ private Map<Key, NamedBinding> addNames(List<Binding> bindings) {
4733
return result;
4834
}
4935

50-
private static Function<Key, ParameterSpec> createNames(
36+
static Function<Key, ParameterSpec> createNames(
5137
Map<Key, NamedBinding> sorted) {
5238
Map<Key, ParameterSpec> cache = new HashMap<>();
5339
return key -> {
@@ -98,4 +84,5 @@ private static String protectAgainstKeywords(String candidateName) {
9884
return SourceVersion.isKeyword(candidateName) ? candidateName + '_' : candidateName;
9985
}
10086
}
87+
10188
}

0 commit comments

Comments
 (0)