aboutsummaryrefslogtreecommitdiff
path: root/extensions/grapher
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/grapher')
-rw-r--r--extensions/grapher/src/com/google/inject/grapher/GraphingVisitor.java66
-rw-r--r--extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java19
-rw-r--r--extensions/grapher/test/com/google/inject/grapher/GraphingVisitorTest.java72
-rw-r--r--extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java29
-rw-r--r--extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java9
5 files changed, 113 insertions, 82 deletions
diff --git a/extensions/grapher/src/com/google/inject/grapher/GraphingVisitor.java b/extensions/grapher/src/com/google/inject/grapher/GraphingVisitor.java
index 86531c09..2ae71cea 100644
--- a/extensions/grapher/src/com/google/inject/grapher/GraphingVisitor.java
+++ b/extensions/grapher/src/com/google/inject/grapher/GraphingVisitor.java
@@ -18,14 +18,16 @@ package com.google.inject.grapher;
import com.google.common.base.Nullable;
import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
import com.google.inject.Binding;
import com.google.inject.Inject;
+import com.google.inject.Key;
+import com.google.inject.Provider;
import com.google.inject.spi.BindingTargetVisitor;
import com.google.inject.spi.ConstructorBinding;
import com.google.inject.spi.ConvertedConstantBinding;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.ExposedBinding;
+import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.LinkedKeyBinding;
@@ -34,9 +36,9 @@ import com.google.inject.spi.ProviderInstanceBinding;
import com.google.inject.spi.ProviderKeyBinding;
import com.google.inject.spi.UntargettedBinding;
+import java.lang.reflect.Member;
import java.util.Collection;
import java.util.List;
-import java.util.Set;
/**
* {@link BindingTargetVisitor} that adds nodes and edges to the graph based on
@@ -137,16 +139,11 @@ implements BindingTargetVisitor<Object, Void> {
* {@link Binding}, where the {@link Binding} is for an instance, rather than
* a class.
*/
- protected M newInstanceImplementationNode(Binding<?> binding, Object instance,
- Collection<InjectionPoint> injectionPoints) {
+ protected M newInstanceImplementationNode(Binding<?> binding, Object instance) {
M node = implementationNodeFactory.newImplementationNode(getInstanceNodeId(binding));
node.setSource(binding.getSource());
node.setInstance(instance);
- for (InjectionPoint injectionPoint : injectionPoints) {
- node.addMember(injectionPoint.getMember());
- }
-
return node;
}
@@ -167,43 +164,36 @@ implements BindingTargetVisitor<Object, Void> {
}
/**
- * Adds {@link DependencyEdge}s to the graph from the given
- * {@link ImplementationNode} to the {@link Key}s specified in the
- * {@link InjectionPoint}s.
+ * Adds {@link DependencyEdge}s to the graph for each of the provided
+ * {@link Dependency}s. These will be from the given node ID to the
+ * {@link Dependency}'s {@link Key}.
* <p>
- * Also adds edges for any {@link Dependency}s passed in that are not covered
- * in the set of {@link InjectionPoint}s.
+ * If a {@link Dependency} has an associated {@link InjectionPoint}, its
+ * member will be added to the given {@link ImplementationNode} and the edge
+ * will start at the {@link Member}.
*
* @see #newDependencyEdge(Object, InjectionPoint, Dependency)
*
* @param nodeId ID of the node that should be the tail of the
* {@link DependencyEdge}s.
- * @param injectionPoints {@link Collection} of {@link InjectionPoint}s on
- * the class or instance represented by the {@link ImplementationNode}.
+ * @param node An {@link ImplementationNode} to add {@link Member}s to.
* @param dependencies {@link Collection} of {@link Dependency}s from the
- * {@link Binding}. Some {@link Binding}s may have {@link Dependency}s
- * even if they do not have {@link InjectionPoint}s.
+ * {@link Binding}.
* @return A {@link Collection} of the {@link DependencyEdge}s that were
* added to the graph.
*/
- protected Collection<D> newDependencyEdges(K nodeId, Collection<InjectionPoint> injectionPoints,
+ protected Collection<D> newDependencyEdges(K nodeId, M node,
Collection<Dependency<?>> dependencies) {
List<D> edges = Lists.newArrayList();
- // Set to keep track of which of the given Dependencies is not duplicated
- // by the InjectionPoints.
- Set<Dependency<?>> remainingDependencies = Sets.newHashSet(dependencies);
-
- for (InjectionPoint injectionPoint : injectionPoints) {
- for (Dependency<?> dependency : injectionPoint.getDependencies()) {
- D edge = newDependencyEdge(nodeId, injectionPoint, dependency);
- edges.add(edge);
- remainingDependencies.remove(dependency);
+ for (Dependency<?> dependency : dependencies) {
+ InjectionPoint injectionPoint = dependency.getInjectionPoint();
+
+ if (injectionPoint != null) {
+ node.addMember(injectionPoint.getMember());
}
- }
- for (Dependency<?> dependency : remainingDependencies) {
- D edge = newDependencyEdge(nodeId, null, dependency);
+ D edge = newDependencyEdge(nodeId, injectionPoint, dependency);
edges.add(edge);
}
@@ -241,9 +231,8 @@ implements BindingTargetVisitor<Object, Void> {
* @see #newDependencyEdges(ImplementationNode, Collection, Collection)
*/
public Void visitConstructor(ConstructorBinding<?> binding) {
- newClassImplementationNode(binding, binding.getInjectionPoints());
- newDependencyEdges(getClassNodeId(binding), binding.getInjectionPoints(),
- binding.getDependencies());
+ M node = newClassImplementationNode(binding, binding.getInjectionPoints());
+ newDependencyEdges(getClassNodeId(binding), node, binding.getDependencies());
return null;
}
@@ -299,9 +288,8 @@ implements BindingTargetVisitor<Object, Void> {
newBindingEdge(getClassNodeId(binding), getInstanceNodeId(binding),
BindingEdge.Type.NORMAL);
- newInstanceImplementationNode(binding, binding.getInstance(), binding.getInjectionPoints());
- newDependencyEdges(getInstanceNodeId(binding), binding.getInjectionPoints(),
- binding.getDependencies());
+ M node = newInstanceImplementationNode(binding, binding.getInstance());
+ newDependencyEdges(getInstanceNodeId(binding), node, binding.getDependencies());
return null;
}
@@ -353,10 +341,8 @@ implements BindingTargetVisitor<Object, Void> {
newInterfaceNode(binding);
newBindingEdge(getClassNodeId(binding), getInstanceNodeId(binding), BindingEdge.Type.PROVIDER);
- newInstanceImplementationNode(binding, binding.getProviderInstance(),
- binding.getInjectionPoints());
- newDependencyEdges(getInstanceNodeId(binding), binding.getInjectionPoints(),
- binding.getDependencies());
+ M node = newInstanceImplementationNode(binding, binding.getProviderInstance());
+ newDependencyEdges(getInstanceNodeId(binding), node, binding.getDependencies());
return null;
}
diff --git a/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java b/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java
index f364b803..c4af901b 100644
--- a/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java
+++ b/extensions/grapher/src/com/google/inject/grapher/TransitiveDependencyVisitor.java
@@ -25,7 +25,6 @@ import com.google.inject.spi.ConvertedConstantBinding;
import com.google.inject.spi.Dependency;
import com.google.inject.spi.ExposedBinding;
import com.google.inject.spi.HasDependencies;
-import com.google.inject.spi.InjectionPoint;
import com.google.inject.spi.InstanceBinding;
import com.google.inject.spi.LinkedKeyBinding;
import com.google.inject.spi.ProviderBinding;
@@ -47,30 +46,22 @@ import java.util.Set;
public class TransitiveDependencyVisitor
implements BindingTargetVisitor<Object, Collection<Key<?>>> {
- // TODO(phopkins): Remove InjectionPoints when issue 298 is fixed.
- private Collection<Key<?>> visitHasDependencies(HasDependencies hasDependencies,
- Collection<InjectionPoint> injectionPoints) {
+ private Collection<Key<?>> visitHasDependencies(HasDependencies hasDependencies) {
Set<Key<?>> dependencies = Sets.newHashSet();
for (Dependency<?> dependency : hasDependencies.getDependencies()) {
dependencies.add(dependency.getKey());
}
- for (InjectionPoint injectionPoint : injectionPoints) {
- for (Dependency<?> dependency : injectionPoint.getDependencies()) {
- dependencies.add(dependency.getKey());
- }
- }
-
return dependencies;
}
public Collection<Key<?>> visitConstructor(ConstructorBinding<?> binding) {
- return visitHasDependencies(binding, binding.getInjectionPoints());
+ return visitHasDependencies(binding);
}
public Collection<Key<?>> visitConvertedConstant(ConvertedConstantBinding<?> binding) {
- return visitHasDependencies(binding, ImmutableSet.<InjectionPoint>of());
+ return visitHasDependencies(binding);
}
public Collection<Key<?>> visitExposed(ExposedBinding<?> binding) {
@@ -79,7 +70,7 @@ implements BindingTargetVisitor<Object, Collection<Key<?>>> {
}
public Collection<Key<?>> visitInstance(InstanceBinding<?> binding) {
- return visitHasDependencies(binding, binding.getInjectionPoints());
+ return visitHasDependencies(binding);
}
public Collection<Key<?>> visitLinkedKey(LinkedKeyBinding<?> binding) {
@@ -91,7 +82,7 @@ implements BindingTargetVisitor<Object, Collection<Key<?>>> {
}
public Collection<Key<?>> visitProviderInstance(ProviderInstanceBinding<?> binding) {
- return visitHasDependencies(binding, binding.getInjectionPoints());
+ return visitHasDependencies(binding);
}
public Collection<Key<?>> visitProviderKey(ProviderKeyBinding<?> binding) {
diff --git a/extensions/grapher/test/com/google/inject/grapher/GraphingVisitorTest.java b/extensions/grapher/test/com/google/inject/grapher/GraphingVisitorTest.java
index 4f3201d4..d46d8e88 100644
--- a/extensions/grapher/test/com/google/inject/grapher/GraphingVisitorTest.java
+++ b/extensions/grapher/test/com/google/inject/grapher/GraphingVisitorTest.java
@@ -17,22 +17,26 @@
package com.google.inject.grapher;
import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
-import com.google.inject.Provides;
+import com.google.inject.Key;
import com.google.inject.spi.ConstructorBinding;
+import com.google.inject.spi.Dependency;
+import com.google.inject.spi.HasDependencies;
import com.google.inject.spi.InjectionPoint;
-import com.google.inject.spi.ProviderInstanceBinding;
+import com.google.inject.spi.InstanceBinding;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import junit.framework.TestCase;
@@ -80,36 +84,52 @@ public class GraphingVisitorTest extends TestCase {
}
public void testNewDependencies_withInjectionPoints() throws Exception {
+ @SuppressWarnings("unchecked")
+ ImplementationNode<String> node = recordMock(createMock(ImplementationNode.class));
+
+ node.addMember(Obj.class.getDeclaredField("string"));
+ expectLastCall();
+ node.addMember(Obj.class.getDeclaredField("integer"));
+ expectLastCall();
+ node.addMember(Obj.class.getDeclaredField("bool"));
+ expectLastCall();
+ node.addMember(Obj.class.getDeclaredMethod("setInteger", Integer.class));
+ expectLastCall();
+
replayAll();
- ConstructorBinding<?> binding = (ConstructorBinding<?>) createInjector().getBinding(Obj.class);
+ Injector injector = Guice.createInjector(new ClassModule());
+ ConstructorBinding<?> binding = (ConstructorBinding<?>) injector.getBinding(Obj.class);
- Collection<DependencyEdge<String>> edges = graphingVisitor.newDependencyEdges("",
- binding.getInjectionPoints(), binding.getDependencies());
+ Collection<DependencyEdge<String>> edges = graphingVisitor.newDependencyEdges("", node,
+ binding.getDependencies());
- assertEquals("There should be three edges, from the InjectionPoints", 3, edges.size());
+ assertEquals("There should be four edges, from the three fields plus the method",
+ 4, edges.size());
verifyAll();
}
public void testNewDependencies_withDependencies() throws Exception {
+ @SuppressWarnings("unchecked")
+ ImplementationNode<String> node = recordMock(createMock(ImplementationNode.class));
+ // No members should be added to the node, since the stated dependencies
+ // have no associated {@link InjectionPoint}s.
+
replayAll();
- ProviderInstanceBinding<?> binding =
- (ProviderInstanceBinding<?>) createInjector().getBinding(Intf.class);
+ Injector injector = Guice.createInjector(new ClassModule(), new InstanceModule());
+ InstanceBinding<?> binding = (InstanceBinding<?>) injector.getBinding(Obj.class);
- Collection<DependencyEdge<String>> edges = graphingVisitor.newDependencyEdges("",
- ImmutableList.<InjectionPoint>of(), binding.getDependencies());
+ Collection<DependencyEdge<String>> edges = graphingVisitor.newDependencyEdges("", node,
+ binding.getDependencies());
- assertEquals("There should be three edges, from the parameter Dependencies", 3, edges.size());
+ assertEquals("One edge should be created, for the one stated Integer dependency",
+ 1, edges.size());
verifyAll();
}
- private Injector createInjector() {
- return Guice.createInjector(new TestModule());
- }
-
private void replayAll() {
for (Object mock : mocks) {
replay(mock);
@@ -132,25 +152,31 @@ public class GraphingVisitorTest extends TestCase {
}
}
- private static class TestModule extends AbstractModule {
+ private static class ClassModule extends AbstractModule {
@Override
protected void configure() {
bind(String.class).toInstance("String");
bind(Integer.class).toInstance(Integer.valueOf(8));
bind(Boolean.class).toInstance(Boolean.TRUE);
}
+ }
- @Provides
- public Intf provideIntf(String string, Integer integer, Boolean bool) {
- return null;
+ private static class InstanceModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(Obj.class).toInstance(new Obj());
}
}
- private static interface Intf {}
-
- private static class Obj {
+ private static class Obj implements HasDependencies {
@Inject String string;
@Inject Integer integer;
@Inject Boolean bool;
+
+ @Inject void setInteger(Integer integer) {}
+
+ public Set<Dependency<?>> getDependencies() {
+ return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(Integer.class)));
+ }
}
}
diff --git a/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java b/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java
index 721e109f..2ef17958 100644
--- a/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java
+++ b/extensions/grapher/test/com/google/inject/grapher/TransitiveDependencyVisitorTest.java
@@ -83,6 +83,16 @@ public class TransitiveDependencyVisitorTest extends TestCase {
assertDependencies(dependencies, Key.get(A.class), Key.get(D.class));
}
+ public void testVisitInstance_instanceHasDependencies() {
+ Binding<?> binding = getBinding(Key.get(Interface.class), new HasDependenciesModule());
+ Collection<Key<?>> dependencies = visitor.visitInstance(
+ (InstanceBinding<?>) binding);
+
+ // Dependencies should only be on the stated
+ // HasDependencies#getDependencies() values
+ assertDependencies(dependencies, Key.get(G.class));
+ }
+
public void testVisitLinkedKey() {
Binding<?> binding = getBinding(Key.get(Interface.class), new LinkedKeyModule());
Collection<Key<?>> dependencies = visitor.visitLinkedKey((LinkedKeyBinding<?>) binding);
@@ -105,7 +115,7 @@ public class TransitiveDependencyVisitorTest extends TestCase {
(ProviderInstanceBinding<?>) binding);
// Dependencies will only be on the field- and method-injected classes.
- assertDependencies(dependencies, Key.get(E.class), Key.get(F.class), Key.get(G.class));
+ assertDependencies(dependencies, Key.get(E.class), Key.get(F.class));
}
public void testVisitProviderKey() {
@@ -147,8 +157,7 @@ public class TransitiveDependencyVisitorTest extends TestCase {
@Inject void setD(D d) {}
}
- private static class ConstructedClassProvider
- implements Provider<ConstructedClass>, HasDependencies {
+ private static class ConstructedClassProvider implements Provider<ConstructedClass> {
@Inject E e;
ConstructedClassProvider() {}
@Inject ConstructedClassProvider(A a, B b, C c) {}
@@ -157,12 +166,17 @@ public class TransitiveDependencyVisitorTest extends TestCase {
public ConstructedClass get() {
return null;
}
+ }
+ private static class HasDependenciesClass implements Interface, HasDependencies {
+ @Inject A a;
+ @Inject B b;
+
public Set<Dependency<?>> getDependencies() {
return ImmutableSet.<Dependency<?>>of(Dependency.get(Key.get(G.class)));
}
}
-
+
private static class ConvertedConstantModule extends AbstractModule {
@Override
protected void configure() {
@@ -190,6 +204,13 @@ public class TransitiveDependencyVisitorTest extends TestCase {
bind(ConstructedClass.class).toProvider(new ConstructedClassProvider());
}
}
+
+ private static class HasDependenciesModule extends AbstractModule {
+ @Override
+ protected void configure() {
+ bind(Interface.class).toInstance(new HasDependenciesClass());
+ }
+ }
private static class ProviderKeyModule extends AbstractModule {
@Override
diff --git a/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java b/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java
index 6ac11048..9ad9745b 100644
--- a/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java
+++ b/extensions/grapher/test/com/google/inject/grapher/demo/PinballParts.java
@@ -16,4 +16,11 @@
package com.google.inject.grapher.demo;
-class PinballParts {}
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+class PinballParts {
+ // Shows up as an injection point on an instance. We use a Provider so that
+ // it doesn't have to be satisfied when the Injector is created.
+ @Inject Provider<DocBrown> salvager;
+}