Skip to content

Commit

Permalink
Add an Injector#getAllMembersInjectorInjectionPoints method.
Browse files Browse the repository at this point in the history
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=241190415
  • Loading branch information
mpoletti authored and ronshapiro committed Apr 8, 2019
1 parent 70552b0 commit a6293fb
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 0 deletions.
27 changes: 27 additions & 0 deletions core/src/com/google/inject/Injector.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package com.google.inject;

import com.google.common.collect.ListMultimap;
import com.google.inject.spi.Element;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.TypeConverterBinding;
import java.lang.annotation.Annotation;
import java.util.List;
Expand Down Expand Up @@ -269,7 +271,32 @@ public interface Injector {
* <p>The returned list does not include elements inherited from a {@link #getParent() parent
* injector}, should one exist.
*
* <p>The returned list is immutable; it contains only the elements that were present when {@link
* #getElements} was invoked. Subsequent calls may return a list with additional elements.
*
* <p>The returned list does not include data inherited from a {@link #getParent() parent
* injector}, should one exist.
*
* <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
*
* @since 5.0
*/
List<Element> getElements();

/**
* Returns the injection points created for calls to {@link #getMembersInjector} (either directly
* or indirectly, e.g. through {@link #injectMembers}.
*
* <p>This excludes any injection points from elements (which are accessible from each element via
* the SPI), unless {@link #getMembersInjector} or {@link #injectMembers} were also called for the
* same key.
*
* <p>The returned multimap does not include data inherited from a {@link #getParent() parent
* injector}, should one exist.
*
* <p>This method is part of the Guice SPI and is intended for use by tools and extensions.
*
* @since 5.0
*/
ListMultimap<TypeLiteral<?>, InjectionPoint> getAllMembersInjectorInjectionPoints();
}
15 changes: 15 additions & 0 deletions core/src/com/google/inject/internal/FailableCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Map;

/**
* Lazily creates (and caches) values for keys. If creating the value fails (with errors), an
Expand Down Expand Up @@ -62,4 +65,16 @@ public V get(K key, Errors errors) throws ErrorsException {
boolean remove(K key) {
return delegate.asMap().remove(key) != null;
}

Map<K, V> asMap() {
return Maps.transformValues(
Maps.filterValues(
ImmutableMap.copyOf(delegate.asMap()),
resultOrError -> !(resultOrError instanceof Errors)),
resultOrError -> {
@SuppressWarnings("unchecked") // create returned a non-error result, so this is safe
V result = (V) resultOrError;
return result;
});
}
}
15 changes: 15 additions & 0 deletions core/src/com/google/inject/internal/InjectorImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
import com.google.common.base.Objects;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Sets;
import com.google.inject.Binder;
import com.google.inject.Binding;
Expand Down Expand Up @@ -128,6 +130,9 @@ enum JitLimitation {

Lookups lookups = new DeferredLookups(this);

/** The set of types passed to {@link #getMembersInjector} and {@link #injectMembers}. */
final Set<TypeLiteral<?>> userRequestedMembersInjectorTypes = Sets.newConcurrentHashSet();

InjectorImpl(InjectorImpl parent, State state, InjectorOptions injectorOptions) {
this.parent = parent;
this.state = state;
Expand Down Expand Up @@ -984,6 +989,14 @@ public List<Element> getElements() {
return elements.build();
}

@Override
public ListMultimap<TypeLiteral<?>, InjectionPoint> getAllMembersInjectorInjectionPoints() {
return ImmutableListMultimap.copyOf(
Multimaps.filterKeys(
membersInjectorStore.getAllInjectionPoints(),
userRequestedMembersInjectorTypes::contains));
}

/** Returns parameter injectors, or {@code null} if there are no parameters. */
SingleParameterInjector<?>[] getParametersInjectors(List<Dependency<?>> parameters, Errors errors)
throws ErrorsException {
Expand Down Expand Up @@ -1038,6 +1051,8 @@ public void injectMembers(Object instance) {
@Override
public <T> MembersInjector<T> getMembersInjector(TypeLiteral<T> typeLiteral) {
checkNotNull(typeLiteral, "typeLiteral");
userRequestedMembersInjectorTypes.add(typeLiteral);

Errors errors = new Errors(typeLiteral);
try {
return membersInjectorStore.get(typeLiteral, errors);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.inject.internal;

import com.google.common.collect.ListMultimap;
import com.google.inject.Binding;
import com.google.inject.Injector;
import com.google.inject.Key;
Expand All @@ -28,6 +29,7 @@
import com.google.inject.internal.util.Stopwatch;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.Element;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.TypeConverterBinding;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
Expand Down Expand Up @@ -312,6 +314,11 @@ public List<Element> getElements() {
return delegateInjector.getElements();
}

@Override
public ListMultimap<TypeLiteral<?>, InjectionPoint> getAllMembersInjectorInjectionPoints() {
return delegateInjector.getAllMembersInjectorInjectionPoints();
}

@Override
public <T> Provider<T> getProvider(Key<T> key) {
throw new UnsupportedOperationException(
Expand Down
11 changes: 11 additions & 0 deletions core/src/com/google/inject/internal/MembersInjectorStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

package com.google.inject.internal;

import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.inject.ConfigurationException;
Expand All @@ -26,6 +29,7 @@
import com.google.inject.spi.TypeListenerBinding;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

/**
Expand Down Expand Up @@ -133,4 +137,11 @@ ImmutableList<SingleMemberInjector> getInjectors(
}
return ImmutableList.copyOf(injectors);
}

ImmutableListMultimap<TypeLiteral<?>, InjectionPoint> getAllInjectionPoints() {
return cache.asMap().entrySet().stream()
.collect(
flatteningToImmutableListMultimap(
Entry::getKey, entry -> entry.getValue().getInjectionPoints().stream()));
}
}
77 changes: 77 additions & 0 deletions core/test/com/google/inject/spi/InjectorSpiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static com.google.common.truth.Truth.assertThat;

import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.inject.AbstractModule;
import com.google.inject.Asserts;
import com.google.inject.Binding;
Expand Down Expand Up @@ -317,4 +319,79 @@ private static class Baz {
@Inject
Provider<Foo> fooP;
}

public void testGetAllMembersInjectorInjectionPoints_injectMembers_returned() {
Injector injector =
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(Integer.class).toInstance(42);
bind(String.class).toInstance("bar");
}
});
injector.injectMembers(new ClassWithInjectableField("foo"));
Multimap<TypeLiteral<?>, InjectionPoint> injectionPoints =
injector.getAllMembersInjectorInjectionPoints();
TypeLiteral<ClassWithInjectableField> expectedTypeLiteral =
TypeLiteral.get(ClassWithInjectableField.class);
assertThat(injectionPoints.keySet()).containsExactly(expectedTypeLiteral);
Key<?> actualDependencyKey =
Iterables.getOnlyElement(
Iterables.getOnlyElement(injectionPoints.get(expectedTypeLiteral))
.getDependencies())
.getKey();
assertEquals(Key.get(Integer.class), actualDependencyKey);
}

public void testGetAllMembersInjectorInjectionPoints_getInstance() {
Injector injector =
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(Integer.class).toInstance(42);
bind(String.class).toInstance("bar");
}
});
injector.getInstance(ClassWithInjectableField.class);
Multimap<TypeLiteral<?>, InjectionPoint> injectionPoints =
injector.getAllMembersInjectorInjectionPoints();
assertThat(injectionPoints).isEmpty();
}

public void testGetAllMembersInjectorInjectionPoints_getInstanceAndInjectMembers() {
Injector injector =
Guice.createInjector(
new AbstractModule() {
@Override
protected void configure() {
bind(Integer.class).toInstance(42);
bind(String.class).toInstance("bar");
}
});
injector.injectMembers(new ClassWithInjectableField("foo"));
injector.getInstance(ClassWithInjectableField.class);
Multimap<TypeLiteral<?>, InjectionPoint> injectionPoints =
injector.getAllMembersInjectorInjectionPoints();
TypeLiteral<ClassWithInjectableField> expectedTypeLiteral =
TypeLiteral.get(ClassWithInjectableField.class);
assertThat(injectionPoints.keySet()).containsExactly(expectedTypeLiteral);
Key<?> actualDependencyKey =
Iterables.getOnlyElement(
Iterables.getOnlyElement(injectionPoints.get(expectedTypeLiteral))
.getDependencies())
.getKey();
assertEquals(Key.get(Integer.class), actualDependencyKey);
}

private static class ClassWithInjectableField {

@Inject
ClassWithInjectableField(String name) {}

@Inject private Integer instanceField;

@Inject private static Double staticField;
}
}

0 comments on commit a6293fb

Please sign in to comment.