Skip to content

Commit

Permalink
add support for assisted inject (#59)
Browse files Browse the repository at this point in the history
* add failing test

* add assistedInject

* first working version, but need to support multiple injectionPoint

* set up test for multiple factory functions

* support ability to return multiple injection points from InjectionPointExtractor

* bump version and update CHANGELOG

* remove unused imports

* add shared variable for guice version

* add spacing for better readability

* remove unused imports

* fix CHANGELOG message

* remove manual version bump and CHANGELOG update

* BREAKING CHANGE: InjectionPointExtractor will now return Iterable<InjectionPoint>

Co-authored-by: Harry <85480431+harrylevick@users.noreply.github.com>
  • Loading branch information
ryuichi7 and harrylevick committed Sep 21, 2021
1 parent 8363802 commit 4c5681d
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 15 deletions.
21 changes: 21 additions & 0 deletions prop-all/src/test/java/io/pleo/prop/PropTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.PrivateModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import io.pleo.prop.objects.MyAssistedInjectFactoryModule;
import io.pleo.prop.objects.MyAssistedInjectFactoryModuleMultiple;
import org.junit.Test;
import org.mockito.Mockito;

Expand Down Expand Up @@ -195,6 +198,24 @@ public void inline_provider_support() {
injector.getInstance(InjectedObject.class);
}

@Test
public void assisted_inject_support() {
Injector injector = createInjector(binder -> {
binder.install(new FactoryModuleBuilder().build(MyAssistedInjectFactoryModule.class));
});

injector.getInstance(MyAssistedInjectFactoryModule.class);
}

@Test
public void assisted_inject_support_multiple_factory_functions() {
Injector injector = createInjector(binder -> {
binder.install(new FactoryModuleBuilder().build(MyAssistedInjectFactoryModuleMultiple.class));
});

injector.getInstance(MyAssistedInjectFactoryModuleMultiple.class);
}

private Injector createInjector(Module... modules) {
AutoPropModule autoPropModule = new AutoPropModule("io.pleo",
Arrays.asList(modules),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.pleo.prop.objects;

import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import io.pleo.prop.core.Prop;

import javax.inject.Named;

public class MyAssistedInjectFactoryImp {
private final Prop<String> prop;
private final String assistedArg;

@Inject
public MyAssistedInjectFactoryImp(
@Named("io.pleo.test.prop3") Prop<String> prop,
@Assisted String assistedArg
) {
this.prop = prop;
this.assistedArg = assistedArg;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.pleo.prop.objects;

import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import io.pleo.prop.core.Prop;

import javax.inject.Named;

public class MyAssistedInjectFactoryImp2 {
private final Prop<String> prop;
private final Integer assistedArg;

@Inject
public MyAssistedInjectFactoryImp2(
@Named("io.pleo.test.prop4") Prop<String> prop,
@Assisted Integer assistedArg
) {
this.prop = prop;
this.assistedArg = assistedArg;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package io.pleo.prop.objects;

public interface MyAssistedInjectFactoryModule {
public MyAssistedInjectFactoryImp create(String assistedArg);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.pleo.prop.objects;

public interface MyAssistedInjectFactoryModuleMultiple {
public MyAssistedInjectFactoryImp create(String assistedArg);
public MyAssistedInjectFactoryImp2 create(Integer assistedArg);
}
5 changes: 4 additions & 1 deletion prop-guice/build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
description = 'Guice integration for Pleo Prop'

def guiceVersion = '5.0.1'

dependencies {
api project(':prop-core')
api 'com.google.inject:guice:5.0.1'
api "com.google.inject:guice:$guiceVersion"
api "com.google.inject.extensions:guice-assistedinject:$guiceVersion"
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package io.pleo.prop.guice.internal;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.function.Predicate;

import com.google.inject.ConfigurationException;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.AssistedInjectBinding;
import com.google.inject.assistedinject.AssistedInjectTargetVisitor;
import com.google.inject.assistedinject.AssistedMethod;
import com.google.inject.spi.DefaultBindingTargetVisitor;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.LinkedKeyBinding;
Expand All @@ -16,8 +20,11 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class InjectionPointExtractor extends DefaultBindingTargetVisitor<Object, InjectionPoint> implements
ProvidesMethodTargetVisitor<Object, InjectionPoint> {
public class InjectionPointExtractor extends DefaultBindingTargetVisitor<Object, Iterable<InjectionPoint>> implements
ProvidesMethodTargetVisitor<Object, Iterable<InjectionPoint>>,
AssistedInjectTargetVisitor<Object, Iterable<InjectionPoint>>
{

private static final Logger logger = LoggerFactory.getLogger(InjectionPointExtractor.class);
private final Predicate<TypeLiteral<?>> filter;

Expand All @@ -26,26 +33,41 @@ public InjectionPointExtractor(Predicate<TypeLiteral<?>> filter) {
}

@Override
public InjectionPoint visit(UntargettedBinding<?> untargettedBinding) {
return getInjectionPointForKey(untargettedBinding.getKey());
public Iterable<InjectionPoint> visit(UntargettedBinding<?> untargettedBinding) {
return Arrays.asList(getInjectionPointForKey(untargettedBinding.getKey()));
}

@Override
public Iterable<InjectionPoint> visit(AssistedInjectBinding<?> assistedInjectBinding) {
Collection<InjectionPoint> injectionPoints = new ArrayList<>();

for (AssistedMethod assistedMethod : assistedInjectBinding.getAssistedMethods()) {
try {
injectionPoints.add(InjectionPoint.forConstructorOf(assistedMethod.getImplementationType()));
} catch (ConfigurationException e) {
logger.info("Skipping assistedMethod type {}: {}", assistedMethod.getImplementationType(), e.getMessage());
}
}

return injectionPoints;
}

@Override
public InjectionPoint visit(LinkedKeyBinding<?> linkedKeyBinding) {
return getInjectionPointForKey(linkedKeyBinding.getLinkedKey());
public Iterable<InjectionPoint> visit(LinkedKeyBinding<?> linkedKeyBinding) {
return Arrays.asList(getInjectionPointForKey(linkedKeyBinding.getLinkedKey()));
}

@Override
public InjectionPoint visit(ProviderKeyBinding<?> providerKeyBinding) {
return getInjectionPointForKey(providerKeyBinding.getProviderKey());
public Iterable<InjectionPoint> visit(ProviderKeyBinding<?> providerKeyBinding) {
return Arrays.asList(getInjectionPointForKey(providerKeyBinding.getProviderKey()));
}

@Override
public InjectionPoint visit(ProvidesMethodBinding<?> providesMethodBinding) {
public Iterable<InjectionPoint> visit(ProvidesMethodBinding<?> providesMethodBinding) {
TypeLiteral<?> type = TypeLiteral.get(providesMethodBinding.getEnclosingInstance().getClass());
if(filter.test(type)){
try {
return InjectionPoint.forMethod(providesMethodBinding.getMethod(),type);
return Arrays.asList(InjectionPoint.forMethod(providesMethodBinding.getMethod(),type));
} catch (ConfigurationException e) {
logger.info("Skipping key {}: {}", providesMethodBinding, e.getMessage());
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

import com.google.common.base.Strings;
import com.google.inject.Binding;
import com.google.inject.Key;
Expand All @@ -24,7 +23,6 @@
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.PrivateElements;
import com.google.inject.spi.ProviderLookup;

import io.pleo.prop.core.Default;
import io.pleo.prop.core.Prop;
import io.pleo.prop.core.internal.ParserFactory;
Expand Down Expand Up @@ -75,6 +73,20 @@ public <T> Map<Key<Prop<?>>, PropResult> visit(ProviderLookup<T> providerLookup)
return extractProps(providerLookup.getDependency().getInjectionPoint());
}

private Map<Key<Prop<?>>, PropResult> extractProps(Iterable<InjectionPoint> injectionPoints) {
if (injectionPoints == null) {
return new HashMap<>();
}

Map<Key<Prop<?>>, PropResult> mappings = new HashMap<>();

for (InjectionPoint injectionPoint : injectionPoints) {
mappings.putAll(extractProps(injectionPoint));
}

return mappings;
}

private Map<Key<Prop<?>>, PropResult> extractProps(InjectionPoint injectionPoint) {
if (injectionPoint == null) {
return new HashMap<>();
Expand Down

0 comments on commit 4c5681d

Please sign in to comment.