Skip to content

Commit

Permalink
ISSUES-17 add BindingRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 committed Dec 2, 2023
1 parent 8b10d6a commit 7061581
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.jbock.simple.processor;

import io.jbock.simple.Component;
import io.jbock.simple.Inject;
import io.jbock.simple.processor.binding.ComponentElement;
import io.jbock.simple.processor.binding.InjectBindingFactory;
import io.jbock.simple.processor.binding.KeyFactory;
Expand Down Expand Up @@ -40,4 +41,29 @@ static ContextComponent create(
Generator generator();

TopologicalSorter topologicalSorter();

final class Factory {
private final TypeTool tool;
private final InjectBindingFactory injectBindingFactory;
private final KeyFactory keyFactory;

@Inject
public Factory(
TypeTool tool,
InjectBindingFactory injectBindingFactory,
KeyFactory keyFactory) {
this.tool = tool;
this.injectBindingFactory = injectBindingFactory;
this.keyFactory = keyFactory;
}

public ContextComponent create(ComponentElement component) {
return ContextComponent_Impl.builder()
.componentElement(component)
.tool(tool)
.injectBindingFactory(injectBindingFactory)
.keyFactory(keyFactory)
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.jbock.javapoet.ClassName;
import io.jbock.simple.Component;
import io.jbock.simple.Inject;
import io.jbock.simple.Provides;
import io.jbock.simple.processor.util.ValidationFailure;
import io.jbock.simple.processor.util.Visitors;
Expand All @@ -25,6 +26,7 @@ public final class ComponentElement {

private final TypeElement element;
private final KeyFactory keyFactory;
private final InjectBinding.Factory injectBindingFactory;

private final Supplier<ClassName> generatedClass = memoize(() -> {
ClassName className = ClassName.get(element());
Expand Down Expand Up @@ -72,7 +74,7 @@ public final class ComponentElement {
continue; // ignore
}
Key key = keyFactory().getKey(method);
InjectBinding b = InjectBinding.create(keyFactory(), method);
InjectBinding b = injectBindingFactory().create(method);
result.put(key, b);
}
return result;
Expand Down Expand Up @@ -122,15 +124,11 @@ public final class ComponentElement {

private ComponentElement(
TypeElement element,
KeyFactory keyFactory) {
KeyFactory keyFactory,
InjectBinding.Factory injectBindingFactory) {
this.element = element;
this.keyFactory = keyFactory;
}

public static ComponentElement create(
TypeElement element,
KeyFactory keyFactory) {
return new ComponentElement(element, keyFactory);
this.injectBindingFactory = injectBindingFactory;
}

public TypeElement element() {
Expand Down Expand Up @@ -165,6 +163,10 @@ private KeyFactory keyFactory() {
return keyFactory;
}

private InjectBinding.Factory injectBindingFactory() {
return injectBindingFactory;
}

public Optional<Binding> parameterBinding(Key key) {
return Optional.ofNullable(parameterBindings.get().get(key));
}
Expand All @@ -188,4 +190,20 @@ public boolean omitMockBuilder() {
}
return annotation.omitMockBuilder();
}

public static final class Factory {
private final KeyFactory keyFactory;
private final InjectBinding.Factory injectBindingFactory;

@Inject
public Factory(KeyFactory keyFactory, InjectBinding.Factory injectBindingFactory) {
this.keyFactory = keyFactory;
this.injectBindingFactory = injectBindingFactory;
}

public ComponentElement create(
TypeElement element) {
return new ComponentElement(element, keyFactory, injectBindingFactory);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import io.jbock.javapoet.ParameterSpec;
import io.jbock.javapoet.ParameterizedTypeName;
import io.jbock.javapoet.TypeName;
import io.jbock.simple.Inject;
import io.jbock.simple.Provides;
import io.jbock.simple.processor.util.ValidationFailure;

Expand Down Expand Up @@ -141,4 +142,23 @@ public String toString() {
private KeyFactory keyFactory() {
return keyFactory;
}

public static final class Factory {
private final KeyFactory keyFactory;

@Inject
public Factory(KeyFactory keyFactory) {
this.keyFactory = keyFactory;
}

InjectBinding create(ExecutableElement m) {
Key key = keyFactory.getKey(m);
if (m.getKind() == ElementKind.CONSTRUCTOR) {
if (key.qualifier().isPresent()) {
throw new ValidationFailure("Constructors can't have qualifiers", m);
}
}
return new InjectBinding(key, keyFactory, m);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import io.jbock.simple.Inject;
import io.jbock.simple.processor.util.ClearableCache;
import io.jbock.simple.processor.util.TypeTool;
import io.jbock.simple.processor.util.ValidationFailure;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
Expand All @@ -15,8 +14,6 @@
import java.util.Optional;
import java.util.stream.Collectors;

import static io.jbock.simple.processor.util.Printing.INDENT;
import static io.jbock.simple.processor.util.Printing.bindingElementToString;
import static io.jbock.simple.processor.util.Visitors.EXECUTABLE_ELEMENT_VISITOR;
import static io.jbock.simple.processor.util.Visitors.TYPE_ELEMENT_VISITOR;

Expand All @@ -26,11 +23,16 @@ public final class InjectBindingFactory implements ClearableCache {

private final TypeTool tool;
private final KeyFactory keyFactory;
private final InjectBinding.Factory injectBindingFactory;

@Inject
public InjectBindingFactory(TypeTool tool, KeyFactory keyFactory) {
public InjectBindingFactory(
TypeTool tool,
KeyFactory keyFactory,
InjectBinding.Factory injectBindingFactory) {
this.tool = tool;
this.keyFactory = keyFactory;
this.injectBindingFactory = injectBindingFactory;
}

public Map<Key, InjectBinding> injectBindings(TypeElement typeElement) {
Expand All @@ -47,18 +49,11 @@ public Map<Key, InjectBinding> injectBindings(TypeElement typeElement) {
return Map.of();
}
result = new LinkedHashMap<>();
for (ExecutableElement m : allMembers) {
InjectBinding b = InjectBinding.create(keyFactory, m);
InjectBinding previous = result.put(b.key(), b);
if (previous != null) {
throw new ValidationFailure("This binding clashes with:\n"
+ INDENT
+ bindingElementToString(previous.element())
+ ".\n"
+ "Consider a (different) qualifier", b.element());
}
injectBindingCache.put(typeElement, result);
for (ExecutableElement method : allMembers) {
InjectBinding b = injectBindingFactory.create(method);
result.put(b.key(), b); // duplicates handled elsewhere
}
injectBindingCache.put(typeElement, result);
return result;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.jbock.simple.processor.step;

import io.jbock.simple.Inject;
import io.jbock.simple.processor.binding.Key;
import io.jbock.simple.processor.binding.KeyFactory;
import io.jbock.simple.processor.util.ValidationFailure;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import java.util.HashMap;
import java.util.Map;

public class BindingRegistry {

private final Map<Key, Element> bindings = new HashMap<>();
private final KeyFactory keyFactory;

@Inject
public BindingRegistry(KeyFactory keyFactory) {
this.keyFactory = keyFactory;
}

void register(ExecutableElement method) {
Key key = keyFactory.getKey(method);
Element previous = bindings.put(key, method);
if (previous != null && !previous.equals(method)) {
throw new ValidationFailure("Duplicate binding for " + key, method);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import io.jbock.simple.processor.ContextComponent;
import io.jbock.simple.processor.binding.Binding;
import io.jbock.simple.processor.binding.ComponentElement;
import io.jbock.simple.processor.binding.InjectBindingFactory;
import io.jbock.simple.processor.binding.KeyFactory;
import io.jbock.simple.processor.util.SpecWriter;
import io.jbock.simple.processor.util.TypeTool;
import io.jbock.simple.processor.util.ValidationFailure;
Expand All @@ -31,28 +29,28 @@ public class ComponentStep implements Step {

private final Messager messager;
private final TypeTool tool;
private final KeyFactory keyFactory;
private final TypeElementValidator typeElementValidator;
private final ExecutableElementValidator executableElementValidator;
private final SpecWriter specWriter;
private final InjectBindingFactory injectBindingFactory;
private final ComponentElement.Factory componentElementFactory;
private final ContextComponent.Factory contextComponentFactory;

@Inject
public ComponentStep(
Messager messager,
TypeTool tool,
KeyFactory keyFactory,
TypeElementValidator typeElementValidator,
ExecutableElementValidator executableElementValidator,
SpecWriter specWriter,
InjectBindingFactory injectBindingFactory) {
ComponentElement.Factory componentElementFactory,
ContextComponent.Factory contextComponentFactory) {
this.messager = messager;
this.tool = tool;
this.keyFactory = keyFactory;
this.typeElementValidator = typeElementValidator;
this.executableElementValidator = executableElementValidator;
this.specWriter = specWriter;
this.injectBindingFactory = injectBindingFactory;
this.componentElementFactory = componentElementFactory;
this.contextComponentFactory = contextComponentFactory;
}

@Override
Expand All @@ -76,7 +74,7 @@ public Set<? extends Element> process(Map<String, Set<Element>> elementsByAnnota

private void process(TypeElement typeElement) {
typeElementValidator.validate(typeElement);
ComponentElement component = ComponentElement.create(typeElement, keyFactory);
ComponentElement component = componentElementFactory.create(typeElement);
component.factoryElement().ifPresent(factory -> {
ExecutableElement method = factory.singleAbstractMethod();
if (!tool.types().isSameType(method.getReturnType(), typeElement.asType())) {
Expand All @@ -88,8 +86,7 @@ private void process(TypeElement typeElement) {
executableElementValidator.validate(m);
}
}
ContextComponent componentComponent = ContextComponent.create(
component, tool, injectBindingFactory, keyFactory);
ContextComponent componentComponent = contextComponentFactory.create(component);
Generator generator = componentComponent.generator();
List<Binding> bindings = componentComponent.topologicalSorter().sortedBindings();
TypeSpec typeSpec = generator.generate(bindings);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,18 @@ public class InjectStep implements Step {
private final InjectBindingValidator validator;
private final ExecutableElementValidator executableElementValidator;
private final Messager messager;
private final BindingRegistry bindingRegistry;

@Inject
public InjectStep(
InjectBindingValidator validator,
ExecutableElementValidator executableElementValidator,
Messager messager) {
Messager messager,
BindingRegistry bindingRegistry) {
this.validator = validator;
this.executableElementValidator = executableElementValidator;
this.messager = messager;
this.bindingRegistry = bindingRegistry;
}

@Override
Expand All @@ -55,10 +58,12 @@ public Set<? extends Element> process(Map<String, Set<Element>> elementsByAnnota
for (ExecutableElement constructor : constructors) {
executableElementValidator.validate(constructor);
validator.validateConstructor(constructor);
bindingRegistry.register(constructor);
}
for (ExecutableElement method : methods) {
executableElementValidator.validate(method);
validator.validateStaticMethod(method);
bindingRegistry.register(method);
}
checkFields(elements);
} catch (ValidationFailure f) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,14 @@
public class ProvidesStep implements Step {

private final Messager messager;
private final BindingRegistry bindingRegistry;

@Inject
public ProvidesStep(
Messager messager) {
Messager messager,
BindingRegistry bindingRegistry) {
this.messager = messager;
this.bindingRegistry = bindingRegistry;
}

@Override
Expand All @@ -50,6 +53,7 @@ public Set<? extends Element> process(Map<String, Set<Element>> elementsByAnnota
if (enclosing.getAnnotation(Component.class) == null) {
throw new ValidationFailure("The @Provides method must be nested inside a @Component", m);
}
bindingRegistry.register(m);
}
} catch (ValidationFailure f) {
f.writeTo(messager);
Expand Down
Loading

0 comments on commit 7061581

Please sign in to comment.