Implement subcomponent factory validation using the new binding graph model.

Extract the ComponentNode implementation into a class in dagger.internal.codegen with some nonpublic properties.

Add the ability to report an error for subcomponent factory methods.

Delete the now-empty BindingGraphValidator.

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=201379680
diff --git a/java/dagger/internal/codegen/BUILD b/java/dagger/internal/codegen/BUILD
index 2006fb3..45597b0 100644
--- a/java/dagger/internal/codegen/BUILD
+++ b/java/dagger/internal/codegen/BUILD
@@ -128,6 +128,7 @@
         "BindingVariableNamer.java",  # needed by FrameworkField
         "BindsTypeChecker.java",
         "ComponentDescriptor.java",
+        "ComponentNodeImpl.java",
         "ComponentRequirement.java",
         "ComponentTreeTraverser.java",
         "ConfigurationAnnotations.java",  # Uses ModuleDescriptors
@@ -164,7 +165,6 @@
     srcs = [
         "AnyBindingMethodValidator.java",
         "BindingDeclarationFormatter.java",
-        "BindingGraphValidator.java",
         "BindingMethodProcessingStep.java",
         "BindingMethodValidator.java",
         "BindsInstanceProcessingStep.java",
@@ -209,6 +209,7 @@
         "MissingBindingValidation.java",
         "NonNullableRequestForNullableBindingValidation.java",
         "ProvisionDependencyOnProducerBindingValidation.java",
+        "SubcomponentFactoryMethodValidation.java",
         "Validation.java",
     ],
     tags = ["maven:merged"],
diff --git a/java/dagger/internal/codegen/BindingGraphConverter.java b/java/dagger/internal/codegen/BindingGraphConverter.java
index f35b5ce..cb8f7e1 100644
--- a/java/dagger/internal/codegen/BindingGraphConverter.java
+++ b/java/dagger/internal/codegen/BindingGraphConverter.java
@@ -18,7 +18,6 @@
 
 import static dagger.internal.codegen.DaggerStreams.instancesOf;
 import static dagger.model.BindingGraphProxies.childFactoryMethodEdge;
-import static dagger.model.BindingGraphProxies.componentNode;
 import static dagger.model.BindingGraphProxies.dependencyEdge;
 
 import com.google.common.collect.ImmutableSet;
@@ -74,10 +73,8 @@
       ComponentNode grandparentComponent = parentComponent;
       parentComponent = currentComponent;
       currentComponent =
-          componentNode(
-              componentTreePath().toComponentPath(),
-              graph.componentDescriptor().entryPoints(),
-              graph.componentDescriptor().scopes());
+          ComponentNodeImpl.create(
+              componentTreePath().toComponentPath(), graph.componentDescriptor());
 
       network.addNode(currentComponent);
 
diff --git a/java/dagger/internal/codegen/BindingGraphPlugins.java b/java/dagger/internal/codegen/BindingGraphPlugins.java
index f21abac..9b2a38b 100644
--- a/java/dagger/internal/codegen/BindingGraphPlugins.java
+++ b/java/dagger/internal/codegen/BindingGraphPlugins.java
@@ -22,6 +22,7 @@
 import static java.lang.annotation.ElementType.METHOD;
 import static java.lang.annotation.ElementType.PARAMETER;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static javax.tools.Diagnostic.Kind.ERROR;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Maps;
@@ -110,4 +111,9 @@
     }
     return diagnosticKinds.build();
   }
+
+  /** Returns {@code true} if any errors are reported by any of the plugins for {@code graph}. */
+  boolean pluginsReportErrors(BindingGraph graph) {
+    return visitGraph(graph).contains(ERROR);
+  }
 }
diff --git a/java/dagger/internal/codegen/BindingGraphValidationModule.java b/java/dagger/internal/codegen/BindingGraphValidationModule.java
index e1137c4..7ed179f 100644
--- a/java/dagger/internal/codegen/BindingGraphValidationModule.java
+++ b/java/dagger/internal/codegen/BindingGraphValidationModule.java
@@ -75,4 +75,9 @@
   @Validation
   BindingGraphPlugin providerDependsOnProducer(
       ProvisionDependencyOnProducerBindingValidation validation);
+
+  @Binds
+  @IntoSet
+  @Validation
+  BindingGraphPlugin subcomponentFactoryMethod(SubcomponentFactoryMethodValidation validation);
 }
diff --git a/java/dagger/internal/codegen/BindingGraphValidator.java b/java/dagger/internal/codegen/BindingGraphValidator.java
deleted file mode 100644
index 3881439..0000000
--- a/java/dagger/internal/codegen/BindingGraphValidator.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2015 The Dagger Authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dagger.internal.codegen;
-
-import static com.google.auto.common.MoreTypes.asDeclared;
-import static com.google.auto.common.MoreTypes.asExecutable;
-import static com.google.auto.common.MoreTypes.asTypeElements;
-import static dagger.internal.codegen.ComponentRequirement.Kind.MODULE;
-import static dagger.internal.codegen.Util.componentCanMakeNewInstances;
-import static dagger.internal.codegen.Util.reentrantComputeIfAbsent;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toSet;
-
-import com.google.common.collect.ImmutableSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import javax.inject.Inject;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.DeclaredType;
-import javax.lang.model.type.ExecutableType;
-
-/** Reports errors in the shape of the binding graph. */
-final class BindingGraphValidator {
-
-  private final DaggerTypes types;
-
-  @Inject
-  BindingGraphValidator(DaggerTypes types) {
-    this.types = types;
-  }
-
-  ValidationReport<TypeElement> validate(BindingGraph graph) {
-    ComponentValidation validation = new ComponentValidation(graph);
-    validation.traverseComponents();
-    return validation.buildReport();
-  }
-
-  private final class ComponentValidation extends ComponentTreeTraverser {
-    final BindingGraph rootGraph;
-    final Map<ComponentDescriptor, ValidationReport.Builder<TypeElement>> reports =
-        new LinkedHashMap<>();
-
-    ComponentValidation(BindingGraph rootGraph) {
-      super(rootGraph);
-      this.rootGraph = rootGraph;
-    }
-
-    /** Returns a report that contains all validation messages found during traversal. */
-    ValidationReport<TypeElement> buildReport() {
-      ValidationReport.Builder<TypeElement> report =
-          ValidationReport.about(rootGraph.componentType());
-      reports.values().forEach(subreport -> report.addSubreport(subreport.build()));
-      return report.build();
-    }
-
-    /** Returns the report builder for a (sub)component. */
-    private ValidationReport.Builder<TypeElement> report(ComponentDescriptor component) {
-      return reentrantComputeIfAbsent(
-          reports,
-          component,
-          descriptor -> ValidationReport.about(descriptor.componentDefinitionType()));
-    }
-
-    @Override
-    protected void visitSubcomponentFactoryMethod(
-        BindingGraph graph, BindingGraph parent, ExecutableElement factoryMethod) {
-      Set<TypeElement> missingModules =
-          graph
-              .componentRequirements()
-              .stream()
-              .filter(componentRequirement -> componentRequirement.kind().equals(MODULE))
-              .map(ComponentRequirement::typeElement)
-              .filter(
-                  moduleType ->
-                      !subgraphFactoryMethodParameters(parent, factoryMethod).contains(moduleType))
-              .filter(moduleType -> !componentCanMakeNewInstances(moduleType))
-              .collect(toSet());
-      if (!missingModules.isEmpty()) {
-        report(parent.componentDescriptor())
-            .addError(
-                String.format(
-                    "%s requires modules which have no visible default constructors. "
-                        + "Add the following modules as parameters to this method: %s",
-                    graph.componentType().getQualifiedName(),
-                    missingModules.stream().map(Object::toString).collect(joining(", "))),
-                factoryMethod);
-      }
-    }
-
-    private ImmutableSet<TypeElement> subgraphFactoryMethodParameters(
-        BindingGraph parent, ExecutableElement childFactoryMethod) {
-      DeclaredType componentType = asDeclared(parent.componentType().asType());
-      ExecutableType factoryMethodType =
-          asExecutable(types.asMemberOf(componentType, childFactoryMethod));
-      return asTypeElements(factoryMethodType.getParameterTypes());
-    }
-  }
-}
diff --git a/java/dagger/internal/codegen/BuilderValidator.java b/java/dagger/internal/codegen/BuilderValidator.java
index 2d6906f..f69806d 100644
--- a/java/dagger/internal/codegen/BuilderValidator.java
+++ b/java/dagger/internal/codegen/BuilderValidator.java
@@ -162,7 +162,7 @@
       builder.addError(msgs.missingBuildMethod(), subject);
     }
 
-    // Note: there's more validation in BindingGraphValidator:
+    // Note: there's more validation in ComponentDescriptorValidator:
     // - to make sure the setter methods mirror the deps
     // - to make sure each type or key is set by only one method
 
diff --git a/java/dagger/internal/codegen/ComponentNodeImpl.java b/java/dagger/internal/codegen/ComponentNodeImpl.java
new file mode 100644
index 0000000..7b624aa
--- /dev/null
+++ b/java/dagger/internal/codegen/ComponentNodeImpl.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableSet;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.model.ComponentPath;
+import dagger.model.DependencyRequest;
+import dagger.model.Scope;
+
+/** An implementation of {@link ComponentNode} that also exposes the {@link ComponentDescriptor}. */
+@AutoValue
+abstract class ComponentNodeImpl implements ComponentNode {
+  static ComponentNode create(
+      ComponentPath componentPath, ComponentDescriptor componentDescriptor) {
+    return new AutoValue_ComponentNodeImpl(componentPath, componentDescriptor);
+  }
+
+  @Override
+  public ImmutableSet<DependencyRequest> entryPoints() {
+    return componentDescriptor().entryPoints();
+  }
+
+  @Override
+  public ImmutableSet<Scope> scopes() {
+    return componentDescriptor().scopes();
+  }
+
+  abstract ComponentDescriptor componentDescriptor();
+
+  @Override
+  public final String toString() {
+    return componentPath().toString();
+  }
+}
diff --git a/java/dagger/internal/codegen/ComponentProcessingStep.java b/java/dagger/internal/codegen/ComponentProcessingStep.java
index 9c744d9..0b5ba26 100644
--- a/java/dagger/internal/codegen/ComponentProcessingStep.java
+++ b/java/dagger/internal/codegen/ComponentProcessingStep.java
@@ -17,7 +17,6 @@
 package dagger.internal.codegen;
 
 import static javax.lang.model.util.ElementFilter.typesIn;
-import static javax.tools.Diagnostic.Kind.ERROR;
 
 import com.google.auto.common.BasicAnnotationProcessor.ProcessingStep;
 import com.google.auto.common.MoreElements;
@@ -48,7 +47,6 @@
   private final ComponentValidator componentValidator;
   private final BuilderValidator builderValidator;
   private final ComponentDescriptorValidator componentDescriptorValidator;
-  private final BindingGraphValidator bindingGraphValidator;
   private final ComponentDescriptor.Factory componentDescriptorFactory;
   private final BindingGraphFactory bindingGraphFactory;
   private final ComponentGenerator componentGenerator;
@@ -62,7 +60,6 @@
       ComponentValidator componentValidator,
       BuilderValidator builderValidator,
       ComponentDescriptorValidator componentDescriptorValidator,
-      BindingGraphValidator bindingGraphValidator,
       ComponentDescriptor.Factory componentDescriptorFactory,
       BindingGraphFactory bindingGraphFactory,
       ComponentGenerator componentGenerator,
@@ -73,7 +70,6 @@
     this.componentValidator = componentValidator;
     this.builderValidator = builderValidator;
     this.componentDescriptorValidator = componentDescriptorValidator;
-    this.bindingGraphValidator = bindingGraphValidator;
     this.componentDescriptorFactory = componentDescriptorFactory;
     this.bindingGraphFactory = bindingGraphFactory;
     this.componentGenerator = componentGenerator;
@@ -154,14 +150,9 @@
   }
 
   private boolean isValid(BindingGraph bindingGraph) {
-    ValidationReport<TypeElement> graphReport = bindingGraphValidator.validate(bindingGraph);
-    graphReport.printMessagesTo(messager);
-
     dagger.model.BindingGraph modelGraph = bindingGraphConverter.convert(bindingGraph);
-    if (validationPlugins.visitGraph(modelGraph).contains(ERROR) || !graphReport.isClean()) {
-      return false;
-    }
-    return !spiPlugins.visitGraph(modelGraph).contains(ERROR);
+    return !validationPlugins.pluginsReportErrors(modelGraph)
+        && !spiPlugins.pluginsReportErrors(modelGraph);
   }
 
   private void generateComponent(BindingGraph bindingGraph) {
diff --git a/java/dagger/internal/codegen/DaggerElements.java b/java/dagger/internal/codegen/DaggerElements.java
index 314c26d..92bf2a3 100644
--- a/java/dagger/internal/codegen/DaggerElements.java
+++ b/java/dagger/internal/codegen/DaggerElements.java
@@ -32,6 +32,8 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.graph.Traverser;
 import dagger.Reusable;
 import java.io.Writer;
 import java.lang.annotation.Annotation;
@@ -74,6 +76,17 @@
     this(processingEnv.getElementUtils(), processingEnv.getTypeUtils());
   }
 
+  /**
+   * Returns {@code true} if {@code encloser} is equal to {@code enclosed} or recursively encloses
+   * it.
+   */
+  static boolean elementEncloses(TypeElement encloser, Element enclosed) {
+    return Iterables.contains(GET_ENCLOSED_ELEMENTS.breadthFirst(encloser), enclosed);
+  }
+
+  private static final Traverser<Element> GET_ENCLOSED_ELEMENTS =
+      Traverser.forTree(Element::getEnclosedElements);
+
   ImmutableSet<ExecutableElement> getUnimplementedMethods(TypeElement type) {
     return FluentIterable.from(getLocalAndInheritedMethods(type, types, elements))
         .filter(hasModifiers(ABSTRACT))
diff --git a/java/dagger/internal/codegen/DiagnosticReporterFactory.java b/java/dagger/internal/codegen/DiagnosticReporterFactory.java
index 62f940e..1b295b7 100644
--- a/java/dagger/internal/codegen/DiagnosticReporterFactory.java
+++ b/java/dagger/internal/codegen/DiagnosticReporterFactory.java
@@ -18,6 +18,7 @@
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.collect.Lists.asList;
+import static dagger.internal.codegen.DaggerElements.elementEncloses;
 import static dagger.internal.codegen.DaggerElements.elementToString;
 import static dagger.internal.codegen.DaggerGraphs.shortestPath;
 
@@ -29,6 +30,7 @@
 import com.google.errorprone.annotations.FormatMethod;
 import dagger.model.BindingGraph;
 import dagger.model.BindingGraph.BindingNode;
+import dagger.model.BindingGraph.ChildFactoryMethodEdge;
 import dagger.model.BindingGraph.ComponentNode;
 import dagger.model.BindingGraph.DependencyEdge;
 import dagger.model.BindingGraph.Edge;
@@ -151,6 +153,26 @@
           diagnosticKind, dependencyEdge, formatMessage(messageFormat, firstArg, moreArgs));
     }
 
+    @Override
+    public void reportSubcomponentFactoryMethod(
+        Diagnostic.Kind diagnosticKind,
+        ChildFactoryMethodEdge childFactoryMethodEdge,
+        String message) {
+      printMessage(
+          diagnosticKind, new StringBuilder(message), childFactoryMethodEdge.factoryMethod());
+    }
+
+    @Override
+    public void reportSubcomponentFactoryMethod(
+        Diagnostic.Kind diagnosticKind,
+        ChildFactoryMethodEdge childFactoryMethodEdge,
+        String messageFormat,
+        Object firstArg,
+        Object... moreArgs) {
+      reportSubcomponentFactoryMethod(
+          diagnosticKind, childFactoryMethodEdge, formatMessage(messageFormat, firstArg, moreArgs));
+    }
+
     private String formatMessage(String messageFormat, Object firstArg, Object[] moreArgs) {
       return String.format(messageFormat, asList(firstArg, moreArgs).toArray());
     }
@@ -209,22 +231,18 @@
       if (!component.equals(graph.rootComponentNode())) {
         appendComponentPath(messageBuilder, component);
       }
-
-      // TODO(ronshapiro): should we create a HashSet out of getEnclosedElements() so we don't
-      // need to do an O(n) contains() each time?
-      if (rootComponent.getEnclosedElements().contains(entryPointElement)) {
-        printMessage(diagnosticKind, messageBuilder, entryPointElement);
-      } else {
-        printMessage(
-            diagnosticKind,
-            insertBracketPrefix(messageBuilder, elementToString(entryPointElement)),
-            rootComponent);
-      }
+      printMessage(diagnosticKind, messageBuilder, entryPointElement);
     }
 
     private void printMessage(
         Diagnostic.Kind diagnosticKind, StringBuilder message, Element elementToReport) {
       reportedDiagnosticKinds.add(diagnosticKind);
+      // TODO(ronshapiro): should we create a HashSet out of elementEncloses() so we don't
+      // need to do an O(n) contains() each time?
+      if (!elementEncloses(rootComponent, elementToReport)) {
+        insertBracketPrefix(message, elementToString(elementToReport));
+        elementToReport = rootComponent;
+      }
       messager.printMessage(diagnosticKind, insertBracketPrefix(message, plugin), elementToReport);
     }
 
diff --git a/java/dagger/internal/codegen/SubcomponentFactoryMethodValidation.java b/java/dagger/internal/codegen/SubcomponentFactoryMethodValidation.java
new file mode 100644
index 0000000..f958c95
--- /dev/null
+++ b/java/dagger/internal/codegen/SubcomponentFactoryMethodValidation.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2018 The Dagger Authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package dagger.internal.codegen;
+
+import static com.google.auto.common.MoreTypes.asDeclared;
+import static com.google.auto.common.MoreTypes.asExecutable;
+import static com.google.auto.common.MoreTypes.asTypeElements;
+import static com.google.common.collect.Sets.union;
+import static dagger.internal.codegen.DaggerStreams.instancesOf;
+import static dagger.internal.codegen.DaggerStreams.toImmutableSet;
+import static dagger.internal.codegen.Util.componentCanMakeNewInstances;
+import static javax.tools.Diagnostic.Kind.ERROR;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+import dagger.model.BindingGraph;
+import dagger.model.BindingGraph.ChildFactoryMethodEdge;
+import dagger.model.BindingGraph.ComponentNode;
+import dagger.spi.BindingGraphPlugin;
+import dagger.spi.DiagnosticReporter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import javax.inject.Inject;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
+
+/** Reports an error if a subcomponent factory method is missing required modules. */
+final class SubcomponentFactoryMethodValidation implements BindingGraphPlugin {
+
+  private final DaggerTypes types;
+  private final Map<ComponentNode, Set<TypeElement>> inheritedModulesCache = new HashMap<>();
+
+  @Inject
+  SubcomponentFactoryMethodValidation(DaggerTypes types) {
+    this.types = types;
+  }
+
+  @Override
+  public String pluginName() {
+    return "Dagger/SubcomponentFactoryMethodMissingModule";
+  }
+
+  @Override
+  public void visitGraph(BindingGraph bindingGraph, DiagnosticReporter diagnosticReporter) {
+    bindingGraph
+        .edges()
+        .stream()
+        .flatMap(instancesOf(ChildFactoryMethodEdge.class))
+        .forEach(
+            edge -> {
+              ImmutableSet<TypeElement> missingModules = findMissingModules(edge, bindingGraph);
+              if (!missingModules.isEmpty()) {
+                reportMissingModuleParameters(
+                    edge, missingModules, bindingGraph, diagnosticReporter);
+              }
+            });
+  }
+
+  private ImmutableSet<TypeElement> findMissingModules(
+      ChildFactoryMethodEdge edge, BindingGraph graph) {
+    ImmutableSet<TypeElement> factoryMethodParameters =
+        subgraphFactoryMethodParameters(edge, graph);
+    ComponentNode child = (ComponentNode) graph.incidentNodes(edge).target();
+    SetView<TypeElement> modulesOwnedByChild = ownedModules(child, graph);
+    return graph
+        .bindingNodes()
+        .stream()
+        // bindings owned by child
+        .filter(node -> node.componentPath().equals(child.componentPath()))
+        // that require a module instance
+        .filter(
+            node ->
+                node.binding() instanceof ContributionBinding
+                    && ((ContributionBinding) node.binding()).requiresModuleInstance())
+        .map(node -> node.binding().contributingModule().get())
+        .distinct()
+        // module owned by child
+        .filter(module -> modulesOwnedByChild.contains(module))
+        // module not in the method parameters
+        .filter(module -> !factoryMethodParameters.contains(module))
+        // module doesn't have an accessible no-arg constructor
+        .filter(moduleType -> !componentCanMakeNewInstances(moduleType))
+        .collect(toImmutableSet());
+  }
+
+  private ImmutableSet<TypeElement> subgraphFactoryMethodParameters(
+      ChildFactoryMethodEdge edge, BindingGraph bindingGraph) {
+    ComponentNode parent = (ComponentNode) bindingGraph.incidentNodes(edge).source();
+    DeclaredType parentType = asDeclared(parent.componentPath().currentComponent().asType());
+    ExecutableType factoryMethodType =
+        asExecutable(types.asMemberOf(parentType, edge.factoryMethod()));
+    return asTypeElements(factoryMethodType.getParameterTypes());
+  }
+
+  private SetView<TypeElement> ownedModules(ComponentNode component, BindingGraph graph) {
+    return Sets.difference(
+        ((ComponentNodeImpl) component).componentDescriptor().transitiveModuleTypes(),
+        inheritedModules(component, graph));
+  }
+
+  private Set<TypeElement> inheritedModules(ComponentNode component, BindingGraph graph) {
+    return Util.reentrantComputeIfAbsent(
+        inheritedModulesCache, component, uncachedInheritedModules(graph));
+  }
+
+  private Function<ComponentNode, Set<TypeElement>> uncachedInheritedModules(BindingGraph graph) {
+    return componentNode ->
+        componentNode.componentPath().atRoot()
+            ? ImmutableSet.of()
+            : graph
+                .componentNode(componentNode.componentPath().parent())
+                .map(parent -> union(ownedModules(parent, graph), inheritedModules(parent, graph)))
+                .get();
+  }
+
+  private void reportMissingModuleParameters(
+      ChildFactoryMethodEdge edge,
+      ImmutableSet<TypeElement> missingModules,
+      BindingGraph graph,
+      DiagnosticReporter diagnosticReporter) {
+    diagnosticReporter.reportSubcomponentFactoryMethod(
+        ERROR,
+        edge,
+        "%s requires modules which have no visible default constructors. "
+            + "Add the following modules as parameters to this method: %s",
+        graph.incidentNodes(edge).target().componentPath().currentComponent().getQualifiedName(),
+        Joiner.on(", ").join(missingModules));
+  }
+}
diff --git a/java/dagger/model/BindingGraph.java b/java/dagger/model/BindingGraph.java
index 9ed3158..7e49da6 100644
--- a/java/dagger/model/BindingGraph.java
+++ b/java/dagger/model/BindingGraph.java
@@ -340,28 +340,16 @@
    * A <b>component node</b> in the graph. Every entry point {@linkplain DependencyEdge dependency
    * edge}'s source node is a component node for the component containing the entry point.
    */
-  @AutoValue
-  public abstract static class ComponentNode implements Node {
-    static ComponentNode create(
-        ComponentPath componentPath,
-        ImmutableSet<DependencyRequest> entryPoints,
-        ImmutableSet<Scope> scopes) {
-      return new AutoValue_BindingGraph_ComponentNode(componentPath, entryPoints, scopes);
-    }
+  public interface ComponentNode extends Node {
 
     /** The component represented by this node. */
     @Override
-    public abstract ComponentPath componentPath();
+    ComponentPath componentPath();
 
     /** The entry points on this component. */
-    public abstract ImmutableSet<DependencyRequest> entryPoints();
+    ImmutableSet<DependencyRequest> entryPoints();
 
     /** The scopes declared on this component. */
-    public abstract ImmutableSet<Scope> scopes();
-
-    @Override
-    public final String toString() {
-      return componentPath().toString();
-    }
+    ImmutableSet<Scope> scopes();
   }
 }
diff --git a/java/dagger/model/BindingGraphProxies.java b/java/dagger/model/BindingGraphProxies.java
index a5e24ff..9c3b601 100644
--- a/java/dagger/model/BindingGraphProxies.java
+++ b/java/dagger/model/BindingGraphProxies.java
@@ -16,10 +16,8 @@
 
 package dagger.model;
 
-import com.google.common.collect.ImmutableSet;
 import com.google.common.graph.Network;
 import dagger.model.BindingGraph.ChildFactoryMethodEdge;
-import dagger.model.BindingGraph.ComponentNode;
 import dagger.model.BindingGraph.DependencyEdge;
 import dagger.model.BindingGraph.Edge;
 import dagger.model.BindingGraph.MissingBindingNode;
@@ -44,14 +42,6 @@
     return MissingBindingNode.create(component, key);
   }
 
-  /** Creates a new {@link ComponentNode}. */
-  public static ComponentNode componentNode(
-      ComponentPath component,
-      ImmutableSet<DependencyRequest> entryPoints,
-      ImmutableSet<Scope> scopes) {
-    return ComponentNode.create(component, entryPoints, scopes);
-  }
-
   /** Creates a new {@link DependencyEdge}. */
   public static DependencyEdge dependencyEdge(
       DependencyRequest dependencyRequest, boolean entryPoint) {
diff --git a/java/dagger/model/ComponentPath.java b/java/dagger/model/ComponentPath.java
index 5ef7b41..7225950 100644
--- a/java/dagger/model/ComponentPath.java
+++ b/java/dagger/model/ComponentPath.java
@@ -62,6 +62,16 @@
   }
 
   /**
+   * Returns this path's parent path.
+   *
+   * @throws IllegalStateException if the current graph is the {@linkplain #atRoot() root component}
+   */
+  public final ComponentPath parent() {
+    checkState(!atRoot());
+    return create(components().subList(0, components().size() - 1));
+  }
+
+  /**
    * Returns {@code true} if the {@linkplain #currentComponent()} current component} is the
    * {@linkplain #rootComponent()} root component}.
    */
diff --git a/java/dagger/spi/DiagnosticReporter.java b/java/dagger/spi/DiagnosticReporter.java
index 05e1d3f..d4b0d7a 100644
--- a/java/dagger/spi/DiagnosticReporter.java
+++ b/java/dagger/spi/DiagnosticReporter.java
@@ -19,6 +19,7 @@
 import com.google.errorprone.annotations.FormatMethod;
 import dagger.model.BindingGraph;
 import dagger.model.BindingGraph.BindingNode;
+import dagger.model.BindingGraph.ChildFactoryMethodEdge;
 import dagger.model.BindingGraph.ComponentNode;
 import dagger.model.BindingGraph.DependencyEdge;
 import javax.tools.Diagnostic;
@@ -82,4 +83,19 @@
       String messageFormat,
       Object firstArg,
       Object... moreArgs);
+
+  /** Reports a diagnostic for a subcomponent factory method. */
+  void reportSubcomponentFactoryMethod(
+      Diagnostic.Kind diagnosticKind,
+      ChildFactoryMethodEdge childFactoryMethodEdge,
+      String message);
+
+  /** Reports a diagnostic for a subcomponent factory method. */
+  @FormatMethod
+  void reportSubcomponentFactoryMethod(
+      Diagnostic.Kind diagnosticKind,
+      ChildFactoryMethodEdge childFactoryMethodEdge,
+      String messageFormat,
+      Object firstArg,
+      Object... moreArgs);
 }