Skip to content

Commit

Permalink
make componentElement available in keyFactory (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
h908714124 authored Dec 24, 2023
1 parent 5b87943 commit 8fc97ab
Show file tree
Hide file tree
Showing 13 changed files with 314 additions and 255 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
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;
import io.jbock.simple.processor.graph.TopologicalSorter;
import io.jbock.simple.processor.util.TypeTool;
Expand All @@ -20,40 +19,30 @@ interface Builder {

Builder tool(TypeTool tool);

Builder injectBindingFactory(InjectBindingFactory injectBindingFactory);

Builder keyFactory(KeyFactory keyFactory);

ContextComponent build();
}

ComponentElement componentElement();
KeyFactory keyFactory();

ComponentElement componentElement();

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) {
TypeTool tool) {
this.tool = tool;
this.injectBindingFactory = injectBindingFactory;
this.keyFactory = keyFactory;
}

public ContextComponent create(TypeElement typeElement) {
return ContextComponent_Impl.builder()
.typeElement(typeElement)
.tool(tool)
.injectBindingFactory(injectBindingFactory)
.keyFactory(keyFactory)
.build();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import io.jbock.simple.Component;
import io.jbock.simple.Provides;
import io.jbock.simple.processor.binding.InjectBindingFactory;
import io.jbock.simple.processor.binding.KeyFactory;
import io.jbock.simple.processor.binding.InjectBindingCache;
import io.jbock.simple.processor.binding.KeyCache;
import io.jbock.simple.processor.step.ComponentFactoryStep;
import io.jbock.simple.processor.step.ComponentStep;
import io.jbock.simple.processor.step.InjectStep;
Expand Down Expand Up @@ -48,10 +48,10 @@ static Types provideTypes(ProcessingEnvironment processingEnvironment) {

@Provides
static List<ClearableCache> caches(
InjectBindingFactory injectBindingFactory,
KeyFactory keyFactory,
InjectBindingCache injectBindingCache,
KeyCache keyCache,
SafeElements safeElements) {
return List.of(injectBindingFactory, keyFactory, safeElements);
return List.of(injectBindingCache, keyCache, safeElements);
}

ComponentStep componentStep();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,15 @@
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;

import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeKind;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;

import static io.jbock.simple.processor.util.Suppliers.memoize;
import static javax.lang.model.util.ElementFilter.methodsIn;

public final class ComponentElement {

private final TypeElement element;
private final KeyFactory keyFactory;

private final Supplier<ClassName> generatedClass = memoize(() -> {
ClassName className = ClassName.get(element());
Expand All @@ -34,141 +20,20 @@ public final class ComponentElement {
.peerClass(String.join("_", className.simpleNames()) + "_Impl");
});

private final Supplier<Optional<FactoryElement>> factoryElement = memoize(() -> {
for (Element el : element().getEnclosedElements()) {
boolean hasFactoryAnnotation = el.getAnnotation(Component.Factory.class) != null;
if (!hasFactoryAnnotation) {
continue;
}
TypeElement tel = Visitors.TYPE_ELEMENT_VISITOR.visit(el);
if (tel == null) {
continue;
}
return Optional.of(new FactoryElement(tel, generatedClass(), keyFactory()));
}
return Optional.empty();
});


private final Supplier<Optional<BuilderElement>> builderElement = memoize(() -> {
for (Element el : element().getEnclosedElements()) {
boolean hasBuilderAnnotation = el.getAnnotation(Component.Builder.class) != null;
if (!hasBuilderAnnotation) {
continue;
}
TypeElement tel = Visitors.TYPE_ELEMENT_VISITOR.visit(el);
if (tel == null) {
continue;
}
return Optional.of(new BuilderElement(tel, generatedClass(), keyFactory()));
}
return Optional.empty();
});

private final Supplier<Map<Key, InjectBinding>> providesBindings = memoize(() -> {
List<ExecutableElement> methods = methodsIn(element().getEnclosedElements());
Map<Key, InjectBinding> result = new LinkedHashMap<>();
for (ExecutableElement method : methods) {
if (method.getAnnotation(Provides.class) == null) {
continue; // ignore
}
Key key = keyFactory().getKey(method);
InjectBinding b = keyFactory().createBinding(method);
result.put(key, b);
}
return result;
});

private final Supplier<Map<Key, DependencyRequest>> requests = memoize(() -> {
List<ExecutableElement> methods = methodsIn(element().getEnclosedElements());
Map<Key, DependencyRequest> result = new LinkedHashMap<>();
for (ExecutableElement method : methods) {
if (method.getModifiers().contains(Modifier.STATIC)) {
continue; // ignore
}
if (method.getAnnotation(Provides.class) != null) {
continue; // ignore
}
if (!method.getParameters().isEmpty()) {
throw new ValidationFailure("Request method may not have any parameters", method);
}
if (method.getModifiers().contains(Modifier.DEFAULT)) {
throw new ValidationFailure("Default modifier is not allowed here", method);
}
if (method.getReturnType().getKind() == TypeKind.VOID) {
throw new ValidationFailure("Request method may not return void", method);
}
Key key = keyFactory().getKey(method);
result.put(key, new DependencyRequest(key, method, method));
}
return result;
});

private final Supplier<Map<Key, ParameterBinding>> parameterBindings = memoize(() -> {
List<ParameterBinding> pBindings = factoryElement()
.map(FactoryElement::parameterBindings)
.or(() -> builderElement().map(BuilderElement::parameterBindings))
.orElse(List.of());
Map<Key, ParameterBinding> result = new LinkedHashMap<>();
for (ParameterBinding b : pBindings) {
ParameterBinding previousBinding = result.put(b.key(), b);
if (previousBinding != null) {
Element p = previousBinding.element();
throw new ValidationFailure("The binding is in conflict with another parameter: " +
p.asType() + ' ' + p.getSimpleName(), b.element());
}
}
return result;
});

@Inject
public ComponentElement(
TypeElement element,
KeyFactory keyFactory) {
TypeElement element) {
this.element = element;
this.keyFactory = keyFactory;
}

public TypeElement element() {
return element;
}

public Optional<FactoryElement> factoryElement() {
return factoryElement.get();
}

public Optional<BuilderElement> builderElement() {
return builderElement.get();
}

public boolean isComponentRequest(Binding binding) {
return requests.get().containsKey(binding.key());
}

public Collection<DependencyRequest> requests() {
return requests.get().values();
}

public Map<Key, InjectBinding> providesBindings() {
return providesBindings.get();
}

public ClassName generatedClass() {
return generatedClass.get();
}

private KeyFactory keyFactory() {
return keyFactory;
}

public Optional<Binding> parameterBinding(Key key) {
return Optional.ofNullable(parameterBindings.get().get(key));
}

public Collection<ParameterBinding> parameterBindings() {
return parameterBindings.get().values();
}

public boolean publicMockBuilder() {
Component annotation = element.getAnnotation(Component.class);
if (annotation == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.jbock.simple.processor.binding;

import io.jbock.simple.Inject;
import io.jbock.simple.processor.util.ClearableCache;

import javax.lang.model.element.TypeElement;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

public class InjectBindingCache implements ClearableCache {

private final Map<TypeElement, Map<Key, InjectBinding>> injectBindingCache = new HashMap<>();

@Inject
public InjectBindingCache() {
}

Map<Key, InjectBinding> computeIfAbsent(
TypeElement typeElement,
Function<TypeElement, Map<Key, InjectBinding>> f) {
return injectBindingCache.computeIfAbsent(typeElement, f);
}


@Override
public void clearCache() {
injectBindingCache.clear();
}
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
package io.jbock.simple.processor.binding;

import io.jbock.simple.Inject;
import io.jbock.simple.processor.util.ClearableCache;
import io.jbock.simple.processor.util.TypeTool;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static io.jbock.simple.processor.util.Visitors.TYPE_ELEMENT_VISITOR;

public final class InjectBindingFactory implements ClearableCache {

private final Map<TypeElement, Map<Key, InjectBinding>> injectBindingCache = new HashMap<>();
public final class InjectBindingFactory {

private final InjectBindingCache injectBindingCache;
private final TypeTool tool;
private final KeyFactory keyFactory;
private final InjectBindingScanner injectBindingScanner;

@Inject
public InjectBindingFactory(
TypeTool tool,
InjectBindingCache injectBindingCache,
KeyFactory keyFactory,
InjectBindingScanner injectBindingScanner) {
this.tool = tool;
this.injectBindingCache = injectBindingCache;
this.keyFactory = keyFactory;
this.injectBindingScanner = injectBindingScanner;
}
Expand All @@ -54,9 +53,4 @@ public Optional<Binding> binding(Key key) {
return Optional.ofNullable(m.get(key));
});
}

@Override
public void clearCache() {
injectBindingCache.clear();
}
}
Loading

0 comments on commit 8fc97ab

Please sign in to comment.